Version 2.8.0-dev.9.0

Merge commit '76b18c455e2caa71215c4c63c41d0abbef6d67ff' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c6992a..b769056 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,8 +22,15 @@
   options. Previously setting a socket options would be ignored and getting a
   socket option would return `null`.
 
+#### `dart:mirrors`
+
+* Added `MirrorSystem.neverType`.
+
 ### Dart VM
 
+* Added `Dart_TypeDynamic`, `Dart_TypeVoid` and `Dart_TypeNever`. Type dynamic
+  can no longer by reached by `Dart_GetType(dart:core, dynamic)`.
+
 ### Tools
 
 #### Dart Dev Compiler (DDC)
@@ -42,6 +49,10 @@
   `allowInterop`. This behavior was always enforced by `dart2js`, but was not
   enforced consistently in `ddc`. It will now be enforced in both.
 * JS interop classes with an index operator are now static errors.
+* Removed the `dart:mirrors` library from the SDK. Use of this library on the
+  web has been unsupported and prevented by the Dart build systems since Dart
+  v2.0.0. All known exception cases have been cleaned up. This change makes DDC
+  and dart2js now issue a compile-time error directly as well.
 
  [announcement]: https://github.com/dart-lang/sdk/issues/38994
 
@@ -53,6 +64,10 @@
   forgiving. Corresponding type parameter bounds now only need to be mutual
   subtypes rather than structurally equal up to renaming of bound type variables
   and equating all top types.
+* Removed the `dart:mirrors` library from the SDK. Use of this library on the
+  web has been unsupported and prevented by the Dart build systems since Dart
+  v2.0.0. All known exception cases have been cleaned up. This change makes DDC
+  and dart2js now issue a compile-time error directly as well.
 
 #### Linter
 
diff --git a/DEPS b/DEPS
index d261291..dd3edac 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": "5a3388d1f79cc3c61f9cdc1b3eaaa405bd62c882",
+  "co19_rev": "def1183bacc28f008db4fdd3d0442ed05f1889f8",
   "co19_2_rev": "368bfa9e877a2df003547f64bb17e30596af10c7",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
@@ -469,7 +469,7 @@
     "packages": [
       {
         "package": "dart/cfe/benchmark_data",
-        "version": "sha1sum:4640fa0bff40726392748d1ad3147e5dd0324ea2",
+        "version": "sha1sum:5b6e6dfa33b85c733cab4e042bf46378984d1544",
       }
     ],
     "dep_type": "cipd",
@@ -479,7 +479,7 @@
     "packages": [
       {
         "package": "dart/cfe/dart2js_dills",
-        "version": "binary_version:38",
+        "version": "binary_version:39",
       }
     ],
     "dep_type": "cipd",
diff --git a/README.md b/README.md
index e0d4071..aac57f6 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
   * **Fast on all platforms**:
   Compile to ARM & x64 machine code for mobile,  desktop, and backend. Or compile to JavaScript for the web
 
-Dart has flexible compiler technology lets you run Dart code in different ways,
+Dart's flexible compiler technology lets you run Dart code in different ways,
 depending on your target platform and goals:
 
   * **Dart Native**: For programs targeting devices (mobile, desktop, server, and more),
diff --git a/docs/language/informal/README.md b/docs/language/informal/README.md
index cd6c9f0..ae9b49e 100644
--- a/docs/language/informal/README.md
+++ b/docs/language/informal/README.md
@@ -1,24 +1,16 @@
-### This directory contains feature specifications.
+## Background material about features
 
-**Note**: This directory contains older feature specifications, new ones
-should be submitted to the language repository
-[here](https://github.com/dart-lang/language).
+This directory contains background material only. Consult the 
+[language specification](https://dart.dev/guides/language/spec)
+and the 
+[language repository](https://github.com/dart-lang/language)
+for current information.
 
-The existing feature specifications in this directory will have their status
-updated as we proceed, and in particular each of them will become 'background'
-material as it is integrated into the language specification. When all feature
-specifications in this directory (that is, all other files than this one) have
-become background material, this directory will serve only as documentation for
-the process whereby each feature was designed and the associated motivation.
-
-That said, the following section contains a few words about what a feature
-specification is, and how it can be used.
-
-### What is a Feature Specification?
+### What is a feature specification?
 
 In order to move faster and get better feedback, we implement and iterate on
-language changes before the full official specification has been written. Still,
-the implementers need *something* to go on.
+language changes before the full official specification has been written.
+Still, the implementers need *something* to go on.
 
 For that, the language team writes _feature specifications_. These are
 intended to be precise enough for a good faith implementer to correctly
@@ -27,3 +19,15 @@
 expect the extra processing to give rise to additional clarifications and
 corrections, which means that a feature specification is expected to be 
 _nearly_ as complete and correct as the language specification.
+
+### Feature specifications in this directory
+
+This directory contains older feature specifications, newer ones can be
+found in, respectively should be submitted to, the language repository
+[here](https://github.com/dart-lang/language).
+
+The status of every feature specification in this directory is that it is
+background material, and the contents has been integrated into the language
+specification. Consequently, these feature specifications can only be used
+as a source of informal background information. Precise rules about the
+features should be looked up in the language specification.
diff --git a/docs/language/informal/extreme-upper-lower-bounds.md b/docs/language/informal/extreme-upper-lower-bounds.md
index 982dc4d..a2e7c69 100644
--- a/docs/language/informal/extreme-upper-lower-bounds.md
+++ b/docs/language/informal/extreme-upper-lower-bounds.md
@@ -2,7 +2,7 @@
 
 **Owner**: eernst@
 
-**Status**: Implemented.
+**Status**: Background material, normative language now in dartLangSpec.tex.
 
 **Version**: 0.2 (2018-05-22)
 
diff --git a/docs/language/informal/implicit-creation.md b/docs/language/informal/implicit-creation.md
index dfa46e1..903ff40 100644
--- a/docs/language/informal/implicit-creation.md
+++ b/docs/language/informal/implicit-creation.md
@@ -4,7 +4,7 @@
 
 Version: 0.7 (2018-04-10)
 
-Status: Implemented.
+Status: Background material, normative language now in dartLangSpec.tex.
 
 **This document** is an informal specification of the *implicit creation*
 feature. **The feature** adds support for omitting some occurrences of the
diff --git a/docs/language/informal/instantiate-to-bound.md b/docs/language/informal/instantiate-to-bound.md
index e54f47d..dafcf2d 100644
--- a/docs/language/informal/instantiate-to-bound.md
+++ b/docs/language/informal/instantiate-to-bound.md
@@ -4,7 +4,7 @@
 
 **Version**: 0.10 (2018-10-31)
 
-**Status**: Implemented.
+**Status**: Background material, normative language now in dartLangSpec.tex.
 
 Based on [this description](https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397) by leafp@.
 
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 d69a1b5..95cc7fb 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -6130,6 +6130,57 @@
     message: r"""Can't spread a value with static type Null.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateNonNullableNotAssignedError = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Non-nullable variable '#name' must be assigned before it can be used.""",
+    withArguments: _withArgumentsNonNullableNotAssignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeNonNullableNotAssignedError =
+    const Code<Message Function(String name)>(
+  "NonNullableNotAssignedError",
+  templateNonNullableNotAssignedError,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonNullableNotAssignedError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNonNullableNotAssignedError,
+      message:
+          """Non-nullable variable '${name}' must be assigned before it can be used.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateNonNullableNotAssignedWarning =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Non-nullable variable '#name' is used before it's assigned.""",
+        withArguments: _withArgumentsNonNullableNotAssignedWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeNonNullableNotAssignedWarning =
+    const Code<Message Function(String name)>(
+        "NonNullableNotAssignedWarning", templateNonNullableNotAssignedWarning,
+        severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonNullableNotAssignedWarning(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNonNullableNotAssignedWarning,
+      message:
+          """Non-nullable variable '${name}' is used before it's assigned.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeNonNullableOptOut = messageNonNullableOptOut;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/main.dart
new file mode 100644
index 0000000..067684a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/main.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.
+
+// @dart=2.6
+
+/*library: nnbd=false*/
+
+import 'opt_in.dart';
+
+/*class: LegacyClass:Class,LegacyClass,Object*/
+class LegacyClass extends Class {
+  /*member: LegacyClass.method:int* Function(int*)**/
+}
+
+/*class: LegacyInterface:Interface,LegacyInterface,Object*/
+abstract class LegacyInterface implements Interface {
+  /*member: LegacyInterface.method:int* Function(int*)**/
+}
+
+/*class: LegacySubClass:Class,Interface,LegacyClass,LegacyInterface,LegacySubClass,Object*/
+class LegacySubClass extends LegacyClass implements LegacyInterface {
+  /*member: LegacySubClass.method:int* Function(int*)**/
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/opt_in.dart
new file mode 100644
index 0000000..97729b5
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/member_from_opt_in/opt_in.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.
+
+/*library: nnbd=true*/
+
+/*class: Class:Class,Object*/
+class Class {
+  /*member: Class.method:int! Function(int?)!*/
+  int method(int? i) => i ?? 0;
+}
+
+/*class: Interface:Interface,Object*/
+abstract class Interface {
+  /*member: Interface.method:int? Function(int!)!*/
+  int? method(int i);
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.dart
new file mode 100644
index 0000000..0ffb78c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/norm_supertypes.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.
+
+/*library: nnbd=true*/
+
+import 'dart:async';
+
+/*class: A:A<T>,Object*/
+class A<T> {}
+
+/*class: Foo:A<FutureOr<T?>!>,Foo<T!,S!>,Object*/
+class Foo<T extends S, S extends Never> implements A<FutureOr<T?>> {}
+
+/*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*/
+class Hest extends Foo implements Bar {}
+
+/*class: Fisk:A<Future<Null>?>,Bar,Baz,Fisk,Object*/
+class Fisk extends Bar implements Baz {}
+
+/*class: Naebdyr:A<Future<Null>?>,Baz,Foo<Never,Never>,Naebdyr,Object*/
+class Naebdyr extends Baz implements Foo {}
+
+main() {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/main.dart
new file mode 100644
index 0000000..984da7d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/main.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: nnbd=false*/
+
+// @dart=2.6
+
+import 'opt_in.dart';
+
+/*class: B2:A,B2,C2,Object*/
+abstract class B2 extends A implements C2 {
+  /*member: B2.method:int* Function(int*,{dynamic optional})**/
+
+  /*member: B2.noSuchMethod:dynamic Function(Invocation*)**/
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+/*class: C2:C2,Object*/
+abstract class C2 {
+  /*member: C2.method:int* Function(int*,{dynamic optional})**/
+  int method(int i, {optional});
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/opt_in.dart
new file mode 100644
index 0000000..e7a737c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/nsm_from_opt_in/opt_in.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.
+
+/*library: nnbd=true*/
+
+/*class: A:A,Object*/
+class A {
+  /*member: A.method:int! Function(int?)!*/
+  int method(int? i) => i ?? 0;
+}
+
+/*class: B1:A,B1,C1,Object*/
+abstract class B1 extends A implements C1 {
+  /*member: B1.method:int! Function(int?,{dynamic optional})!*/
+
+  /*member: B1.noSuchMethod:dynamic Function(Invocation!)!*/
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+/*class: C1:C1,Object*/
+abstract class C1 {
+  /*member: C1.method:int! Function(int?,{dynamic optional})!*/
+  int method(int? i, {optional});
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/core.dart
index 38f91c1..f91b62b 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/core.dart
@@ -14,6 +14,10 @@
   const Object();
 
   bool operator ==(Object other) => true;
+
+  noSuchMethod(Invocation invocation) => null;
+
+  String toString() => '';
 }
 
 /*class: Null:Null,Object*/
@@ -61,3 +65,6 @@
 
 /*class: Type:Object,Type*/
 class Type {}
+
+/*class: Invocation:Invocation,Object*/
+class Invocation {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/opt_out.dart
index 1d7d8a1..374b04b8 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/opt_out.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_equals/opt_out.dart
@@ -8,38 +8,77 @@
 
 /*class: Class1:Class1,Object*/
 class Class1 {
+  /*member: Class1.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class1.toString:String* Function()**/
+
   /*member: Class1.==:bool! Function(dynamic)**/
   operator ==(other) => true;
 }
 
 /*class: Class2a:Class2a,Object*/
 abstract class Class2a {
+  /*member: Class2a.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class2a.toString:String* Function()**/
+
   /*member: Class2a.==:bool* Function(Object*)**/
   bool operator ==(Object other);
 }
 
 /*class: Class2b:Class2a,Class2b,Object*/
 class Class2b extends Class2a {
+  /*member: Class2b.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class2b.toString:String* Function()**/
   /*member: Class2b.==:bool* Function(Object*)**/
 }
 
 /*class: Class3a:Class3a,Object*/
 class Class3a {
+  /*member: Class3a.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class3a.toString:String* Function()**/
   /*member: Class3a.==:bool* Function(Object*)**/
 }
 
 /*class: Class3b:Class3a,Class3b,Object*/
 abstract class Class3b extends Class3a {
+  /*member: Class3b.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class3b.toString:String* Function()**/
+
   /*member: Class3b.==:bool* Function(Object*)**/
   bool operator ==(Object other);
 }
 
 /*class: Class3c:Class3a,Class3b,Class3c,Object*/
 class Class3c extends Class3b {
+  /*member: Class3c.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Class3c.toString:String* Function()**/
   /*member: Class3c.==:bool* Function(Object*)**/
 }
 
 /*class: Foo:Foo,Object*/
 class Foo extends /*error: TypeNotFound*/ Unresolved {
+  /*member: Foo.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Foo.toString:String* Function()**/
   /*member: Foo.==:bool* Function(Object*)**/
 }
+
+/*class: A:A,Object*/
+abstract class A {
+  /*member: A.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: A.==:bool* Function(Object*)**/
+
+  /*member: A.toString:String* Function({bool* withNullability})**/
+  String toString({bool withNullability = false}) {
+    return '';
+  }
+}
+
+/*class: B:A,B,Object*/
+abstract class B implements A {
+  /*member: B.toString:String* Function({bool* withNullability})**/
+  /*member: B.==:bool* Function(Object*)**/
+
+  /*member: B.noSuchMethod:dynamic Function(Invocation*)**/
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/README.md b/pkg/analysis_server/lib/src/edit/nnbd_migration/README.md
index 0b96245..2e622fa 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/README.md
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/README.md
@@ -1,7 +1,7 @@
 # Null Safety Migration Tooling
 
 Note: the null safety migration tooling and workflow is in a very early state;
-this doc will be updated as the steps and workflow are simplified. 
+this doc will be updated as the steps and workflow are simplified.
 
 ## Background
 
@@ -37,12 +37,12 @@
     - non-nullable
 ```
 - run `pub get` for the package (and, verify that the
-  `.dart_tool/package_config.json` file was created) 
+  `.dart_tool/package_config.json` file was created)
 
 Then, run the migration tool from the top-level of the package directory:
 
 ```
-<sdk-repo>/xcodebuild/ReleaseX64/dart <sdk-repo>/pkg/dartfix/bin/dartfix.dart  upgrade sdk --sdk=<sdk-repo>/xcodebuild/ReleaseX64NNBD/dart-sdk/ .
+<sdk-repo>/xcodebuild/ReleaseX64/dart <sdk-repo>/pkg/dartfix/bin/dartfix.dart upgrade sdk --sdk=<sdk-repo>/xcodebuild/ReleaseX64NNBD/dart-sdk/ .
 ```
 
 The migration tool will run, print the proposed changes to the console,
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 5386501..1e20583 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
@@ -2,74 +2,14 @@
 // for details. All 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: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/resources/resources.g.dart'
     as resources;
-import 'package:mustache/mustache.dart' as mustache;
 import 'package:path/path.dart' as path;
 
-/// A mustache template for one library's instrumentation output.
-mustache.Template _template = mustache.Template(r'''
-<html>
-  <head>
-    <title>Non-nullable fix instrumentation report</title>
-    <script src="{{ highlightJsPath }}"></script>
-    <script>{{{ dartPageScript }}}</script>
-    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap">
-    <link rel="stylesheet" href="{{ highlightStylePath }}">
-    <style>{{{ dartPageStyle }}}</style>
-  </head>
-  <body>
-    <h1>Preview of NNBD migration</h1>
-    <h2 id="unit-name">&nbsp;</h2>
-    <div class="panels">
-    <div class="horizontal">
-    <div class="nav-panel">
-      <div class="nav-inner">
-        <p class="panel-heading">Navigation</p>
-        <p class="root">{{{ root }}}</p>
-        <div class="nav-tree"></div>
-      </div><!-- /nav-inner -->
-    </div><!-- /nav -->
-    '''
-    '<div class="content">'
-    '<div class="code">'
-    '{{! Compilation unit content is written here. }}'
-    '<p class="welcome">'
-    '{{! TODO(srawlins): More welcome text! }}'
-    'Select a source file on the left to preview the edits.'
-    '</p>'
-    '</div>'
-    '<div class="regions">'
-    '{{! The regions are then written again, overlaying the first copy of }}'
-    '{{! the content, to provide tooltips for modified regions. }}'
-    '</div><!-- /regions -->'
-    '<div class="footer"><em>Generated on {{ generationDate }}</em></div>'
-    '</div><!-- /content -->'
-    '''
-    <div class="info-panel">
-      <div class="panel-container">
-        <div class="edit-panel">
-          <p class="panel-heading">Edit info</p>
-          <div class="panel-content">
-            <p>
-            Click a modified region of code to see why the migration tool chose
-            to make the edit.
-            </p>
-          </div><!-- /panel-content -->
-        </div><!-- /edit-panel -->
-        <div class="edit-list">
-          <p class="panel-heading">Edits</p>
-          <div class="panel-content"></div>
-        </div><!-- /edit-list -->
-      </div><!-- /panel-container -->
-    </div><!-- /info-panel -->
-    </div><!-- /horizontal -->
-    </div><!-- /panels -->
-  </body>
-</html>''');
-
 /// Instrumentation display output for a library that was migrated to use
 /// non-nullable types.
 class InstrumentationRenderer {
@@ -89,14 +29,44 @@
 
   /// Builds an HTML view of the instrumentation information.
   String render() {
-    Map<String, dynamic> mustacheContext = {
+    Map<String, String> variables = {
       'root': migrationInfo.includedRoot,
       'dartPageScript': resources.migration_js,
       'dartPageStyle': resources.migration_css,
       'highlightJsPath': migrationInfo.highlightJsPath,
       'highlightStylePath': migrationInfo.highlightStylePath,
-      'generationDate': migrationInfo.migrationDate,
+      'sdkVersion': _dartSdkVersion,
     };
-    return _template.renderString(mustacheContext);
+
+    return substituteVariables(resources.index_html, variables);
   }
 }
+
+String substituteVariables(String content, Map<String, String> variables) {
+  for (String variable in variables.keys) {
+    String value = variables[variable];
+    content = content.replaceAll('{{ $variable }}', value);
+  }
+
+  return content;
+}
+
+String get _dartSdkVersion {
+  String version = Platform.version;
+
+  // Remove the build date and OS.
+  if (version.contains(' ')) {
+    version = version.substring(0, version.indexOf(' '));
+  }
+
+  // Convert a git hash to 8 chars.
+  // '2.8.0-edge.fd992e423ef69ece9f44bd3ac58fa2355b563212'
+  final RegExp versionRegExp = RegExp(r'^.*\.([0123456789abcdef]+)$');
+  RegExpMatch match = versionRegExp.firstMatch(version);
+  if (match != null && match.group(1).length == 40) {
+    String commit = match.group(1);
+    version = version.replaceAll(commit, commit.substring(0, 10));
+  }
+
+  return version;
+}
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 528e6bd..97f7b1b 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
@@ -47,10 +47,7 @@
   /// The filesystem root used to create relative paths for each unit.
   final String includedRoot;
 
-  final String migrationDate;
-
-  MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot)
-      : migrationDate = DateTime.now().toString();
+  MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot);
 
   /// The path to the highlight.pack.js script, relative to [unitInfo].
   String get highlightJsPath => PreviewSite.highlightJsPath;
@@ -63,21 +60,19 @@
   String computeName(UnitInfo unit) =>
       pathContext.relative(unit.path, from: includedRoot);
 
-  /// Generate mustache context for unit links.
   List<UnitLink> unitLinks() {
     List<UnitLink> links = [];
     for (UnitInfo unit in units) {
       int count = unit.fixRegions.length;
       links.add(UnitLink(
-          _pathTo(target: unit), path.split(computeName(unit)), count));
+          _pathTo(target: unit), pathContext.split(computeName(unit)), count));
     }
     return links;
   }
 
-  /// The path to [target], relative to [from].
-  String _pathTo({@required UnitInfo target}) {
-    return target.path;
-  }
+  /// The path to [target], as an HTTP URI path, using forward slash separators.
+  String _pathTo({@required UnitInfo target}) =>
+      '/' + pathContext.split(target.path).skip(1).join('/');
 }
 
 /// A location from or to which a user might want to navigate.
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
index 8b3464b..8fd1348 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
@@ -47,7 +47,7 @@
         {
           'type': 'file',
           'name': link.fileName,
-          'path': link.relativePath,
+          'path': pathContext.joinAll(link.pathParts),
           'href': link.url,
           'editCount': link.editCount,
         },
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 369b9da..5790a63 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
@@ -36,13 +36,14 @@
   String render() {
     var unitDir = pathContext.dirname(pathMapper.map(unitInfo.path));
 
-    Map<String, String> linkForTarget(NavigationTarget target) {
+    Map<String, dynamic> linkForTarget(NavigationTarget target) {
       String relativePath = _relativePathToTarget(target, unitDir);
       String targetUri = _uriForRelativePath(relativePath, target);
-      // TODO(brianwilkerson) Add the line number to the link text. This
-      //  will require that either the contents of all navigation targets
-      //  have been set or that line information has been saved.
-      return {'text': relativePath, 'href': targetUri};
+      return {
+        'text': relativePath,
+        'href': targetUri,
+        'line': target.line,
+      };
     }
 
     Map<String, String> linkForEdit(EditDetail 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
new file mode 100644
index 0000000..0ae6ea6
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
@@ -0,0 +1,57 @@
+<html>
+<head>
+    <title>Null Safety Preview</title>
+    <script src="{{ highlightJsPath }}"></script>
+    <script>{{ dartPageScript }}</script>
+    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap">
+    <link rel="stylesheet" href="{{ highlightStylePath }}">
+    <style>{{ dartPageStyle }}</style>
+</head>
+<body>
+<p class="root">{{ root }}</p>
+<header class="elevation-z4">
+    <h1>Proposed null safety changes</h1>
+    <h2 id="unit-name">&nbsp;</h2>
+</header>
+<div class="panels horizontal">
+    <div class="nav-panel">
+        <div class="nav-inner">
+            <div class="panel-heading">Project Files</div>
+            <div class="nav-tree"></div>
+        </div><!-- /nav-inner -->
+    </div><!-- /nav -->
+    <div class="content">
+        <div class="code">
+            <!-- Compilation unit content is written here. -->
+            <p class="welcome">
+                <!-- TODO(srawlins): More welcome text! -->
+                Select a source file on the left to preview the edits.
+            </p>
+        </div>
+        <div class="regions">
+            <!-- The regions are then written again, overlaying the first copy of -->
+            <!-- the content, to provide tooltips for modified regions. -->
+        </div><!-- /regions -->
+    </div><!-- /content -->
+    <div class="info-panel">
+        <div class="edit-list">
+            <div class="panel-heading">Proposed Edits</div>
+            <div class="panel-content"></div>
+        </div><!-- /edit-list -->
+        <div class="edit-panel">
+            <div class="panel-heading">Edit Details</div>
+            <div class="panel-content">
+                <p>See details about a proposed edit.</p>
+            </div><!-- /panel-content -->
+        </div><!-- /edit-panel -->
+    </div><!-- /info-panel -->
+</div><!-- /panels -->
+<footer>
+    <a target="_blank"
+       href="https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/lib/src/edit/nnbd_migration/README.md">Null
+        safety migration help</a>
+    <span class="wide"> </span>
+    <div>Based on {{ sdkVersion }}</div>
+</footer>
+</body>
+</html>
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 3963f24..da3c82c 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
@@ -3,54 +3,89 @@
 /* BSD-style license that can be found in the LICENSE file.                   */
 
 body {
-  background-color: black;
-  color: white;
-  font-family: 'Open Sans', sans-serif;
+  background-color: #12202f;
+  color: #ccc;
+  font-family: "Roboto", sans-serif;
+  font-size: 14px;
+  display: flex;
+  flex-direction: column;
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
   margin: 0;
   padding: 0;
+  overflow: hidden;
+}
+
+header {
+  background-color: #1c2834;
+  height: 48px;
+  padding-left: 24px;
+  align-items: center;
+  z-index: 4;
+}
+
+header h1,
+header h2 {
+  display: inline-block;
+  font-family: "Google Sans","Roboto",sans-serif;
+  font-weight: 400;
+  margin-right: 24px;
 }
 
 h1 {
-  font-size: 2.4em;
-  font-weight: 600;
-  margin: 8px 8px 0 8px;
+  font-size: 1.5em;
 }
 
-h2#unit-name {
+header h2 {
   font-size: 1.2em;
-  font-weight: 600;
-  margin: 8px 8px 0 8px;
+}
+
+footer {
+  color: #ccc;
+  background-color: #27323a;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 8px 24px;
+}
+
+footer .wide {
+  flex: 1;
 }
 
 .horizontal {
   display: flex;
 }
 
-.panel-heading {
-  font-size: 18px;
-  font-weight: 600;
-  margin-top: 0;
-  padding: 7px 7px 0 7px;
+.panels {
+  background-color: #121a25;
+  flex: 1;
+  overflow: hidden;
 }
 
-.nav-link, .region {
+.panel-heading {
+  font-family: "Roboto Mono", monospace;
+  font-size: 12px;
+  color: gray;
+  margin: 8px;
+}
+
+.nav-link,
+.region {
   cursor: pointer;
 }
 
 .nav-panel {
   background-color: #282b2e;
-  flex: 1 1 270px;
-  font-size: 14px;
-  /* 10px to match exact top margin of .content.
-   * 0.8em to pair with the -0.5em margin of .content, producing a net margin
-   * between the two of 0.3em.
-   */
-  margin: 10px 0.8em 0 0;
+  flex: 1 200px;
+  margin: 0;
+  overflow: scroll;
 }
 
 .nav-inner {
-  background-color: #282b2e;
-  overflow: auto;
   padding: 0 0 7px 7px;
 }
 
@@ -59,26 +94,24 @@
   top: 0;
 }
 
-.nav-inner .root {
+.root {
   margin: 0;
+  display: none;
+}
+
+.nav-tree > ul {
+  padding-left: 6px;
 }
 
 .nav-inner ul {
   padding-left: 12px;
-}
-.nav-inner > ul {
-  padding-left: 0;
-  margin-top: 0;
+  margin: 0;
 }
 
 .nav-inner li {
   list-style-type: none;
 }
 
-.nav-inner li.dir {
-  margin-left: 5px;
-}
-
 .nav-inner li:not(.dir) {
   margin-left: 20px;
   margin-bottom: 3px;
@@ -106,10 +139,6 @@
   overflow: hidden;
 }
 
-.nav-inner .nav-link {
-  color: #33ccff;
-}
-
 .nav-inner .selected-file {
   color: white;
   cursor: inherit;
@@ -118,44 +147,42 @@
 }
 
 .edit-count {
-  background-color: #cccc00;
-  border-radius: 15px;
+  background-color: #37aedc;
+  border-radius: 10px;
   color: #000000;
   display: inline-block;
   font-size: 11px;
   font-weight: 600;
   margin-left: 5px;
   min-width: 25px;
-  padding: 5px 0;
+  padding: 4px 0 2px 0;
   text-align: center;
+  line-height: 1em;
 }
 
 .content {
-  flex: 0 1 auto;
+  flex: 4 300px;
+  background: #282b2e;
   font-family: monospace;
-  /**
-   * Left margin offsets the margin introduced by the absolutely positioned
-   * child div.
-   */
-  margin: 10px 10px 10px -0.5em;
+  margin: 0 6px;
   position: relative;
   white-space: pre;
+  overflow: scroll;
 }
 
 .code {
-  left: 0.5em;
-  /* Increase line height to make room for borders in non-nullable type
-   * regions.
-   */
-  line-height: 1.3;
-  min-height: 600px;
-  padding-left: 62px;
-  position: inherit;
-  z-index: 100;
+  padding: 0.5em;
+  position: absolute;
+  left: 0;
+  top: 0;
+  margin-left: 56px;
 }
 
-.code.hljs {
-  background-color: inherit;
+.hljs {
+  background-color: #282b2e;
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
 }
 
 .code .welcome {
@@ -180,15 +207,15 @@
 }
 
 .regions {
-  background-color: #282b2e;
-  padding: 0.5em 0 0.5em 0.5em;
+  padding: 0.5em;
   position: absolute;
-  left: 0.5em;
+  left: 0;
   top: 0;
 }
 
 .regions table {
   border-spacing: 0;
+  font-size: inherit;
 }
 
 .regions td {
@@ -196,7 +223,6 @@
   /* The content of the regions is not visible; the user instead will see the
    * highlighted copy of the content. */
   color: rgba(255, 255, 255, 0);
-  line-height: 1.3;
   padding: 0;
   white-space: pre;
 }
@@ -207,20 +233,21 @@
 
 .regions tr.highlight td:last-child {
   background-color: #444444;
+  color: white;
 }
 
 .regions td.line-no {
   border-right: solid #282b2e 2px;
   color: #999999;
-  display: inline-block;
   padding-right: 4px;
   text-align: right;
   visibility: visible;
   width: 50px;
+  display: inline-block;
 }
 
 .regions tr.highlight td.line-no {
-  border-right: solid #cccccc 2px;
+  border-right: solid #ccc 2px;
 }
 
 .region {
@@ -242,7 +269,7 @@
 
 .region.unchanged-region {
   background-color: rgba(0, 0, 0, 0.3);
-  border-bottom: solid 2px #cccccc;
+  border-bottom: solid 2px #ccc;
   /* Invisible text; use underlying highlighting. */
   color: rgba(0, 0, 0, 0);
   /* Reduce line height to make room for border. */
@@ -257,9 +284,11 @@
 }
 
 .info-panel {
-  flex: 1 1 270px;
-  font-size: 14px;
-  margin: 10px 0;
+  flex: 1 200px;
+  margin: 0;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
 }
 
 .info-panel .edit-panel {
@@ -268,19 +297,13 @@
 }
 
 .info-panel .panel-content {
-  font-size: 13px;
   padding: 7px;
 }
 
-.info-panel .panel-content > :first-child {
+.info-panel .panel-content> :first-child {
   margin-top: 0;
 }
 
-.info-panel .region-location {
-  padding-left: 12px;
-  text-indent: -12px;
-}
-
 .info-panel .nowrap {
   white-space: nowrap;
 }
@@ -290,26 +313,47 @@
   padding-left: 20px;
 }
 
+.info-panel li {
+  margin: 0 0 5px 0;
+}
+
 .info-panel a {
   color: #33ccff;
 }
 
 .info-panel .edit-list {
   background-color: #282b2e;
-  margin-top: 12px;
   overflow: auto;
 }
 
+.edit-panel {
+  margin-top: 6px;
+  flex: 1 100px;
+}
+
+.edit-list {
+  flex: 2 100px;
+}
+
 .edit-list .edit {
   margin: 3px 0;
-  padding-left: 21px;
-  text-indent: -21px;
 }
 
 .edit-list .edit-link {
   cursor: pointer;
 }
 
-.footer {
-  padding: 8px 8px 100px 8px;
+.elevation-z4 {
+  box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, .12);
+}
+
+a {
+  color: #ccc;
+  fill: #ccc;
+  text-decoration: none;
+}
+
+a:hover {
+  color: #fff;
+  fill: #fff;
 }
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 ea345f8..16a0fbc 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
@@ -13,6 +13,10 @@
   return _highlight_css ??= _decode(_highlight_css_base64);
 }
 
+String get index_html {
+  return _index_html ??= _decode(_index_html_base64);
+}
+
 String get highlight_pack_js {
   return _highlight_pack_js ??= _decode(_highlight_pack_js_base64);
 }
@@ -48,6 +52,47 @@
 eWxlOiBpdGFsaWM7Cn0KCi5obGpzLXN0cm9uZyB7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0K
 ''';
 
+String _index_html;
+// index_html md5 is '8733d08faa10c30355405d4c78b051e5'
+String _index_html_base64 = '''
+PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
+cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
+cnRQYWdlU2NyaXB0IH19PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0
+dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1PcGVuK1NhbnM6NDAwLDYwMCZkaXNw
+bGF5PXN3YXAiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJ7eyBoaWdobGlnaHRTdHls
+ZVBhdGggfX0iPgogICAgPHN0eWxlPnt7IGRhcnRQYWdlU3R5bGUgfX08L3N0eWxlPgo8L2hlYWQ+Cjxi
+b2R5Pgo8cCBjbGFzcz0icm9vdCI+e3sgcm9vdCB9fTwvcD4KPGhlYWRlciBjbGFzcz0iZWxldmF0aW9u
+LXo0Ij4KICAgIDxoMT5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9oMT4KICAgIDxoMiBpZD0i
+dW5pdC1uYW1lIj4mbmJzcDs8L2gyPgo8L2hlYWRlcj4KPGRpdiBjbGFzcz0icGFuZWxzIGhvcml6b250
+YWwiPgogICAgPGRpdiBjbGFzcz0ibmF2LXBhbmVsIj4KICAgICAgICA8ZGl2IGNsYXNzPSJuYXYtaW5u
+ZXIiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5Qcm9qZWN0IEZpbGVzPC9k
+aXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im5hdi10cmVlIj48L2Rpdj4KICAgICAgICA8L2Rpdj48
+IS0tIC9uYXYtaW5uZXIgLS0+CiAgICA8L2Rpdj48IS0tIC9uYXYgLS0+CiAgICA8ZGl2IGNsYXNzPSJj
+b250ZW50Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJjb2RlIj4KICAgICAgICAgICAgPCEtLSBDb21waWxh
+dGlvbiB1bml0IGNvbnRlbnQgaXMgd3JpdHRlbiBoZXJlLiAtLT4KICAgICAgICAgICAgPHAgY2xhc3M9
+IndlbGNvbWUiPgogICAgICAgICAgICAgICAgPCEtLSBUT0RPKHNyYXdsaW5zKTogTW9yZSB3ZWxjb21l
+IHRleHQhIC0tPgogICAgICAgICAgICAgICAgU2VsZWN0IGEgc291cmNlIGZpbGUgb24gdGhlIGxlZnQg
+dG8gcHJldmlldyB0aGUgZWRpdHMuCiAgICAgICAgICAgIDwvcD4KICAgICAgICA8L2Rpdj4KICAgICAg
+ICA8ZGl2IGNsYXNzPSJyZWdpb25zIj4KICAgICAgICAgICAgPCEtLSBUaGUgcmVnaW9ucyBhcmUgdGhl
+biB3cml0dGVuIGFnYWluLCBvdmVybGF5aW5nIHRoZSBmaXJzdCBjb3B5IG9mIC0tPgogICAgICAgICAg
+ICA8IS0tIHRoZSBjb250ZW50LCB0byBwcm92aWRlIHRvb2x0aXBzIGZvciBtb2RpZmllZCByZWdpb25z
+LiAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9yZWdpb25zIC0tPgogICAgPC9kaXY+PCEtLSAvY29udGVu
+dCAtLT4KICAgIDxkaXYgY2xhc3M9ImluZm8tcGFuZWwiPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQt
+bGlzdCI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPlByb3Bvc2VkIEVkaXRz
+PC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPjwvZGl2PgogICAgICAg
+IDwvZGl2PjwhLS0gL2VkaXQtbGlzdCAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LXBhbmVsIj4K
+ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+RWRpdCBEZXRhaWxzPC9kaXY+CiAg
+ICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPHA+U2Vl
+IGRldGFpbHMgYWJvdXQgYSBwcm9wb3NlZCBlZGl0LjwvcD4KICAgICAgICAgICAgPC9kaXY+PCEtLSAv
+cGFuZWwtY29udGVudCAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9lZGl0LXBhbmVsIC0tPgogICAgPC9k
+aXY+PCEtLSAvaW5mby1wYW5lbCAtLT4KPC9kaXY+PCEtLSAvcGFuZWxzIC0tPgo8Zm9vdGVyPgogICAg
+PGEgdGFyZ2V0PSJfYmxhbmsiCiAgICAgICBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vZGFydC1sYW5n
+L3Nkay9ibG9iL21hc3Rlci9wa2cvYW5hbHlzaXNfc2VydmVyL2xpYi9zcmMvZWRpdC9ubmJkX21pZ3Jh
+dGlvbi9SRUFETUUubWQiPk51bGwKICAgICAgICBzYWZldHkgbWlncmF0aW9uIGhlbHA8L2E+CiAgICA8
+c3BhbiBjbGFzcz0id2lkZSI+IDwvc3Bhbj4KICAgIDxkaXY+QmFzZWQgb24ge3sgc2RrVmVyc2lvbiB9
+fTwvZGl2Pgo8L2Zvb3Rlcj4KPC9ib2R5Pgo8L2h0bWw+Cg==
+''';
+
 String _highlight_pack_js;
 // highlight_pack_js md5 is '9104bfe8b056f8e00da50b0ea3d6e6d4'
 String _highlight_pack_js_base64 = '''
@@ -266,7 +311,7 @@
 ''';
 
 String _migration_js;
-// migration_dart md5 is '61fc6d8b736b7e11eb4f1945dfc64194'
+// migration_dart md5 is '18178aa7baafdeeeb6b040e74fc6c973'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgdD1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHM9MDtzPHQubGVuZ3RoO3MrKyl7dmFyIHI9dFtzXQpiW3JdPWFb
@@ -287,7 +332,7 @@
 dG90eXBlPXR9fWZ1bmN0aW9uIGluaGVyaXRNYW55KGEsYil7Zm9yKHZhciB0PTA7dDxiLmxlbmd0aDt0
 KyspaW5oZXJpdChiW3RdLGEpfWZ1bmN0aW9uIG1peGluKGEsYil7Y29weVByb3BlcnRpZXMoYi5wcm90
 b3R5cGUsYS5wcm90b3R5cGUpCmEucHJvdG90eXBlLmNvbnN0cnVjdG9yPWF9ZnVuY3Rpb24gbGF6eShh
-LGIsYyxkKXt2YXIgdD1hCmFbYl09dAphW2NdPWZ1bmN0aW9uKCl7YVtjXT1mdW5jdGlvbigpe0gubEco
+LGIsYyxkKXt2YXIgdD1hCmFbYl09dAphW2NdPWZ1bmN0aW9uKCl7YVtjXT1mdW5jdGlvbigpe0guYWco
 Yil9CnZhciBzCnZhciByPWQKdHJ5e2lmKGFbYl09PT10KXtzPWFbYl09cgpzPWFbYl09ZCgpfWVsc2Ug
 cz1hW2JdfWZpbmFsbHl7aWYocz09PXIpYVtiXT1udWxsCmFbY109ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
 c1tiXX19cmV0dXJuIHN9fWZ1bmN0aW9uIG1ha2VDb25zdExpc3QoYSl7YS5pbW11dGFibGUkbGlzdD1B
@@ -297,16 +342,16 @@
 dFRvRmFzdE9iamVjdChhW3RdKX12YXIgeT0wCmZ1bmN0aW9uIHRlYXJPZmZHZXR0ZXIoYSxiLGMsZCxl
 KXtyZXR1cm4gZT9uZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJyZWZs
 ZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5Kysr
-IihyZWNlaXZlcikgeyIrImlmIChjID09PSBudWxsKSBjID0gIisiSC5ocCIrIigiKyJ0aGlzLCBmdW5j
+IihyZWNlaXZlcikgeyIrImlmIChjID09PSBudWxsKSBjID0gIisiSC5LcSIrIigiKyJ0aGlzLCBmdW5j
 cywgYXBwbHlUcmFtcG9saW5lSW5kZXgsIHJlZmxlY3Rpb25JbmZvLCBmYWxzZSwgdHJ1ZSwgbmFtZSk7
 IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1bmNzWzBdLCByZWNlaXZlciwgbmFtZSk7IisifSIpKGEsYixj
 LGQsSCxudWxsKTpuZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJyZWZs
 ZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5Kysr
-IigpIHsiKyJpZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkguaHAiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5
+IigpIHsiKyJpZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5
 VHJhbXBvbGluZUluZGV4LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIGZhbHNlLCBuYW1lKTsiKyJyZXR1
 cm4gbmV3IGModGhpcywgZnVuY3NbMF0sIG51bGwsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVsbCl9
 ZnVuY3Rpb24gdGVhck9mZihhLGIsYyxkLGUsZil7dmFyIHQ9bnVsbApyZXR1cm4gZD9mdW5jdGlvbigp
-e2lmKHQ9PT1udWxsKXQ9SC5ocCh0aGlzLGEsYixjLHRydWUsZmFsc2UsZSkucHJvdG90eXBlCnJldHVy
+e2lmKHQ9PT1udWxsKXQ9SC5LcSh0aGlzLGEsYixjLHRydWUsZmFsc2UsZSkucHJvdG90eXBlCnJldHVy
 biB0fTp0ZWFyT2ZmR2V0dGVyKGEsYixjLGUsZil9dmFyIHg9MApmdW5jdGlvbiBpbnN0YWxsVGVhck9m
 ZihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIgdD1bXQpmb3IodmFyIHM9MDtzPGgubGVuZ3RoO3MrKyl7
 dmFyIHI9aFtzXQppZih0eXBlb2Ygcj09J3N0cmluZycpcj1hW3JdCnIuJGNhbGxOYW1lPWdbc10KdC5w
@@ -340,2956 +385,3300 @@
 czpzZXRPclVwZGF0ZUxlYWZUYWdzfX0oKQpmdW5jdGlvbiBpbml0aWFsaXplRGVmZXJyZWRIdW5rKGEp
 e3g9di50eXBlcy5sZW5ndGgKYShodW5rSGVscGVycyx2LHcsJCl9ZnVuY3Rpb24gZ2V0R2xvYmFsRnJv
 bU5hbWUoYSl7Zm9yKHZhciB0PTA7dDx3Lmxlbmd0aDt0Kyspe2lmKHdbdF09PUMpY29udGludWUKaWYo
-d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17aDA6ZnVuY3Rpb24gaDAoKXt9LApmdzpm
+d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17ZW86ZnVuY3Rpb24gZW8oKXt9LApvbzpm
 dW5jdGlvbihhKXt2YXIgdCxzPWFeNDgKaWYoczw9OSlyZXR1cm4gcwp0PWF8MzIKaWYoOTc8PXQmJnQ8
-PTEwMilyZXR1cm4gdC04NwpyZXR1cm4tMX0sCmhQOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmJoKCJO
-byBlbGVtZW50Iil9LApqSTpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5iaCgiVG9vIG1hbnkgZWxlbWVu
-dHMiKX0sCmN5OmZ1bmN0aW9uIGN5KGEpe3RoaXMuYT1hfSwKYkM6ZnVuY3Rpb24gYkMoKXt9LAphZTpm
-dW5jdGlvbiBhZSgpe30sCmFROmZ1bmN0aW9uIGFRKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1i
-Cl8uYz0wCl8uZD1udWxsCl8uJHRpPWN9LAphNDpmdW5jdGlvbiBhNChhLGIsYyl7dGhpcy5hPWEKdGhp
-cy5iPWIKdGhpcy4kdGk9Y30sCmFZOmZ1bmN0aW9uIGFZKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0
-aGlzLiR0aT1jfSwKY186ZnVuY3Rpb24gY18oYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRp
-PWN9LApWOmZ1bmN0aW9uIFYoKXt9LAphWDpmdW5jdGlvbiBhWCgpe30sCmJsOmZ1bmN0aW9uIGJsKCl7
-fSwKYmk6ZnVuY3Rpb24gYmkoYSl7dGhpcy5hPWF9LApqQzpmdW5jdGlvbigpe3Rocm93IEguYShQLk4o
-IkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIE1hcCIpKX0sCmlZOmZ1bmN0aW9uKGEpe3ZhciB0LHM9
-SC5pWChhKQppZih0eXBlb2Ygcz09InN0cmluZyIpcmV0dXJuIHMKdD0ibWluaWZpZWQ6IithCnJldHVy
-biB0fSwKbHg6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiIT1udWxsKXt0PWIueAppZih0IT1udWxsKXJl
-dHVybiB0fXJldHVybiB1LmFVLmMoYSl9LApiOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKHR5cGVvZiBhPT0i
-c3RyaW5nIilyZXR1cm4gYQppZih0eXBlb2YgYT09Im51bWJlciIpe2lmKGEhPT0wKXJldHVybiIiK2F9
-ZWxzZSBpZighMD09PWEpcmV0dXJuInRydWUiCmVsc2UgaWYoITE9PT1hKXJldHVybiJmYWxzZSIKZWxz
-ZSBpZihhPT1udWxsKXJldHVybiJudWxsIgp0PUouYjIoYSkKaWYodHlwZW9mIHQhPSJzdHJpbmciKXRo
-cm93IEguYShILmFzKGEpKQpyZXR1cm4gdH0sCmJWOmZ1bmN0aW9uKGEpe3ZhciB0PWEuJGlkZW50aXR5
-SGFzaAppZih0PT1udWxsKXt0PU1hdGgucmFuZG9tKCkqMHgzZmZmZmZmZnwwCmEuJGlkZW50aXR5SGFz
-aD10fXJldHVybiB0fSwKaDQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89bnVsbCxuPS9eXHMq
-WystXT8oKDB4W2EtZjAtOV0rKXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZihuPT1u
-dWxsKXJldHVybiBvCmlmKDM+PW4ubGVuZ3RoKXJldHVybiBILmkobiwzKQp0PUgubyhuWzNdKQppZihi
-PT1udWxsKXtpZih0IT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihuWzJdIT1udWxsKXJldHVy
-biBwYXJzZUludChhLDE2KQpyZXR1cm4gb31pZihiPDJ8fGI+MzYpdGhyb3cgSC5hKFAuTChiLDIsMzYs
-InJhZGl4IixvKSkKaWYoYj09PTEwJiZ0IT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihiPDEw
-fHx0PT1udWxsKXtzPWI8PTEwPzQ3K2I6ODYrYgpyPW5bMV0KZm9yKHE9ci5sZW5ndGgscD0wO3A8cTsr
-K3ApaWYoKEMuYS50KHIscCl8MzIpPnMpcmV0dXJuIG99cmV0dXJuIHBhcnNlSW50KGEsYil9LAplZjpm
-dW5jdGlvbihhKXt2YXIgdD1ILmpSKGEpCnJldHVybiB0fSwKalI6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-CmlmKGEgaW5zdGFuY2VvZiBQLnQpcmV0dXJuIEguUChILmE4KGEpLG51bGwpCmlmKEouYUUoYSk9PT1D
-LlB8fHUuYWsuYyhhKSl7dD1DLnEoYSkKaWYoSC5oWCh0KSlyZXR1cm4gdApzPWEuY29uc3RydWN0b3IK
-aWYodHlwZW9mIHM9PSJmdW5jdGlvbiIpe3I9cy5uYW1lCmlmKHR5cGVvZiByPT0ic3RyaW5nIiYmSC5o
-WChyKSlyZXR1cm4gcn19cmV0dXJuIEguUChILmE4KGEpLG51bGwpfSwKaFg6ZnVuY3Rpb24oYSl7dmFy
-IHQ9YSE9PSJPYmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApoVzpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
-cSxwPWEubGVuZ3RoCmlmKHA8PTUwMClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxs
-LGEpCmZvcih0PSIiLHM9MDtzPHA7cz1yKXtyPXMrNTAwCnE9cjxwP3I6cAp0Kz1TdHJpbmcuZnJvbUNo
-YXJDb2RlLmFwcGx5KG51bGwsYS5zbGljZShzLHEpKX1yZXR1cm4gdH0sCmtfOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxPUgubihbXSx1LnQpCmZvcih0PWEubGVuZ3RoLHM9MDtzPGEubGVuZ3RoO2EubGVuZ3Ro
-PT09dHx8KDAsSC5jcikoYSksKytzKXtyPWFbc10KaWYoIUguZEoocikpdGhyb3cgSC5hKEguYXMocikp
-CmlmKHI8PTY1NTM1KUMuYi5rKHEscikKZWxzZSBpZihyPD0xMTE0MTExKXtDLmIuayhxLDU1Mjk2KyhD
-LmMuWihyLTY1NTM2LDEwKSYxMDIzKSkKQy5iLmsocSw1NjMyMCsociYxMDIzKSl9ZWxzZSB0aHJvdyBI
-LmEoSC5hcyhyKSl9cmV0dXJuIEguaFcocSl9LApoWTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKZm9yKHQ9
-YS5sZW5ndGgscz0wO3M8dDsrK3Mpe3I9YVtzXQppZighSC5kSihyKSl0aHJvdyBILmEoSC5hcyhyKSkK
-aWYocjwwKXRocm93IEguYShILmFzKHIpKQppZihyPjY1NTM1KXJldHVybiBILmtfKGEpfXJldHVybiBI
-LmhXKGEpfSwKazA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGM8PTUwMCYmYj09PTAmJmM9
-PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEpCmZvcih0PWIs
-cz0iIjt0PGM7dD1yKXtyPXQrNTAwCnE9cjxjP3I6YwpzKz1TdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5
-KG51bGwsYS5zdWJhcnJheSh0LHEpKX1yZXR1cm4gc30sCmRfOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKDA8
-PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGEpCmlmKGE8PTExMTQxMTEp
-e3Q9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgoNTUyOTZ8Qy5jLloodCwxMCkpPj4+
-MCw1NjMyMHx0JjEwMjMpfX10aHJvdyBILmEoUC5MKGEsMCwxMTE0MTExLG51bGwsbnVsbCkpfSwKYVQ6
-ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0ZT1uZXcgRGF0ZShhLmEpCnJldHVybiBh
-LmRhdGV9LApqWjpmdW5jdGlvbihhKXt2YXIgdD1ILmFUKGEpLmdldEZ1bGxZZWFyKCkrMApyZXR1cm4g
-dH0sCmpYOmZ1bmN0aW9uKGEpe3ZhciB0PUguYVQoYSkuZ2V0TW9udGgoKSsxCnJldHVybiB0fSwKalQ6
-ZnVuY3Rpb24oYSl7dmFyIHQ9SC5hVChhKS5nZXREYXRlKCkrMApyZXR1cm4gdH0sCmpVOmZ1bmN0aW9u
-KGEpe3ZhciB0PUguYVQoYSkuZ2V0SG91cnMoKSswCnJldHVybiB0fSwKalc6ZnVuY3Rpb24oYSl7dmFy
-IHQ9SC5hVChhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gdH0sCmpZOmZ1bmN0aW9uKGEpe3ZhciB0PUgu
-YVQoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHR9LApqVjpmdW5jdGlvbihhKXt2YXIgdD1ILmFUKGEp
-LmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHR9LApiZjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxy
-PXt9CnIuYT0wCnQ9W10Kcz1bXQpyLmE9Yi5sZW5ndGgKQy5iLkkodCxiKQpyLmI9IiIKaWYoYyE9bnVs
-bCYmYy5hIT09MCljLkEoMCxuZXcgSC5lZShyLHMsdCkpCiIiK3IuYQpyZXR1cm4gSi5qcShhLG5ldyBI
-LmNKKEMuYTAsMCx0LHMsMCkpfSwKalM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGIgaW5z
-dGFuY2VvZiBBcnJheSl0PWM9PW51bGx8fGMuYT09PTAKZWxzZSB0PSExCmlmKHQpe3M9YgpyPXMubGVu
-Z3RoCmlmKHI9PT0wKXtpZighIWEuJDApcmV0dXJuIGEuJDAoKX1lbHNlIGlmKHI9PT0xKXtpZighIWEu
-JDEpcmV0dXJuIGEuJDEoc1swXSl9ZWxzZSBpZihyPT09Mil7aWYoISFhLiQyKXJldHVybiBhLiQyKHNb
-MF0sc1sxXSl9ZWxzZSBpZihyPT09Myl7aWYoISFhLiQzKXJldHVybiBhLiQzKHNbMF0sc1sxXSxzWzJd
-KX1lbHNlIGlmKHI9PT00KXtpZighIWEuJDQpcmV0dXJuIGEuJDQoc1swXSxzWzFdLHNbMl0sc1szXSl9
-ZWxzZSBpZihyPT09NSlpZighIWEuJDUpcmV0dXJuIGEuJDUoc1swXSxzWzFdLHNbMl0sc1szXSxzWzRd
-KQpxPWFbIiIrIiQiK3JdCmlmKHEhPW51bGwpcmV0dXJuIHEuYXBwbHkoYSxzKX1yZXR1cm4gSC5qUShh
-LGIsYyl9LApqUTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9YiBpbnN0YW5j
-ZW9mIEFycmF5P2I6UC5oMihiLCEwLHUueiksaj1rLmxlbmd0aCxpPWEuJFIKaWYoajxpKXJldHVybiBI
-LmJmKGEsayxjKQp0PWEuJEQKcz10PT1udWxsCnI9IXM/dCgpOm51bGwKcT1KLmFFKGEpCnA9cS4kQwpp
-Zih0eXBlb2YgcD09InN0cmluZyIpcD1xW3BdCmlmKHMpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0dXJu
-IEguYmYoYSxrLGMpCmlmKGo9PT1pKXJldHVybiBwLmFwcGx5KGEsaykKcmV0dXJuIEguYmYoYSxrLGMp
-fWlmKHIgaW5zdGFuY2VvZiBBcnJheSl7aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC5iZihhLGss
-YykKaWYoaj5pK3IubGVuZ3RoKXJldHVybiBILmJmKGEsayxudWxsKQpDLmIuSShrLHIuc2xpY2Uoai1p
-KSkKcmV0dXJuIHAuYXBwbHkoYSxrKX1lbHNle2lmKGo+aSlyZXR1cm4gSC5iZihhLGssYykKbz1PYmpl
-Y3Qua2V5cyhyKQppZihjPT1udWxsKWZvcihzPW8ubGVuZ3RoLG49MDtuPG8ubGVuZ3RoO28ubGVuZ3Ro
-PT09c3x8KDAsSC5jcikobyksKytuKUMuYi5rKGsscltILm8ob1tuXSldKQplbHNle2ZvcihzPW8ubGVu
-Z3RoLG09MCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEguY3IpKG8pLCsrbil7bD1ILm8o
-b1tuXSkKaWYoYy5hXyhsKSl7KyttCkMuYi5rKGssYy5qKDAsbCkpfWVsc2UgQy5iLmsoayxyW2xdKX1p
-ZihtIT09Yy5hKXJldHVybiBILmJmKGEsayxjKX1yZXR1cm4gcC5hcHBseShhLGspfX0sCmFqOmZ1bmN0
-aW9uKGEpe3Rocm93IEguYShILmFzKGEpKX0sCmk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKUouYXQo
-YSkKdGhyb3cgSC5hKEguYjEoYSxiKSl9LApiMTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj0iaW5kZXgi
-CmlmKCFILmRKKGIpKXJldHVybiBuZXcgUC5hMSghMCxiLHIsbnVsbCkKdD1ILngoSi5hdChhKSkKaWYo
-IShiPDApKXtpZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiBILmFqKHQpCnM9Yj49dH1lbHNlIHM9
-ITAKaWYocylyZXR1cm4gUC5lNShiLGEscixudWxsLHQpCnJldHVybiBQLmVnKGIscil9LApsbDpmdW5j
-dGlvbihhLGIsYyl7dmFyIHQ9IkludmFsaWQgdmFsdWUiCmlmKGE+YylyZXR1cm4gbmV3IFAuYVUoMCxj
-LCEwLGEsInN0YXJ0Iix0KQppZihiIT1udWxsKWlmKGI8YXx8Yj5jKXJldHVybiBuZXcgUC5hVShhLGMs
-ITAsYiwiZW5kIix0KQpyZXR1cm4gbmV3IFAuYTEoITAsYiwiZW5kIixudWxsKX0sCmFzOmZ1bmN0aW9u
-KGEpe3JldHVybiBuZXcgUC5hMSghMCxhLG51bGwsbnVsbCl9LAphOmZ1bmN0aW9uKGEpe3ZhciB0Cmlm
-KGE9PW51bGwpYT1uZXcgUC5iZCgpCnQ9bmV3IEVycm9yKCkKdC5kYXJ0RXhjZXB0aW9uPWEKaWYoImRl
-ZmluZVByb3BlcnR5IiBpbiBPYmplY3Qpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJtZXNzYWdlIix7
-Z2V0OkguaVd9KQp0Lm5hbWU9IiJ9ZWxzZSB0LnRvU3RyaW5nPUguaVcKcmV0dXJuIHR9LAppVzpmdW5j
-dGlvbigpe3JldHVybiBKLmIyKHRoaXMuZGFydEV4Y2VwdGlvbil9LAphazpmdW5jdGlvbihhKXt0aHJv
-dyBILmEoYSl9LApjcjpmdW5jdGlvbihhKXt0aHJvdyBILmEoUC5hdihhKSl9LAphbzpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscSxwLG8KYT1ILmxEKGEucmVwbGFjZShTdHJpbmcoe30pLCckcmVjZWl2ZXIkJykp
-CnQ9YS5tYXRjaCgvXFxcJFthLXpBLVpdK1xcXCQvZykKaWYodD09bnVsbCl0PUgubihbXSx1LnMpCnM9
-dC5pbmRleE9mKCJcXCRhcmd1bWVudHNcXCQiKQpyPXQuaW5kZXhPZigiXFwkYXJndW1lbnRzRXhwclxc
-JCIpCnE9dC5pbmRleE9mKCJcXCRleHByXFwkIikKcD10LmluZGV4T2YoIlxcJG1ldGhvZFxcJCIpCm89
-dC5pbmRleE9mKCJcXCRyZWNlaXZlclxcJCIpCnJldHVybiBuZXcgSC5laihhLnJlcGxhY2UobmV3IFJl
-Z0V4cCgnXFxcXFxcJGFyZ3VtZW50c1xcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNl
-KG5ldyBSZWdFeHAoJ1xcXFxcXCRhcmd1bWVudHNFeHByXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkq
-KScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGV4cHJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhd
-KSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkbWV0aG9kXFxcXFxcJCcsJ2cnKSwnKCg/Onh8
-W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJHJlY2VpdmVyXFxcXFxcJCcsJ2cnKSwn
-KCg/Onh8W154XSkqKScpLHMscixxLHAsbyl9LAplazpmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24o
-JGV4cHIkKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5eyRleHByJC4kbWV0aG9k
-JCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHQpe3JldHVybiB0Lm1lc3NhZ2V9fShhKX0sCmkzOmZ1bmN0
-aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhwciQpe3RyeXskZXhwciQuJG1ldGhvZCR9Y2F0Y2godCl7
-cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKaFY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguY1YoYSxi
-PT1udWxsP251bGw6Yi5tZXRob2QpfSwKaDE6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iPT1udWxsLHM9dD9u
-dWxsOmIubWV0aG9kCnJldHVybiBuZXcgSC5jTChhLHMsdD9udWxsOmIucmVjZWl2ZXIpfSwKUTpmdW5j
-dGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVsbCxlPW5ldyBILmZSKGEp
-CmlmKGE9PW51bGwpcmV0dXJuIGYKaWYodHlwZW9mIGEhPT0ib2JqZWN0IilyZXR1cm4gYQppZigiZGFy
-dEV4Y2VwdGlvbiIgaW4gYSlyZXR1cm4gZS4kMShhLmRhcnRFeGNlcHRpb24pCmVsc2UgaWYoISgibWVz
-c2FnZSIgaW4gYSkpcmV0dXJuIGEKdD1hLm1lc3NhZ2UKaWYoIm51bWJlciIgaW4gYSYmdHlwZW9mIGEu
-bnVtYmVyPT0ibnVtYmVyIil7cz1hLm51bWJlcgpyPXMmNjU1MzUKaWYoKEMuYy5aKHMsMTYpJjgxOTEp
-PT09MTApc3dpdGNoKHIpe2Nhc2UgNDM4OnJldHVybiBlLiQxKEguaDEoSC5iKHQpKyIgKEVycm9yICIr
-cisiKSIsZikpCmNhc2UgNDQ1OmNhc2UgNTAwNzpyZXR1cm4gZS4kMShILmhWKEguYih0KSsiIChFcnJv
-ciAiK3IrIikiLGYpKX19aWYoYSBpbnN0YW5jZW9mIFR5cGVFcnJvcil7cT0kLmoyKCkKcD0kLmozKCkK
-bz0kLmo0KCkKbj0kLmo1KCkKbT0kLmo4KCkKbD0kLmo5KCkKaz0kLmo3KCkKJC5qNigpCmo9JC5qYigp
-Cmk9JC5qYSgpCmg9cS5MKHQpCmlmKGghPW51bGwpcmV0dXJuIGUuJDEoSC5oMShILm8odCksaCkpCmVs
-c2V7aD1wLkwodCkKaWYoaCE9bnVsbCl7aC5tZXRob2Q9ImNhbGwiCnJldHVybiBlLiQxKEguaDEoSC5v
-KHQpLGgpKX1lbHNle2g9by5MKHQpCmlmKGg9PW51bGwpe2g9bi5MKHQpCmlmKGg9PW51bGwpe2g9bS5M
-KHQpCmlmKGg9PW51bGwpe2g9bC5MKHQpCmlmKGg9PW51bGwpe2g9ay5MKHQpCmlmKGg9PW51bGwpe2g9
-bi5MKHQpCmlmKGg9PW51bGwpe2g9ai5MKHQpCmlmKGg9PW51bGwpe2g9aS5MKHQpCmc9aCE9bnVsbH1l
-bHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1l
-bHNlIGc9ITAKaWYoZylyZXR1cm4gZS4kMShILmhWKEgubyh0KSxoKSl9fXJldHVybiBlLiQxKG5ldyBI
-LmRhKHR5cGVvZiB0PT0ic3RyaW5nIj90OiIiKSl9aWYoYSBpbnN0YW5jZW9mIFJhbmdlRXJyb3Ipe2lm
-KHR5cGVvZiB0PT0ic3RyaW5nIiYmdC5pbmRleE9mKCJjYWxsIHN0YWNrIikhPT0tMSlyZXR1cm4gbmV3
-IFAuYlgoKQp0PWZ1bmN0aW9uKGIpe3RyeXtyZXR1cm4gU3RyaW5nKGIpfWNhdGNoKGQpe31yZXR1cm4g
-bnVsbH0oYSkKcmV0dXJuIGUuJDEobmV3IFAuYTEoITEsZixmLHR5cGVvZiB0PT0ic3RyaW5nIj90LnJl
-cGxhY2UoL15SYW5nZUVycm9yOlxzKi8sIiIpOnQpKX1pZih0eXBlb2YgSW50ZXJuYWxFcnJvcj09ImZ1
-bmN0aW9uIiYmYSBpbnN0YW5jZW9mIEludGVybmFsRXJyb3IpaWYodHlwZW9mIHQ9PSJzdHJpbmciJiZ0
-PT09InRvbyBtdWNoIHJlY3Vyc2lvbiIpcmV0dXJuIG5ldyBQLmJYKCkKcmV0dXJuIGF9LApjcDpmdW5j
-dGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBuZXcgSC5jZyhhKQp0PWEuJGNhY2hlZFRyYWNl
-CmlmKHQhPW51bGwpcmV0dXJuIHQKcmV0dXJuIGEuJGNhY2hlZFRyYWNlPW5ldyBILmNnKGEpfSwKbG06
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT1hLmxlbmd0aApmb3IodD0wO3Q8cTt0PXIpe3M9dCsxCnI9
-cysxCmIubCgwLGFbdF0sYVtzXSl9cmV0dXJuIGJ9LApsdzpmdW5jdGlvbihhLGIsYyxkLGUsZil7dS5a
-LmIoYSkKc3dpdGNoKEgueChiKSl7Y2FzZSAwOnJldHVybiBhLiQwKCkKY2FzZSAxOnJldHVybiBhLiQx
-KGMpCmNhc2UgMjpyZXR1cm4gYS4kMihjLGQpCmNhc2UgMzpyZXR1cm4gYS4kMyhjLGQsZSkKY2FzZSA0
-OnJldHVybiBhLiQ0KGMsZCxlLGYpfXRocm93IEguYShuZXcgUC5lQSgiVW5zdXBwb3J0ZWQgbnVtYmVy
-IG9mIGFyZ3VtZW50cyBmb3Igd3JhcHBlZCBjbG9zdXJlIikpfSwKZE06ZnVuY3Rpb24oYSxiKXt2YXIg
-dAppZihhPT1udWxsKXJldHVybiBudWxsCnQ9YS4kaWRlbnRpdHkKaWYoISF0KXJldHVybiB0CnQ9ZnVu
-Y3Rpb24oYyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gZShjLGQsZixnLGgsaSl9
-fShhLGIsSC5sdykKYS4kaWRlbnRpdHk9dApyZXR1cm4gdH0sCmpCOmZ1bmN0aW9uKGEsYixjLGQsZSxm
-LGcpe3ZhciB0LHMscixxLHAsbyxuLG0sbD1udWxsLGs9YlswXSxqPWsuJGNhbGxOYW1lLGk9ZT9PYmpl
-Y3QuY3JlYXRlKG5ldyBILmQzKCkuY29uc3RydWN0b3IucHJvdG90eXBlKTpPYmplY3QuY3JlYXRlKG5l
-dyBILmI2KGwsbCxsLGwpLmNvbnN0cnVjdG9yLnByb3RvdHlwZSkKaS4kaW5pdGlhbGl6ZT1pLmNvbnN0
-cnVjdG9yCmlmKGUpdD1mdW5jdGlvbiBzdGF0aWNfdGVhcl9vZmYoKXt0aGlzLiRpbml0aWFsaXplKCl9
-CmVsc2V7cz0kLmFtCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuQigpCiQuYW09cysxCnM9
-bmV3IEZ1bmN0aW9uKCJhLGIsYyxkIitzLCJ0aGlzLiRpbml0aWFsaXplKGEsYixjLGQiK3MrIikiKQp0
-PXN9aS5jb25zdHJ1Y3Rvcj10CnQucHJvdG90eXBlPWkKaWYoIWUpe3I9SC5oTChhLGssZikKci4kcmVm
-bGVjdGlvbkluZm89ZH1lbHNle2kuJHN0YXRpY19uYW1lPWcKcj1rfXE9SC5qeChkLGUsZikKaS4kUz1x
-Cmlbal09cgpmb3IocD1yLG89MTtvPGIubGVuZ3RoOysrbyl7bj1iW29dCm09bi4kY2FsbE5hbWUKaWYo
-bSE9bnVsbCl7bj1lP246SC5oTChhLG4sZikKaVttXT1ufWlmKG89PT1jKXtuLiRyZWZsZWN0aW9uSW5m
-bz1kCnA9bn19aS4kQz1wCmkuJFI9ay4kUgppLiREPWsuJEQKcmV0dXJuIHR9LApqeDpmdW5jdGlvbihh
-LGIsYyl7dmFyIHQKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBmdW5jdGlvbihkLGUpe3JldHVy
-biBmdW5jdGlvbigpe3JldHVybiBkKGUpfX0oSC5pTCxhKQppZih0eXBlb2YgYT09InN0cmluZyIpe2lm
-KGIpdGhyb3cgSC5hKCJDYW5ub3QgY29tcHV0ZSBzaWduYXR1cmUgZm9yIHN0YXRpYyB0ZWFyb2ZmLiIp
-CnQ9Yz9ILmp2OkguanUKcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJu
-IGUodGhpcyxkKX19KGEsdCl9dGhyb3cgSC5hKCJFcnJvciBpbiBmdW5jdGlvblR5cGUgb2YgdGVhcm9m
-ZiIpfSwKank6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5oSwpzd2l0Y2goYj8tMTphKXtjYXNlIDA6
-cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oKX19
-KGMsdCkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnKXtyZXR1cm4g
-Zih0aGlzKVtlXShnKX19KGMsdCkKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5j
-dGlvbihnLGgpe3JldHVybiBmKHRoaXMpW2VdKGcsaCl9fShjLHQpCmNhc2UgMzpyZXR1cm4gZnVuY3Rp
-b24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpKX19KGMs
-dCkKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqKXtyZXR1
-cm4gZih0aGlzKVtlXShnLGgsaSxqKX19KGMsdCkKY2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYpe3Jl
-dHVybiBmdW5jdGlvbihnLGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGosayl9fShjLHQp
-CmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUuYXBw
-bHkoZih0aGlzKSxhcmd1bWVudHMpfX0oZCx0KX19LApoTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxy
-LHEscCxvLG4KaWYoYylyZXR1cm4gSC5qQShhLGIpCnQ9Yi4kc3R1Yk5hbWUKcz1iLmxlbmd0aApyPWFb
-dF0KcT1iPT1udWxsP3I9PW51bGw6Yj09PXIKcD0hcXx8cz49MjcKaWYocClyZXR1cm4gSC5qeShzLCFx
-LHQsYikKaWYocz09PTApe3E9JC5hbQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLkIoKQok
-LmFtPXErMQpvPSJzZWxmIitxCnE9InJldHVybiBmdW5jdGlvbigpe3ZhciAiK28rIiA9IHRoaXMuIgpw
-PSQuYngKcmV0dXJuIG5ldyBGdW5jdGlvbihxK0guYihwPT1udWxsPyQuYng9SC5kUygic2VsZiIpOnAp
-KyI7cmV0dXJuICIrbysiLiIrSC5iKHQpKyIoKTt9IikoKX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2
-d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHMpLmpvaW4oIiwiKQpxPSQuYW0KaWYodHlwZW9mIHEhPT0i
-bnVtYmVyIilyZXR1cm4gcS5CKCkKJC5hbT1xKzEKbis9cQpxPSJyZXR1cm4gZnVuY3Rpb24oIituKyIp
-e3JldHVybiB0aGlzLiIKcD0kLmJ4CnJldHVybiBuZXcgRnVuY3Rpb24ocStILmIocD09bnVsbD8kLmJ4
-PUguZFMoInNlbGYiKTpwKSsiLiIrSC5iKHQpKyIoIituKyIpO30iKSgpfSwKano6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHQ9SC5oSyxzPUguancKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnRocm93IEguYShILmsz
-KCJJbnRlcmNlcHRlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cy4iKSkKY2FzZSAxOnJldHVybiBm
-dW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSl9
-fShjLHQscykKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgpe3Jl
-dHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCl9fShjLHQscykKY2FzZSAzOnJldHVybiBmdW5jdGlvbihl
-LGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGkpfX0o
-Yyx0LHMpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksail7
-cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksail9fShjLHQscykKY2FzZSA1OnJldHVybiBmdW5j
-dGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcodGhp
-cyksaCxpLGosayl9fShjLHQscykKY2FzZSA2OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1
-bmN0aW9uKGgsaSxqLGssbCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrLGwpfX0oYyx0
-LHMpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZixnLGgpe3JldHVybiBmdW5jdGlvbigpe2g9W2co
-dGhpcyldCkFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGgsYXJndW1lbnRzKQpyZXR1cm4gZS5hcHBs
-eShmKHRoaXMpLGgpfX0oZCx0LHMpfX0sCmpBOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4s
-bT0kLmJ4CmlmKG09PW51bGwpbT0kLmJ4PUguZFMoInNlbGYiKQp0PSQuaEoKaWYodD09bnVsbCl0PSQu
-aEo9SC5kUygicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5ndGgKcT1hW3NdCnA9Yj09bnVs
-bD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEguanoociwhcCxzLGIpCmlmKHI9
-PT0xKXttPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guYihtKSsiLiIrSC5iKHMpKyIo
-dGhpcy4iK0guYih0KSsiKTsiCnQ9JC5hbQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkIo
-KQokLmFtPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9bj0iYWJjZGVmZ2hpamtsbW5v
-cHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4oIiwiKQptPSJyZXR1cm4gZnVu
-Y3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5iKG0pKyIuIitILmIocykrIih0aGlzLiIrSC5iKHQp
-KyIsICIrbisiKTsiCnQ9JC5hbQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkIoKQokLmFt
-PXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9LApocDpmdW5jdGlvbihhLGIsYyxkLGUs
-ZixnKXtyZXR1cm4gSC5qQihhLGIsYyxkLCEhZSwhIWYsZyl9LApqdTpmdW5jdGlvbihhLGIpe3JldHVy
-biBILmRGKHYudHlwZVVuaXZlcnNlLEguYTgoYS5hKSxiKX0sCmp2OmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IEguZEYodi50eXBlVW5pdmVyc2UsSC5hOChhLmMpLGIpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-YX0sCmp3OmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApkUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1u
-ZXcgSC5iNigic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLHA9Si5qSihPYmplY3QuZ2V0
-T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8dDsrK3Mpe3I9cFtzXQppZihx
-W3JdPT09YSlyZXR1cm4gcn19LApkSzpmdW5jdGlvbihhKXtpZihhPT1udWxsKUgubGcoImJvb2xlYW4g
-ZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApsZzpmdW5jdGlvbihhKXt0aHJv
-dyBILmEobmV3IEguZGcoYSkpfSwKbEc6ZnVuY3Rpb24oYSl7dGhyb3cgSC5hKG5ldyBQLmNCKGEpKX0s
-CmszOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5kMChhKX0sCmhyOmZ1bmN0aW9uKGEpe3JldHVybiB2
-LmdldElzb2xhdGVUYWcoYSl9LApuOmZ1bmN0aW9uKGEsYil7YS4kdGk9YgpyZXR1cm4gYX0sCmlKOmZ1
-bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIGEuJHRpfSwKbXY6ZnVuY3Rpb24o
-YSxiLGMpe3JldHVybiBILmlWKGFbIiRhIitILmIoYyldLEguaUooYikpfSwKaVY6ZnVuY3Rpb24oYSxi
-KXtpZihhPT1udWxsKXJldHVybiBiCmE9YS5hcHBseShudWxsLGIpCmlmKGE9PW51bGwpcmV0dXJuIG51
-bGwKaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1
-cm4gYS5hcHBseShudWxsLGIpCnJldHVybiBifSwKbXQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmFw
-cGx5KGIsSC5pVihKLmFFKGIpWyIkYSIrSC5iKGMpXSxILmlKKGIpKSl9LAptdTpmdW5jdGlvbihhLGIs
-Yyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRh
-YmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCmxCOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9
-SC5vKCQuaUsuJDEoYSkpLG89JC5mb1twXQppZihvIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHko
-YSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
-dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9dD0kLmZCW3BdCmlmKHQhPW51bGwpcmV0
-dXJuIHQKcz12LmludGVyY2VwdG9yc0J5VGFnW3BdCmlmKHM9PW51bGwpe3A9SC5vKCQuaUguJDIoYSxw
-KSkKaWYocCE9bnVsbCl7bz0kLmZvW3BdCmlmKG8hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShh
-LHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0
-cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQuZkJbcF0KaWYodCE9bnVsbClyZXR1
-cm4gdApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF19fWlmKHM9PW51bGwpcmV0dXJuIG51bGwKdD1zLnBy
-b3RvdHlwZQpyPXBbMF0KaWYocj09PSIhIil7bz1ILmZPKHQpCiQuZm9bcF09bwpPYmplY3QuZGVmaW5l
-UHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Us
-d3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9aWYocj09PSJ+Iil7JC5m
-QltwXT10CnJldHVybiB0fWlmKHI9PT0iLSIpe3E9SC5mTyh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHko
-T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnEsZW51
-bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHEuaX1p
-ZihyPT09IisiKXJldHVybiBILmlTKGEsdCkKaWYocj09PSIqIil0aHJvdyBILmEoUC5lbChwKSkKaWYo
-di5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5mTyh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0
-LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnEsZW51bWVyYWJs
-ZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHEuaX1lbHNlIHJl
-dHVybiBILmlTKGEsdCl9LAppUzpmdW5jdGlvbihhLGIpe3ZhciB0PU9iamVjdC5nZXRQcm90b3R5cGVP
-ZihhKQpPYmplY3QuZGVmaW5lUHJvcGVydHkodCx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpK
-Lmh2KGIsdCxudWxsLG51bGwpLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFi
-bGU6dHJ1ZX0pCnJldHVybiBifSwKZk86ZnVuY3Rpb24oYSl7cmV0dXJuIEouaHYoYSwhMSxudWxsLCEh
-YS4kaUopfSwKbEM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PWIucHJvdG90eXBlCmlmKHYubGVhZlRhZ3Nb
-YV09PT10cnVlKXJldHVybiBILmZPKHQpCmVsc2UgcmV0dXJuIEouaHYodCxjLG51bGwsbnVsbCl9LAps
-dTpmdW5jdGlvbigpe2lmKCEwPT09JC5ocylyZXR1cm4KJC5ocz0hMApILmx2KCl9LApsdjpmdW5jdGlv
-bigpe3ZhciB0LHMscixxLHAsbyxuLG0KJC5mbz1PYmplY3QuY3JlYXRlKG51bGwpCiQuZkI9T2JqZWN0
-LmNyZWF0ZShudWxsKQpILmx0KCkKdD12LmludGVyY2VwdG9yc0J5VGFnCnM9T2JqZWN0LmdldE93blBy
-b3BlcnR5TmFtZXModCkKaWYodHlwZW9mIHdpbmRvdyE9InVuZGVmaW5lZCIpe3dpbmRvdwpyPWZ1bmN0
-aW9uKCl7fQpmb3IocT0wO3E8cy5sZW5ndGg7KytxKXtwPXNbcV0Kbz0kLmlULiQxKHApCmlmKG8hPW51
-bGwpe249SC5sQyhwLHRbcF0sbykKaWYobiE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KG8sdi5k
-aXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6bixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUs
-Y29uZmlndXJhYmxlOnRydWV9KQpyLnByb3RvdHlwZT1vfX19fWZvcihxPTA7cTxzLmxlbmd0aDsrK3Ep
-e3A9c1txXQppZigvXltBLVphLXpfXS8udGVzdChwKSl7bT10W3BdCnRbIiEiK3BdPW0KdFsifiIrcF09
-bQp0WyItIitwXT1tCnRbIisiK3BdPW0KdFsiKiIrcF09bX19fSwKbHQ6ZnVuY3Rpb24oKXt2YXIgdCxz
-LHIscSxwLG8sbj1DLkUoKQpuPUguYnUoQy5GLEguYnUoQy5HLEguYnUoQy5yLEguYnUoQy5yLEguYnUo
-Qy5ILEguYnUoQy5JLEguYnUoQy5KKEMucSksbikpKSkpKSkKaWYodHlwZW9mIGRhcnROYXRpdmVEaXNw
-YXRjaEhvb2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXt0PWRhcnROYXRpdmVEaXNwYXRjaEhvb2tz
-VHJhbnNmb3JtZXIKaWYodHlwZW9mIHQ9PSJmdW5jdGlvbiIpdD1bdF0KaWYodC5jb25zdHJ1Y3Rvcj09
-QXJyYXkpZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCmlmKHR5cGVvZiByPT0iZnVuY3Rpb24i
-KW49cihuKXx8bn19cT1uLmdldFRhZwpwPW4uZ2V0VW5rbm93blRhZwpvPW4ucHJvdG90eXBlRm9yVGFn
-CiQuaUs9bmV3IEguZnkocSkKJC5pSD1uZXcgSC5meihwKQokLmlUPW5ldyBILmZBKG8pfSwKYnU6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gYShiKXx8Yn0sCmpNOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgdD1i
-PyJtIjoiIixzPWM/IiI6ImkiLHI9ZD8idSI6IiIscT1lPyJzIjoiIixwPWY/ImciOiIiLG89ZnVuY3Rp
-b24oZyxoKXt0cnl7cmV0dXJuIG5ldyBSZWdFeHAoZyxoKX1jYXRjaChuKXtyZXR1cm4gbn19KGEsdCtz
-K3IrcStwKQppZihvIGluc3RhbmNlb2YgUmVnRXhwKXJldHVybiBvCnRocm93IEguYShQLkEoIklsbGVn
-YWwgUmVnRXhwIHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51bGwpKX0sCmxEOmZ1bmN0aW9uKGEp
-e2lmKC9bW1xde30oKSorPy5cXF4kfF0vLnRlc3QoYSkpcmV0dXJuIGEucmVwbGFjZSgvW1tcXXt9KCkq
-Kz8uXFxeJHxdL2csIlxcJCYiKQpyZXR1cm4gYX0sCmJ6OmZ1bmN0aW9uIGJ6KGEsYil7dGhpcy5hPWEK
-dGhpcy4kdGk9Yn0sCmJ5OmZ1bmN0aW9uIGJ5KCl7fSwKYUo6ZnVuY3Rpb24gYUooYSxiLGMsZCl7dmFy
-IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKY0o6ZnVuY3Rpb24gY0ooYSxiLGMsZCxl
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uZj1lfSwKZWU6ZnVuY3Rpb24gZWUo
-YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKZWo6ZnVuY3Rpb24gZWooYSxiLGMsZCxl
-LGYpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWZ9LApjVjpmdW5j
-dGlvbiBjVihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKY0w6ZnVuY3Rpb24gY0woYSxiLGMpe3RoaXMu
-YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKZGE6ZnVuY3Rpb24gZGEoYSl7dGhpcy5hPWF9LApmUjpmdW5j
-dGlvbiBmUihhKXt0aGlzLmE9YX0sCmNnOmZ1bmN0aW9uIGNnKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxs
-fSwKYUk6ZnVuY3Rpb24gYUkoKXt9LApkODpmdW5jdGlvbiBkOCgpe30sCmQzOmZ1bmN0aW9uIGQzKCl7
-fSwKYjY6ZnVuY3Rpb24gYjYoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9
-ZH0sCmQwOmZ1bmN0aW9uIGQwKGEpe3RoaXMuYT1hfSwKZGc6ZnVuY3Rpb24gZGcoYSl7dGhpcy5hPWF9
-LAphbjpmdW5jdGlvbiBhbihhKXt2YXIgXz10aGlzCl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVs
-bApfLnI9MApfLiR0aT1hfSwKZTg6ZnVuY3Rpb24gZTgoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1i
-Cl8uZD1fLmM9bnVsbH0sCmFQOmZ1bmN0aW9uIGFQKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmJM
-OmZ1bmN0aW9uIGJMKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0
-aT1jfSwKZnk6ZnVuY3Rpb24gZnkoYSl7dGhpcy5hPWF9LApmejpmdW5jdGlvbiBmeihhKXt0aGlzLmE9
-YX0sCmZBOmZ1bmN0aW9uIGZBKGEpe3RoaXMuYT1hfSwKY0s6ZnVuY3Rpb24gY0soYSxiKXt2YXIgXz10
-aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbH0sCmtYOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKak86
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBJbnQ4QXJyYXkoYSl9LAphcjpmdW5jdGlvbihhLGIsYyl7aWYo
-YT4+PjAhPT1hfHxhPj1jKXRocm93IEguYShILmIxKGIsYSkpfSwKa1U6ZnVuY3Rpb24oYSxiLGMpe3Zh
-ciB0CmlmKCEoYT4+PjAhPT1hKSl0PWI+Pj4wIT09Ynx8YT5ifHxiPmMKZWxzZSB0PSEwCmlmKHQpdGhy
-b3cgSC5hKEgubGwoYSxiLGMpKQpyZXR1cm4gYn0sCkM6ZnVuY3Rpb24gQygpe30sCmJROmZ1bmN0aW9u
-IGJRKCl7fSwKYVI6ZnVuY3Rpb24gYVIoKXt9LApiUjpmdW5jdGlvbiBiUigpe30sCmNQOmZ1bmN0aW9u
-IGNQKCl7fSwKY1E6ZnVuY3Rpb24gY1EoKXt9LApjUjpmdW5jdGlvbiBjUigpe30sCmNTOmZ1bmN0aW9u
-IGNTKCl7fSwKY1Q6ZnVuY3Rpb24gY1QoKXt9LApiUzpmdW5jdGlvbiBiUygpe30sCmFTOmZ1bmN0aW9u
-IGFTKCl7fSwKYzk6ZnVuY3Rpb24gYzkoKXt9LApjYTpmdW5jdGlvbiBjYSgpe30sCmNiOmZ1bmN0aW9u
-IGNiKCl7fSwKY2M6ZnVuY3Rpb24gY2MoKXt9LAppMDpmdW5jdGlvbihhLGIpe3ZhciB0PWIuZApyZXR1
-cm4gdD09bnVsbD9iLmQ9SC5mMChhLCJiRSIsW2IuUV0pOnR9LAppMTpmdW5jdGlvbihhKXt2YXIgdD1h
-LnoKaWYodD09PTZ8fHQ9PT03fHx0PT09OClyZXR1cm4gSC5pMShhLlEpCnJldHVybiB0PT09MTF8fHQ9
-PT0xMn0sCmsyOmZ1bmN0aW9uKGEpe3JldHVybiBhLmRifSwKZnA6ZnVuY3Rpb24oYSl7cmV0dXJuIEgu
-aGModi50eXBlVW5pdmVyc2UsYSl9LApsazpmdW5jdGlvbihhKXt2YXIgdD1hLiRTCmlmKHQhPW51bGwp
-e2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1cm4gSC5pTCh0KQpyZXR1cm4gYS4kUygpfXJldHVybiBu
-dWxsfSwKaHQ6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihILmkxKGIpKWlmKGEgaW5zdGFuY2VvZiBILmFJ
-KXt0PUgubGsoYSkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gSC5hOChhKX0sCmE4OmZ1bmN0aW9u
-KGEpe3ZhciB0CmlmKGEgaW5zdGFuY2VvZiBQLnQpe3Q9YS4kdGkKcmV0dXJuIHQhPW51bGw/dDpILmhs
-KGEpfWlmKEFycmF5LmlzQXJyYXkoYSkpcmV0dXJuIEguWihhKQpyZXR1cm4gSC5obChKLmFFKGEpKX0s
-Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9YS4kdGkscz11LmIKaWYodD09bnVsbClyZXR1cm4gcwppZih0LmNv
-bnN0cnVjdG9yIT09cy5jb25zdHJ1Y3RvcilyZXR1cm4gcwpyZXR1cm4gdH0sCnY6ZnVuY3Rpb24oYSl7
-dmFyIHQ9YS4kdGkKcmV0dXJuIHQhPW51bGw/dDpILmhsKGEpfSwKaGw6ZnVuY3Rpb24oYSl7dmFyIHQ9
-YS5jb25zdHJ1Y3RvcixzPXQuJGNjYWNoZQppZihzIT1udWxsKXJldHVybiBzCnJldHVybiBILmwxKGEs
-dCl9LApsMTpmdW5jdGlvbihhLGIpe3ZhciB0PWEgaW5zdGFuY2VvZiBILmFJP2EuX19wcm90b19fLl9f
-cHJvdG9fXy5jb25zdHJ1Y3RvcjpiLHM9SC5rQih2LnR5cGVVbml2ZXJzZSx0Lm5hbWUpCmIuJGNjYWNo
-ZT1zCnJldHVybiBzfSwKaUw6ZnVuY3Rpb24oYSl7dmFyIHQscz1hLHI9di50eXBlcyxxPXJbc10KaWYo
-dHlwZW9mIHE9PSJzdHJpbmciKXt0PUguaGModi50eXBlVW5pdmVyc2UscSkKcltzXT10CnJldHVybiB0
-fXJldHVybiBxfSwKbDA6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy56LHE9SC5rWgppZihILmNx
-KHMpKXtxPUgubDUKcy5iPXMuYT1ILmtTfWVsc2UgaWYocj09PTkpe3Q9cy5kYgppZigiZiI9PT10KXE9
-SC5kSgplbHNlIGlmKCJUIj09PXQpcT1ILml5CmVsc2UgaWYoIlUiPT09dClxPUguaXkKZWxzZSBpZigi
-YyI9PT10KXE9SC5sMwplbHNlIGlmKCJ6Ij09PXQpcT1ILmZkCmVsc2V7cj1zLlEKaWYocy5jaC5ldmVy
-eShILmNxKSl7cy54PSIkaSIrcgpxPUgubDR9fX1zLmM9cQpyZXR1cm4gcy5jKGEpfSwKa1o6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcwpyZXR1cm4gSC5EKHYudHlwZVVuaXZlcnNlLEguaHQoYSx0KSxudWxsLHQs
-bnVsbCl9LApsNDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLngKaWYoYSBpbnN0YW5jZW9mIFAudClyZXR1
-cm4hIWFbdF0KcmV0dXJuISFKLmFFKGEpW3RdfSwKa1k6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYT09bnVs
-bClyZXR1cm4gYQp0PXRoaXMKaWYodC5jKGEpKXJldHVybiBhCnRocm93IEguYShILmtqKEguZXkoYSxI
-Lmh0KGEsdCksSC5QKHQsbnVsbCkpKSl9LApsXzpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJl
-dHVybiBhCnQ9dGhpcwppZih0LmMoYSkpcmV0dXJuIGEKdGhyb3cgSC5hKEguaWcoSC5leShhLEguaHQo
-YSx0KSxILlAodCxudWxsKSkpKX0sCmRMOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PW51bGwKaWYoSC5E
-KHYudHlwZVVuaXZlcnNlLGEsdCxiLHQpKXJldHVybiBhCnRocm93IEguYShILmlnKCJUaGUgdHlwZSBh
-cmd1bWVudCAnIitILmIoSC5QKGEsdCkpKyInIGlzIG5vdCBhIHN1YnR5cGUgb2YgdGhlIHR5cGUgdmFy
-aWFibGUgYm91bmQgJyIrSC5iKEguUChiLHQpKSsiJyBvZiB0eXBlIHZhcmlhYmxlICciK2MrIicgaW4g
-JyIrSC5iKGQpKyInLiIpKX0sCmV5OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLmFNKGEpLHM9SC5QKGI9
-PW51bGw/SC5hOChhKTpiLG51bGwpCnJldHVybiB0KyI6IHR5cGUgJyIrSC5iKHMpKyInIGlzIG5vdCBh
-IHN1YnR5cGUgb2YgdHlwZSAnIitILmIoYykrIicifSwKa2o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBI
-LmMxKCJDYXN0RXJyb3I6ICIrYSl9LApkajpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5jMSgiQ2Fz
-dEVycm9yOiAiK0guZXkoYSxudWxsLGIpKX0sCmlnOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5jaCgi
-VHlwZUVycm9yOiAiK2EpfSwKZEQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguY2goIlR5cGVFcnJv
-cjogIitILmV5KGEsbnVsbCxiKSl9LApsNTpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCmtTOmZ1bmN0aW9u
-KGEpe3JldHVybiBhfSwKZmQ6ZnVuY3Rpb24oYSl7cmV0dXJuITA9PT1hfHwhMT09PWF9LAptajpmdW5j
-dGlvbihhKXtpZighMD09PWF8fCExPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93
-IEguYShILmRqKGEsImJvb2wiKSl9LApoZzpmdW5jdGlvbihhKXtpZighMD09PWF8fCExPT09YSlyZXR1
-cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYShILmREKGEsImJvb2wiKSl9LAptazpmdW5j
-dGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0
-aHJvdyBILmEoSC5kaihhLCJkb3VibGUiKSl9LAptbzpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51
-bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmEoSC5kRChhLCJkb3VibGUi
-KSl9LApkSjpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEp
-PT09YX0sCm1sOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09
-PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmEoSC5kaihhLCJpbnQiKSl9LAp4
-OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWEpcmV0dXJu
-IGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmEoSC5kRChhLCJpbnQiKSl9LAppeTpmdW5jdGlv
-bihhKXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKbW06ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9
-PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5hKEguZGooYSwibnVt
-IikpfSwKbXA6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51
-bGwpcmV0dXJuIGEKdGhyb3cgSC5hKEguZEQoYSwibnVtIikpfSwKbDM6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHR5cGVvZiBhPT0ic3RyaW5nIn0sCm1uOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIily
-ZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYShILmRqKGEsIlN0cmluZyIpKX0sCm86
-ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJu
-IGEKdGhyb3cgSC5hKEguZEQoYSwiU3RyaW5nIikpfSwKbGE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIK
-Zm9yKHQ9IiIscz0iIixyPTA7cjxhLmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMuYS5CKHMsSC5QKGFbcl0s
-YikpCnJldHVybiB0fSwKaXQ6ZnVuY3Rpb24oYTAsYTEsYTIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxr
-LGosaSxoLGcsZixlLGQsYyxiLGE9IiwgIgppZihhMiE9bnVsbCl7dD1hMi5sZW5ndGgKaWYoYTE9PW51
-bGwpe2ExPUgubihbXSx1LnMpCnM9bnVsbH1lbHNlIHM9YTEubGVuZ3RoCnI9YTEubGVuZ3RoCmZvcihx
-PXQ7cT4wOy0tcSlDLmIuayhhMSwiVCIrKHIrcSkpCmZvcihwPSI8IixvPSIiLHE9MDtxPHQ7KytxLG89
-YSl7cCs9bwpuPWExLmxlbmd0aAptPW4tMS1xCmlmKG08MClyZXR1cm4gSC5pKGExLG0pCnA9Qy5hLkIo
-cCxhMVttXSkKbD1hMltxXQppZighSC5jcShsKSlwKz1DLmEuQigiIGV4dGVuZHMgIixILlAobCxhMSkp
-fXArPSI+In1lbHNle3A9IiIKcz1udWxsfW49YTAuUQprPWEwLmNoCmo9ay5hCmk9ai5sZW5ndGgKaD1r
-LmIKZz1oLmxlbmd0aApmPWsuYwplPWYubGVuZ3RoCmQ9SC5QKG4sYTEpCmZvcihjPSIiLGI9IiIscT0w
-O3E8aTsrK3EsYj1hKWMrPUMuYS5CKGIsSC5QKGpbcV0sYTEpKQppZihnPjApe2MrPWIrIlsiCmZvcihi
-PSIiLHE9MDtxPGc7KytxLGI9YSljKz1DLmEuQihiLEguUChoW3FdLGExKSkKYys9Il0ifWlmKGU+MCl7
-Yys9YisieyIKZm9yKGI9IiIscT0wO3E8ZTtxKz0yLGI9YSljKz1DLmEuQihiLEguUChmW3ErMV0sYTEp
-KSsiICIrZltxXQpjKz0ifSJ9aWYocyE9bnVsbClhMS5sZW5ndGg9cwpyZXR1cm4gcCsiKCIrYysiKSA9
-PiAiK0guYihkKX0sClA6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPWEuegppZihwPT09NSlyZXR1
-cm4iZXJhc2VkIgppZihwPT09MilyZXR1cm4iZHluYW1pYyIKaWYocD09PTMpcmV0dXJuInZvaWQiCmlm
-KHA9PT0xKXJldHVybiJOZXZlciIKaWYocD09PTQpcmV0dXJuImFueSIKaWYocD09PTYpcmV0dXJuIEgu
-YihILlAoYS5RLGIpKSsiKiIKaWYocD09PTcpcmV0dXJuIEguYihILlAoYS5RLGIpKSsiPyIKaWYocD09
-PTgpcmV0dXJuIkZ1dHVyZU9yPCIrSC5iKEguUChhLlEsYikpKyI+IgppZihwPT09OSl7dD1ILmxkKGEu
-USkKcz1hLmNoCnJldHVybiBzLmxlbmd0aCE9PTA/dCsoIjwiK0gubGEocyxiKSsiPiIpOnR9aWYocD09
-PTExKXJldHVybiBILml0KGEsYixudWxsKQppZihwPT09MTIpcmV0dXJuIEguaXQoYS5RLGIsYS5jaCkK
-aWYocD09PTEzKXtyPWEuUQpxPWIubGVuZ3RoCnI9cS0xLXIKaWYocjwwfHxyPj1xKXJldHVybiBILmko
-YixyKQpyZXR1cm4gYltyXX1yZXR1cm4iPyJ9LApsZDpmdW5jdGlvbihhKXt2YXIgdCxzPUguaVgoYSkK
-aWYocyE9bnVsbClyZXR1cm4gcwp0PSJtaW5pZmllZDoiK2EKcmV0dXJuIHR9LAppajpmdW5jdGlvbihh
-LGIpe3ZhciB0PWEudFJbYl0KZm9yKDt0eXBlb2YgdD09InN0cmluZyI7KXQ9YS50Ult0XQpyZXR1cm4g
-dH0sCmtCOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvPWEuZVQsbj1vW2JdCmlmKG49PW51bGwp
-cmV0dXJuIEguaGMoYSxiKQplbHNlIGlmKHR5cGVvZiBuPT0ibnVtYmVyIil7dD1uCnM9SC5jaShhLDUs
-IiMiKQpyPVtdCmZvcihxPTA7cTx0OysrcSlyLnB1c2gocykKcD1ILmYwKGEsYixyKQpvW2JdPXAKcmV0
-dXJuIHB9ZWxzZSByZXR1cm4gbn0sCmt6OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguaXIoYS50UixiKX0s
-Cmt5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguaXIoYS5lVCxiKX0sCmhjOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscz1hLmVDLHI9cy5nZXQoYikKaWYociE9bnVsbClyZXR1cm4gcgp0PUguaWkoYSxudWxsLGIpCnMu
-c2V0KGIsdCkKcmV0dXJuIHR9LApkRjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPWIuY3gKaWYocj09
-bnVsbClyPWIuY3g9bmV3IE1hcCgpCnQ9ci5nZXQoYykKaWYodCE9bnVsbClyZXR1cm4gdApzPUguaWko
-YSxiLGMpCnIuc2V0KGMscykKcmV0dXJuIHN9LAprQTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9
-Yi5jeQppZihxPT1udWxsKXE9Yi5jeT1uZXcgTWFwKCkKdD1jLmRiCnM9cS5nZXQodCkKaWYocyE9bnVs
-bClyZXR1cm4gcwpyPUguaWgoYSxiLGMuej09PTEwP2MuY2g6W2NdKQpxLnNldCh0LHIpCnJldHVybiBy
-fSwKaWk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgua3IoSC5rbihhLGIsYykpCnJldHVybiB0fSwKYnA6
-ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLmRiCmEuZUMuc2V0KHQsYikKYi5hPUgua1kKYi5iPUgubF8KYi5j
-PUgubDAKcmV0dXJuIGJ9LApjaTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1hLmVDLmdldChjKQppZihz
-IT1udWxsKXJldHVybiBzCnQ9bmV3IEguYWYobnVsbCxudWxsLG51bGwpCnQuej1iCnQuZGI9YwpyZXR1
-cm4gSC5icChhLHQpfSwKaGI6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1hLmVDLmdldChkKQppZihz
-IT1udWxsKXJldHVybiBzCnQ9bmV3IEguYWYobnVsbCxudWxsLG51bGwpCnQuej1iCnQuUT1jCnQuZGI9
-ZApyZXR1cm4gSC5icChhLHQpfSwKa3c6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPSIiK2IrIl4iLHI9YS5l
-Qy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PW5ldyBILmFmKG51bGwsbnVsbCxudWxsKQp0Lno9
-MTMKdC5RPWIKdC5kYj1zCnJldHVybiBILmJwKGEsdCl9LApkRTpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
-cT1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9MDtyPHE7KytyLHM9IiwiKXQrPXMrYVtyXS5kYgpyZXR1
-cm4gdH0sCmt1OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbz1hLmxlbmd0aApmb3IodD0iIixzPSIi
-LHI9MDtyPG87cis9MixzPSIsIil7cT1hW3JdCnA9YVtyKzFdLmRiCnQrPXMrcSsiOiIrcH1yZXR1cm4g
-dH0sCmYwOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9YgppZihjLmxlbmd0aCE9PTApcis9IjwiK0gu
-ZEUoYykrIj4iCnQ9YS5lQy5nZXQocikKaWYodCE9bnVsbClyZXR1cm4gdApzPW5ldyBILmFmKG51bGws
-bnVsbCxudWxsKQpzLno9OQpzLlE9YgpzLmNoPWMKaWYoYy5sZW5ndGg+MClzLmQ9Y1swXQpzLmRiPXIK
-cmV0dXJuIEguYnAoYSxzKX0sCmloOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwCmlmKGIuej09
-PTEwKXt0PWIuUQpzPWIuY2guY29uY2F0KGMpfWVsc2V7cz1jCnQ9Yn1yPXQuZGIrIjsiKygiPCIrSC5k
-RShzKSsiPiIpCnE9YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpwPW5ldyBILmFmKG51bGws
-bnVsbCxudWxsKQpwLno9MTAKcC5RPXQKcC5jaD1zCnAuZGI9cgpyZXR1cm4gSC5icChhLHApfSwKa3Y6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIuZGIscD1jLmEsbz1wLmxlbmd0aCxuPWMuYixtPW4u
-bGVuZ3RoLGw9Yy5jLGs9bC5sZW5ndGgsaj0iKCIrSC5kRShwKQppZihtPjApais9KG8+MD8iLCI6IiIp
-KyJbIitILmRFKG4pKyJdIgppZihrPjApais9KG8+MD8iLCI6IiIpKyJ7IitILmt1KGwpKyJ9Igp0PXEr
-KGorIikiKQpzPWEuZUMuZ2V0KHQpCmlmKHMhPW51bGwpcmV0dXJuIHMKcj1uZXcgSC5hZihudWxsLG51
-bGwsbnVsbCkKci56PTExCnIuUT1iCnIuY2g9YwpyLmRiPXQKcmV0dXJuIEguYnAoYSxyKX0sCmt4OmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuZGIrIjwiK0guZEUoYykrIj4iLHI9YS5lQy5nZXQocykKaWYo
-ciE9bnVsbClyZXR1cm4gcgp0PW5ldyBILmFmKG51bGwsbnVsbCxudWxsKQp0Lno9MTIKdC5RPWIKdC5j
-aD1jCnQuZGI9cwpyZXR1cm4gSC5icChhLHQpfSwKa246ZnVuY3Rpb24oYSxiLGMpe3JldHVybnt1OmEs
-ZTpiLHI6YyxzOltdLHA6MH19LAprcjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxq
-LGksaCxnPWEucixmPWEucwpmb3IodD1nLmxlbmd0aCxzPTA7czx0Oyl7cj1nLmNoYXJDb2RlQXQocykK
-aWYocj49NDgmJnI8PTU3KXM9SC5rbyhzKzEscixnLGYpCmVsc2UgaWYoKCgocnwzMik+Pj4wKS05NyY2
-NTUzNSk8MjZ8fHI9PT05NXx8cj09PTM2KXM9SC5pZChhLHMsZyxmLCExKQplbHNlIGlmKHI9PT00Nilz
-PUguaWQoYSxzLGcsZiwhMCkKZWxzZXsrK3MKc3dpdGNoKHIpe2Nhc2UgNDQ6YnJlYWsKY2FzZSA1ODpi
-cmVhawpjYXNlIDU5OmYucHVzaChILmFEKGEudSxhLmUsZi5wb3AoKSkpCmJyZWFrCmNhc2UgOTQ6Zi5w
-dXNoKEgua3coYS51LGYucG9wKCkpKQpicmVhawpjYXNlIDM1OmYucHVzaChILmNpKGEudSw1LCIjIikp
-CmJyZWFrCmNhc2UgNjQ6Zi5wdXNoKEguY2koYS51LDIsIkAiKSkKYnJlYWsKY2FzZSAxMjY6Zi5wdXNo
-KEguY2koYS51LDMsIn4iKSkKYnJlYWsKY2FzZSA2MDpmLnB1c2goYS5wKQphLnA9Zi5sZW5ndGgKYnJl
-YWsKY2FzZSA2MjpxPWEudQpwPWYuc3BsaWNlKGEucCkKSC5oYShhLnUsYS5lLHApCmEucD1mLnBvcCgp
-Cm89Zi5wb3AoKQppZih0eXBlb2Ygbz09InN0cmluZyIpZi5wdXNoKEguZjAocSxvLHApKQplbHNle249
-SC5hRChxLGEuZSxvKQpzd2l0Y2gobi56KXtjYXNlIDExOmYucHVzaChILmt4KHEsbixwKSkKYnJlYWsK
-ZGVmYXVsdDpmLnB1c2goSC5paChxLG4scCkpCmJyZWFrfX1icmVhawpjYXNlIDM4Okgua3AoYSxmKQpi
-cmVhawpjYXNlIDQyOm09YS51Cmw9SC5hRChtLGEuZSxmLnBvcCgpKQpmLnB1c2goSC5oYihtLDYsbCxs
-LmRiKyIqIikpCmJyZWFrCmNhc2UgNjM6bT1hLnUKbD1ILmFEKG0sYS5lLGYucG9wKCkpCmYucHVzaChI
-LmhiKG0sNyxsLGwuZGIrIj8iKSkKYnJlYWsKY2FzZSA0NzptPWEudQpsPUguYUQobSxhLmUsZi5wb3Ao
-KSkKZi5wdXNoKEguaGIobSw4LGwsbC5kYisiLyIpKQpicmVhawpjYXNlIDQwOmYucHVzaChhLnApCmEu
-cD1mLmxlbmd0aApicmVhawpjYXNlIDQxOnE9YS51Cms9bmV3IEguZUIoKQpqPXEuc0VBCmk9cS5zRUEK
-bz1mLnBvcCgpCmlmKHR5cGVvZiBvPT0ibnVtYmVyIilzd2l0Y2gobyl7Y2FzZS0xOmo9Zi5wb3AoKQpi
-cmVhawpjYXNlLTI6aT1mLnBvcCgpCmJyZWFrCmRlZmF1bHQ6Zi5wdXNoKG8pCmJyZWFrfWVsc2UgZi5w
-dXNoKG8pCnA9Zi5zcGxpY2UoYS5wKQpILmhhKGEudSxhLmUscCkKYS5wPWYucG9wKCkKay5hPXAKay5i
-PWoKay5jPWkKZi5wdXNoKEgua3YocSxILmFEKHEsYS5lLGYucG9wKCkpLGspKQpicmVhawpjYXNlIDkx
-OmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDkzOnA9Zi5zcGxpY2UoYS5wKQpILmhh
-KGEudSxhLmUscCkKYS5wPWYucG9wKCkKZi5wdXNoKHApCmYucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6
-Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgMTI1OnA9Zi5zcGxpY2UoYS5wKQpILmtz
-KGEudSxhLmUscCkKYS5wPWYucG9wKCkKZi5wdXNoKHApCmYucHVzaCgtMikKYnJlYWsKZGVmYXVsdDp0
-aHJvdyJCYWQgY2hhcmFjdGVyICIrcn19fWg9Zi5wb3AoKQpyZXR1cm4gSC5hRChhLnUsYS5lLGgpfSwK
-a286ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5ndGg7YTx0OysrYSl7
-cz1jLmNoYXJDb2RlQXQoYSkKaWYoIShzPj00OCYmczw9NTcpKWJyZWFrCnI9cioxMCsocy00OCl9ZC5w
-dXNoKHIpCnJldHVybiBhfSwKaWQ6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbj1i
-KzEKZm9yKHQ9Yy5sZW5ndGg7bjx0Oysrbil7cz1jLmNoYXJDb2RlQXQobikKaWYocz09PTQ2KXtpZihl
-KWJyZWFrCmU9ITB9ZWxzZXtpZighKCgoKHN8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxzPT09OTV8fHM9
-PT0zNikpcj1zPj00OCYmczw9NTcKZWxzZSByPSEwCmlmKCFyKWJyZWFrfX1xPWMuc3Vic3RyaW5nKGIs
-bikKaWYoZSl7dD1hLnUKcD1hLmUKaWYocC56PT09MTApcD1wLlEKbz1ILmlqKHQscC5RKVtxXQppZihv
-PT1udWxsKUguYWsoJ05vICInK3ErJyIgaW4gIicrSC5rMihwKSsnIicpCmQucHVzaChILmRGKHQscCxv
-KSl9ZWxzZSBkLnB1c2gocSkKcmV0dXJuIG59LAprcDpmdW5jdGlvbihhLGIpe3ZhciB0PWIucG9wKCkK
-aWYoMD09PXQpe2IucHVzaChILmNpKGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQpe2IucHVzaChI
-LmNpKGEudSw0LCIxJiIpKQpyZXR1cm59dGhyb3cgSC5hKFAuZlkoIlVuZXhwZWN0ZWQgZXh0ZW5kZWQg
-b3BlcmF0aW9uICIrSC5iKHQpKSl9LAphRDpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGM9PSJzdHJp
-bmciKXJldHVybiBILmYwKGEsYyxhLnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIpcmV0dXJu
-IEgua3EoYSxiLGMpCmVsc2UgcmV0dXJuIGN9LApoYTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1jLmxl
-bmd0aApmb3IodD0wO3Q8czsrK3QpY1t0XT1ILmFEKGEsYixjW3RdKX0sCmtzOmZ1bmN0aW9uKGEsYixj
-KXt2YXIgdCxzPWMubGVuZ3RoCmZvcih0PTE7dDxzO3QrPTIpY1t0XT1ILmFEKGEsYixjW3RdKX0sCmtx
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9Yi56CmlmKHI9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIu
-UQp0PWIuY2gKcz10Lmxlbmd0aAppZihjPD1zKXJldHVybiB0W2MtMV0KYy09cwpiPWIuUQpyPWIuen1l
-bHNlIGlmKGM9PT0wKXJldHVybiBiCmlmKHIhPT05KXRocm93IEguYShQLmZZKCJJbmRleGVkIGJhc2Ug
-bXVzdCBiZSBhbiBpbnRlcmZhY2UgdHlwZSIpKQp0PWIuY2gKaWYoYzw9dC5sZW5ndGgpcmV0dXJuIHRb
-Yy0xXQp0aHJvdyBILmEoUC5mWSgiQmFkIGluZGV4ICIrYysiIGZvciAiK2IuaSgwKSkpfSwKRDpmdW5j
-dGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrCmlmKGI9PT1kKXJldHVybiEwCmlm
-KEguY3EoZCkpcmV0dXJuITAKdD1iLnoKaWYodD09PTQpcmV0dXJuITAKaWYoSC5jcShiKSlyZXR1cm4h
-MQppZihiPT09dS5QKXJldHVybiEwCnM9dD09PTEzCmlmKHMpaWYoSC5EKGEsY1tiLlFdLGMsZCxlKSly
-ZXR1cm4hMApyPWQuegppZih0PT09NilyZXR1cm4gSC5EKGEsYi5RLGMsZCxlKQppZihyPT09Nil7cT1k
-LlEKcmV0dXJuIEguRChhLGIsYyxxLGUpfWlmKHQ9PT04KXtpZighSC5EKGEsYi5RLGMsZCxlKSlyZXR1
-cm4hMQpyZXR1cm4gSC5EKGEsSC5pMChhLGIpLGMsZCxlKX1pZih0PT09Nyl7cT1ILkQoYSxiLlEsYyxk
-LGUpCnJldHVybiBxfWlmKHI9PT04KXtpZihILkQoYSxiLGMsZC5RLGUpKXJldHVybiEwCnJldHVybiBI
-LkQoYSxiLGMsSC5pMChhLGQpLGUpfWlmKHI9PT03KXtxPUguRChhLGIsYyxkLlEsZSkKcmV0dXJuIHF9
-aWYocylyZXR1cm4hMQpxPXQhPT0xMQppZigoIXF8fHQ9PT0xMikmJmQ9PT11LlopcmV0dXJuITAKaWYo
-cj09PTEyKXtpZihiPT09dS5nKXJldHVybiEwCmlmKHQhPT0xMilyZXR1cm4hMQpwPWIuY2gKbz1kLmNo
-Cm49cC5sZW5ndGgKaWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmZvcihxPXUuYXYsbT0wO208bjsrK20p
-e2w9cFttXQprPW9bbV0KcS5iKGwpCnEuYihrKQppZighSC5EKGEsbCxjLGssZSl8fCFILkQoYSxrLGUs
-bCxjKSlyZXR1cm4hMX1jPWM9PW51bGw/cDpwLmNvbmNhdChjKQplPWU9PW51bGw/bzpvLmNvbmNhdChl
-KQpyZXR1cm4gSC5pdyhhLGIuUSxjLGQuUSxlKX1pZihyPT09MTEpe2lmKGI9PT11LmcpcmV0dXJuITAK
-aWYocSlyZXR1cm4hMQpyZXR1cm4gSC5pdyhhLGIsYyxkLGUpfWlmKHQ9PT05KXtpZihyIT09OSlyZXR1
-cm4hMQpyZXR1cm4gSC5sMihhLGIsYyxkLGUpfXJldHVybiExfSwKaXc6ZnVuY3Rpb24oYTAsYTEsYTIs
-YTMsYTQpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEKaWYoIUguRChh
-MCxhMS5RLGEyLGEzLlEsYTQpKXJldHVybiExCnQ9YTEuY2gKcz1hMy5jaApyPXQuYQpxPXMuYQpwPXIu
-bGVuZ3RoCm89cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5iCmw9cy5iCms9bS5sZW5n
-dGgKaj1sLmxlbmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxwOysraSl7aD1yW2ldCmlm
-KCFILkQoYTAscVtpXSxhNCxoLGEyKSlyZXR1cm4hMX1mb3IoaT0wO2k8bjsrK2kpe2g9bVtpXQppZigh
-SC5EKGEwLHFbcCtpXSxhNCxoLGEyKSlyZXR1cm4hMX1mb3IoaT0wO2k8ajsrK2kpe2g9bVtuK2ldCmlm
-KCFILkQoYTAsbFtpXSxhNCxoLGEyKSlyZXR1cm4hMX1nPXQuYwpmPXMuYwplPWcubGVuZ3RoCmQ9Zi5s
-ZW5ndGgKZm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihpPj1lKXJldHVybiExCmE9Z1tp
-XQppKz0yfXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFdCmlmKCFILkQoYTAsZltjKzFd
-LGE0LGgsYTIpKXJldHVybiExfXJldHVybiEwfSwKbDI6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGw9Yi5RLGs9ZC5RCmlmKGw9PT1rKXt0PWIuY2gKcz1kLmNoCnI9dC5sZW5ndGgK
-Zm9yKHE9MDtxPHI7KytxKXtwPXRbcV0Kbz1zW3FdCmlmKCFILkQoYSxwLGMsbyxlKSlyZXR1cm4hMX1y
-ZXR1cm4hMH1uPUguaWooYSxsKQppZihuPT1udWxsKXJldHVybiExCm09bltrXQppZihtPT1udWxsKXJl
-dHVybiExCnI9bS5sZW5ndGgKcz1kLmNoCmZvcihxPTA7cTxyOysrcSlpZighSC5EKGEsSC5kRihhLGIs
-bVtxXSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKY3E6ZnVuY3Rpb24oYSl7dmFyIHQscwpp
-ZihhPT09dS5LKXJldHVybiEwCnQ9YS56CmlmKHQhPT0yKWlmKHQhPT0zKWlmKHQhPT00KWlmKHQhPT01
-KXM9dD09PTgmJkguY3EoYS5RKQplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAK
-cmV0dXJuIHN9LAppcjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1PYmplY3Qua2V5cyhiKSxxPXIubGVu
-Z3RoCmZvcih0PTA7dDxxOysrdCl7cz1yW3RdCmFbc109YltzXX19LAphZjpmdW5jdGlvbiBhZihhLGIs
-Yyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLnk9Xy54PV8uZD1udWxsCl8uej0wCl8uZGI9
-Xy5jeT1fLmN4PV8uY2g9Xy5RPW51bGx9LAplQjpmdW5jdGlvbiBlQigpe3RoaXMuYz10aGlzLmI9dGhp
-cy5hPW51bGx9LApkcDpmdW5jdGlvbiBkcCgpe30sCmMxOmZ1bmN0aW9uIGMxKGEpe3RoaXMuYT1hfSwK
-Y2g6ZnVuY3Rpb24gY2goYSl7dGhpcy5hPWF9LAppTTpmdW5jdGlvbihhKXtyZXR1cm4gdS5kLmMoYSl8
-fHUuQS5jKGEpfHx1LncuYyhhKXx8dS5JLmMoYSl8fHUuRi5jKGEpfHx1Lmc0LmMoYSl8fHUuZzIuYyhh
-KX0sCmlYOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1thXX19LEo9ewpodjpm
-dW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmROOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxLHA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihwPT1udWxsKWlmKCQuaHM9PW51
-bGwpe0gubHUoKQpwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV19aWYocCE9bnVsbCl7dD1wLnAKaWYo
-ITE9PT10KXJldHVybiBwLmkKaWYoITA9PT10KXJldHVybiBhCnM9T2JqZWN0LmdldFByb3RvdHlwZU9m
-KGEpCmlmKHQ9PT1zKXJldHVybiBwLmkKaWYocC5lPT09cyl0aHJvdyBILmEoUC5lbCgiUmV0dXJuIGlu
-dGVyY2VwdG9yIGZvciAiK0guYih0KGEscCkpKSl9cj1hLmNvbnN0cnVjdG9yCnE9cj09bnVsbD9udWxs
-OnJbJC5oeSgpXQppZihxIT1udWxsKXJldHVybiBxCnE9SC5sQihhKQppZihxIT1udWxsKXJldHVybiBx
-CmlmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBDLlIKdD1PYmplY3QuZ2V0UHJvdG90eXBlT2Yo
-YSkKaWYodD09bnVsbClyZXR1cm4gQy5CCmlmKHQ9PT1PYmplY3QucHJvdG90eXBlKXJldHVybiBDLkIK
-aWYodHlwZW9mIHI9PSJmdW5jdGlvbiIpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShyLCQuaHkoKSx7dmFs
-dWU6Qy5uLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJl
-dHVybiBDLm59cmV0dXJuIEMubn0sCmpKOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CnJl
-dHVybiBhfSwKaFI6ZnVuY3Rpb24oYSl7aWYoYTwyNTYpc3dpdGNoKGEpe2Nhc2UgOTpjYXNlIDEwOmNh
-c2UgMTE6Y2FzZSAxMjpjYXNlIDEzOmNhc2UgMzI6Y2FzZSAxMzM6Y2FzZSAxNjA6cmV0dXJuITAKZGVm
-YXVsdDpyZXR1cm4hMX1zd2l0Y2goYSl7Y2FzZSA1NzYwOmNhc2UgODE5MjpjYXNlIDgxOTM6Y2FzZSA4
-MTk0OmNhc2UgODE5NTpjYXNlIDgxOTY6Y2FzZSA4MTk3OmNhc2UgODE5ODpjYXNlIDgxOTk6Y2FzZSA4
-MjAwOmNhc2UgODIwMTpjYXNlIDgyMDI6Y2FzZSA4MjMyOmNhc2UgODIzMzpjYXNlIDgyMzk6Y2FzZSA4
-Mjg3OmNhc2UgMTIyODg6Y2FzZSA2NTI3OTpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfX0sCmpLOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscwpmb3IodD1hLmxlbmd0aDtiPHQ7KXtzPUMuYS50KGEsYikKaWYocyE9
-PTMyJiZzIT09MTMmJiFKLmhSKHMpKWJyZWFrOysrYn1yZXR1cm4gYn0sCmpMOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscwpmb3IoO2I+MDtiPXQpe3Q9Yi0xCnM9Qy5hLnYoYSx0KQppZihzIT09MzImJnMhPT0xMyYm
-IUouaFIocykpYnJlYWt9cmV0dXJuIGJ9LAphRTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJl
-ciIpe2lmKE1hdGguZmxvb3IoYSk9PWEpcmV0dXJuIEouYkkucHJvdG90eXBlCnJldHVybiBKLmNJLnBy
-b3RvdHlwZX1pZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouYXgucHJvdG90eXBlCmlmKGE9PW51
-bGwpcmV0dXJuIEouYkoucHJvdG90eXBlCmlmKHR5cGVvZiBhPT0iYm9vbGVhbiIpcmV0dXJuIEouY0gu
-cHJvdG90eXBlCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLkYucHJvdG90eXBlCmlmKHR5
-cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYWQucHJvdG90
-eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLnQpcmV0dXJuIGEKcmV0dXJuIEouZE4oYSl9LAps
-bjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEouYmEucHJvdG90eXBlCmlm
-KHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5heC5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4g
-YQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5GLnByb3RvdHlwZQppZih0eXBlb2YgYSE9
-Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmFkLnByb3RvdHlwZQpyZXR1
-cm4gYX1pZihhIGluc3RhbmNlb2YgUC50KXJldHVybiBhCnJldHVybiBKLmROKGEpfSwKYV86ZnVuY3Rp
-b24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLmF4LnByb3RvdHlwZQppZihhPT1udWxs
-KXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLkYucHJvdG90eXBlCmlmKHR5
-cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYWQucHJvdG90
-eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLnQpcmV0dXJuIGEKcmV0dXJuIEouZE4oYSl9LApo
-cTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJl
-dHVybiBKLkYucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5j
-dGlvbiIpcmV0dXJuIEouYWQucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLnQpcmV0
-dXJuIGEKcmV0dXJuIEouZE4oYSl9LAphMDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIp
-cmV0dXJuIEouYXgucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoIShhIGluc3RhbmNlb2Yg
-UC50KSlyZXR1cm4gSi5iay5wcm90b3R5cGUKcmV0dXJuIGF9LApFOmZ1bmN0aW9uKGEpe2lmKGE9PW51
-bGwpcmV0dXJuIGEKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIily
-ZXR1cm4gSi5hZC5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAudClyZXR1cm4gYQpy
-ZXR1cm4gSi5kTihhKX0sCmpqOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZ0eXBl
-b2YgYj09Im51bWJlciIpcmV0dXJuIGErYgpyZXR1cm4gSi5sbihhKS5CKGEsYil9LApjczpmdW5jdGlv
-bihhLGIpe2lmKGE9PW51bGwpcmV0dXJuIGI9PW51bGwKaWYodHlwZW9mIGEhPSJvYmplY3QiKXJldHVy
-biBiIT1udWxsJiZhPT09YgpyZXR1cm4gSi5hRShhKS5HKGEsYil9LApmVzpmdW5jdGlvbihhLGIpe2lm
-KHR5cGVvZiBiPT09Im51bWJlciIpaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXl8fHR5cGVvZiBhPT0ic3Ry
-aW5nInx8SC5seChhLGFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0pKWlmKGI+Pj4wPT09YiYmYjxhLmxl
-bmd0aClyZXR1cm4gYVtiXQpyZXR1cm4gSi5hXyhhKS5qKGEsYil9LApqazpmdW5jdGlvbihhKXtyZXR1
-cm4gSi5FKGEpLmJNKGEpfSwKaEQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5hMChhKS50KGEsYil9LApq
-bDpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5FKGEpLmI3KGEsYixjLGQpfSwKam06ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gSi5ocShhKS5PKGEsYil9LApqbjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5F
-KGEpLmNiKGEsYixjLGQpfSwKam86ZnVuY3Rpb24oYSl7cmV0dXJuIEouRShhKS5nYzAoYSl9LAphbDpm
-dW5jdGlvbihhKXtyZXR1cm4gSi5FKGEpLmdDKGEpfSwKYnY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouYUUo
-YSkuZ3EoYSl9LAphOTpmdW5jdGlvbihhKXtyZXR1cm4gSi5ocShhKS5nRihhKX0sCmF0OmZ1bmN0aW9u
-KGEpe3JldHVybiBKLmFfKGEpLmdtKGEpfSwKZFA6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRShhKS5nYUco
-YSl9LApqcDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouaHEoYSkuYUYoYSxiLGMpfSwKanE6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gSi5hRShhKS5haChhLGIpfSwKaEU6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRShh
-KS5jbihhKX0sCmpyOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLmEwKGEpLmEwKGEsYixjLGQpfSwK
-aEY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRShhKS5idChhKX0sCmRROmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IEouRShhKS5zYWYoYSxiKX0sCmhHOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5FKGEpLmE2KGEsYixj
-KX0sCmN0OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5hMChhKS5TKGEsYixjKX0sCmpzOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIEouYTAoYSkuVShhLGIpfSwKaEg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLmEw
-KGEpLm4oYSxiLGMpfSwKanQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouYTAoYSkuY3IoYSl9LApiMjpmdW5j
-dGlvbihhKXtyZXR1cm4gSi5hRShhKS5pKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouYTAoYSku
-Y3MoYSl9LApJOmZ1bmN0aW9uIEkoKXt9LApjSDpmdW5jdGlvbiBjSCgpe30sCmJKOmZ1bmN0aW9uIGJK
-KCl7fSwKYXk6ZnVuY3Rpb24gYXkoKXt9LApjWjpmdW5jdGlvbiBjWigpe30sCmJrOmZ1bmN0aW9uIGJr
-KCl7fSwKYWQ6ZnVuY3Rpb24gYWQoKXt9LApGOmZ1bmN0aW9uIEYoYSl7dGhpcy4kdGk9YX0sCmU3OmZ1
-bmN0aW9uIGU3KGEpe3RoaXMuJHRpPWF9LAphRjpmdW5jdGlvbiBhRihhLGIsYyl7dmFyIF89dGhpcwpf
-LmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwKYmE6ZnVuY3Rpb24gYmEoKXt9LApiSTpm
-dW5jdGlvbiBiSSgpe30sCmNJOmZ1bmN0aW9uIGNJKCl7fSwKYXg6ZnVuY3Rpb24gYXgoKXt9fSxQPXsK
-a2Y6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9e30KaWYoc2VsZi5zY2hlZHVsZUltbWVkaWF0ZSE9bnVsbCly
-ZXR1cm4gUC5saCgpCmlmKHNlbGYuTXV0YXRpb25PYnNlcnZlciE9bnVsbCYmc2VsZi5kb2N1bWVudCE9
-bnVsbCl7dD1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpCnM9c2VsZi5kb2N1bWVudC5j
-cmVhdGVFbGVtZW50KCJzcGFuIikKci5hPW51bGwKbmV3IHNlbGYuTXV0YXRpb25PYnNlcnZlcihILmRN
-KG5ldyBQLmV0KHIpLDEpKS5vYnNlcnZlKHQse2NoaWxkTGlzdDp0cnVlfSkKcmV0dXJuIG5ldyBQLmVz
-KHIsdCxzKX1lbHNlIGlmKHNlbGYuc2V0SW1tZWRpYXRlIT1udWxsKXJldHVybiBQLmxpKCkKcmV0dXJu
-IFAubGooKX0sCmtnOmZ1bmN0aW9uKGEpe3NlbGYuc2NoZWR1bGVJbW1lZGlhdGUoSC5kTShuZXcgUC5l
-dSh1Lk0uYihhKSksMCkpfSwKa2g6ZnVuY3Rpb24oYSl7c2VsZi5zZXRJbW1lZGlhdGUoSC5kTShuZXcg
-UC5ldih1Lk0uYihhKSksMCkpfSwKa2k6ZnVuY3Rpb24oYSl7UC5oNyhDLk0sdS5NLmIoYSkpfSwKaDc6
-ZnVuY3Rpb24oYSxiKXt2YXIgdD1DLmMuYWIoYS5hLDEwMDApCnJldHVybiBQLmt0KHQ8MD8wOnQsYil9
-LAprdDpmdW5jdGlvbihhLGIpe3ZhciB0PW5ldyBQLmRDKCkKdC5iRihhLGIpCnJldHVybiB0fSwKaTk6
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKYi5hPTEKdHJ5e2EuYm4obmV3IFAuZUcoYiksbmV3IFAuZUgo
-YiksdS5QKX1jYXRjaChyKXt0PUguUShyKQpzPUguY3AocikKUC5sRihuZXcgUC5lSShiLHQscykpfX0s
-CmVGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxzPT09MjspYT10LmIoYS5j
-KQppZihzPj00KXtyPWIuYTkoKQpiLmE9YS5hCmIuYz1hLmMKUC5ibyhiLHIpfWVsc2V7cj11LnguYihi
-LmMpCmIuYT0yCmIuYz1hCmEuYjIocil9fSwKYm86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8s
-bixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7
-ITA7KXtxPXt9CnA9Yy5hPT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYihjLmMpClAuZmUoZSxlLGMu
-YixvLmEsby5iKX1yZXR1cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5hPW51bGwKUC5ibyhkLmEs
-Yil9Yz1kLmEKbT1jLmMKcS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsm
-MTUpPT09OH1lbHNlIGs9ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxp
-KX1lbHNlIGk9ITEKaWYoaSl7dC5iKG0pClAuZmUoZSxlLGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLncK
-aWYoaCE9PWopJC53PWoKZWxzZSBoPWUKYz1iLmMKaWYoKGMmMTUpPT09OCluZXcgUC5lTihkLHEsYixw
-KS4kMCgpCmVsc2UgaWYobCl7aWYoKGMmMSkhPT0wKW5ldyBQLmVNKHEsYixtKS4kMCgpfWVsc2UgaWYo
-KGMmMikhPT0wKW5ldyBQLmVMKGQscSxiKS4kMCgpCmlmKGghPW51bGwpJC53PWgKYz1xLmIKaWYoci5j
-KGMpKXtpZihjLmE+PTQpe2c9cy5iKGsuYykKay5jPW51bGwKYj1rLmFhKGcpCmsuYT1jLmEKay5jPWMu
-YwpkLmE9Ywpjb250aW51ZX1lbHNlIFAuZUYoYyxrKQpyZXR1cm59fWY9Yi5iCmc9cy5iKGYuYykKZi5j
-PW51bGwKYj1mLmFhKGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5kLmIobCkKZi5hPTQKZi5jPWx9
-ZWxzZXt0LmIobCkKZi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sCml6OmZ1bmN0aW9uKGEsYil7dmFyIHQ9
-dS5ZCmlmKHQuYyhhKSlyZXR1cm4gdC5iKGEpCnQ9dS55CmlmKHQuYyhhKSlyZXR1cm4gdC5iKGEpCnRo
-cm93IEguYShQLmZYKGEsIm9uRXJyb3IiLCJFcnJvciBoYW5kbGVyIG11c3QgYWNjZXB0IG9uZSBPYmpl
-Y3Qgb3Igb25lIE9iamVjdCBhbmQgYSBTdGFja1RyYWNlIGFzIGFyZ3VtZW50cywgYW5kIHJldHVybiBh
-IGEgdmFsaWQgcmVzdWx0IikpfSwKbDc6ZnVuY3Rpb24oKXt2YXIgdCxzCmZvcig7dD0kLmJzLHQhPW51
-bGw7KXskLmNvPW51bGwKcz10LmIKJC5icz1zCmlmKHM9PW51bGwpJC5jbj1udWxsCnQuYS4kMCgpfX0s
-CmxjOmZ1bmN0aW9uKCl7JC5obT0hMAp0cnl7UC5sNygpfWZpbmFsbHl7JC5jbz1udWxsCiQuaG09ITEK
-aWYoJC5icyE9bnVsbCkkLmhBKCkuJDEoUC5pSSgpKX19LAppRTpmdW5jdGlvbihhKXt2YXIgdD1uZXcg
-UC5kaChhKQppZigkLmJzPT1udWxsKXskLmJzPSQuY249dAppZighJC5obSkkLmhBKCkuJDEoUC5pSSgp
-KX1lbHNlICQuY249JC5jbi5iPXR9LApsYjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9JC5icwppZihyPT1u
-dWxsKXtQLmlFKGEpCiQuY289JC5jbgpyZXR1cm59dD1uZXcgUC5kaChhKQpzPSQuY28KaWYocz09bnVs
-bCl7dC5iPXIKJC5icz0kLmNvPXR9ZWxzZXt0LmI9cy5iCiQuY289cy5iPXQKaWYodC5iPT1udWxsKSQu
-Y249dH19LApsRjpmdW5jdGlvbihhKXt2YXIgdD1udWxsLHM9JC53CmlmKEMuZD09PXMpe1AuYnQodCx0
-LEMuZCxhKQpyZXR1cm59UC5idCh0LHQscyx1Lk0uYihzLmF6KGEpKSl9LAprNzpmdW5jdGlvbihhLGIp
-e3ZhciB0PSQudwppZih0PT09Qy5kKXJldHVybiBQLmg3KGEsdS5NLmIoYikpCnJldHVybiBQLmg3KGEs
-dS5NLmIodC5heihiKSkpfSwKZmU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD17fQp0LmE9ZApQLmxi
-KG5ldyBQLmZmKHQsZSkpfSwKaUE6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzPSQudwppZihzPT09
-YylyZXR1cm4gZC4kMCgpCiQudz1jCnQ9cwp0cnl7cz1kLiQwKCkKcmV0dXJuIHN9ZmluYWxseXskLnc9
-dH19LAppQjpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2YXIgdCxzPSQudwppZihzPT09YylyZXR1cm4g
-ZC4kMShlKQokLnc9Ywp0PXMKdHJ5e3M9ZC4kMShlKQpyZXR1cm4gc31maW5hbGx5eyQudz10fX0sCmw5
-OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpKXt2YXIgdCxzPSQudwppZihzPT09YylyZXR1cm4gZC4k
-MihlLGYpCiQudz1jCnQ9cwp0cnl7cz1kLiQyKGUsZikKcmV0dXJuIHN9ZmluYWxseXskLnc9dH19LApi
-dDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdAp1Lk0uYihkKQp0PUMuZCE9PWMKaWYodClkPSEoIXR8fCEx
-KT9jLmF6KGQpOmMuYzEoZCx1LkgpClAuaUUoZCl9LApldDpmdW5jdGlvbiBldChhKXt0aGlzLmE9YX0s
-CmVzOmZ1bmN0aW9uIGVzKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmV1OmZ1bmN0
-aW9uIGV1KGEpe3RoaXMuYT1hfSwKZXY6ZnVuY3Rpb24gZXYoYSl7dGhpcy5hPWF9LApkQzpmdW5jdGlv
-biBkQygpe3RoaXMuYj1udWxsfSwKZl86ZnVuY3Rpb24gZl8oYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
-CmMyOmZ1bmN0aW9uIGMyKCl7fSwKYzA6ZnVuY3Rpb24gYzAoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1i
-fSwKYVo6ZnVuY3Rpb24gYVooYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8uYz1i
-Cl8uZD1jCl8uZT1kCl8uJHRpPWV9LApTOmZ1bmN0aW9uIFMoYSxiKXt2YXIgXz10aGlzCl8uYT0wCl8u
-Yj1hCl8uYz1udWxsCl8uJHRpPWJ9LAplQzpmdW5jdGlvbiBlQyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
-fSwKZUs6ZnVuY3Rpb24gZUsoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmVHOmZ1bmN0aW9uIGVHKGEp
-e3RoaXMuYT1hfSwKZUg6ZnVuY3Rpb24gZUgoYSl7dGhpcy5hPWF9LAplSTpmdW5jdGlvbiBlSShhLGIs
-Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAplRTpmdW5jdGlvbiBlRShhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKZUo6ZnVuY3Rpb24gZUooYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmVEOmZ1bmN0
-aW9uIGVEKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmVOOmZ1bmN0aW9uIGVOKGEs
-YixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAplTzpmdW5jdGlvbiBlTyhh
-KXt0aGlzLmE9YX0sCmVNOmZ1bmN0aW9uIGVNKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
-Y30sCmVMOmZ1bmN0aW9uIGVMKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmRoOmZ1
-bmN0aW9uIGRoKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKYlk6ZnVuY3Rpb24gYlkoKXt9LAplaDpm
-dW5jdGlvbiBlaChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZWk6ZnVuY3Rpb24gZWkoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCmQ0OmZ1bmN0aW9uIGQ0KCl7fSwKZDU6ZnVuY3Rpb24gZDUoKXt9LAphdTpm
-dW5jdGlvbiBhdShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZEc6ZnVuY3Rpb24gZEcoKXt9LApmZjpm
-dW5jdGlvbiBmZihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZHg6ZnVuY3Rpb24gZHgoKXt9LAplUjpm
-dW5jdGlvbiBlUihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAplUTpmdW5jdGlvbiBl
-UShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZVM6ZnVuY3Rpb24gZVMoYSxiLGMpe3RoaXMuYT1hCnRo
-aXMuYj1iCnRoaXMuYz1jfSwKY086ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLmgoIkA8MD4iKS5FKGMp
-LmgoImhTPDEsMj4iKS5iKEgubG0oYSxuZXcgSC5hbihiLmgoIkA8MD4iKS5FKGMpLmgoImFuPDEsMj4i
-KSkpKX0sCmU5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmFuKGEuaCgiQDwwPiIpLkUoYikuaCgi
-YW48MSwyPiIpKX0sCmJNOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5jNihhLmgoImM2PDA+IikpfSwK
-aDk6ZnVuY3Rpb24oKXt2YXIgdD1PYmplY3QuY3JlYXRlKG51bGwpCnRbIjxub24taWRlbnRpZmllci1r
-ZXk+Il09dApkZWxldGUgdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXQpyZXR1cm4gdH0sCmljOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgdD1uZXcgUC5iMChhLGIsYy5oKCJiMDwwPiIpKQp0LmM9YS5lCnJldHVybiB0
-fSwKakg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5obihhKSl7aWYoYj09PSIoIiYmYz09PSIp
-IilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9dD1ILm4oW10sdS5zKQpDLmIuaygkLlgsYSkK
-dHJ5e1AubDYoYSx0KX1maW5hbGx5e2lmKDA+PSQuWC5sZW5ndGgpcmV0dXJuIEguaSgkLlgsLTEpCiQu
-WC5wb3AoKX1zPVAuaTIoYix1LlIuYih0KSwiLCAiKStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/
-czpzfSwKZTY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5obihhKSlyZXR1cm4gYisiLi4uIitj
-CnQ9bmV3IFAuSChiKQpDLmIuaygkLlgsYSkKdHJ5e3M9dApzLmE9UC5pMihzLmEsYSwiLCAiKX1maW5h
-bGx5e2lmKDA+PSQuWC5sZW5ndGgpcmV0dXJuIEguaSgkLlgsLTEpCiQuWC5wb3AoKX10LmErPWMKcz10
-LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApobjpmdW5jdGlvbihhKXt2YXIgdCxzCmZv
-cih0PSQuWC5sZW5ndGgscz0wO3M8dDsrK3MpaWYoYT09PSQuWFtzXSlyZXR1cm4hMApyZXR1cm4hMX0s
-Cmw2OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbT1hLmdGKGEpLGw9MCxrPTAKd2hpbGUo
-ITApe2lmKCEobDw4MHx8azwzKSlicmVhawppZighbS5wKCkpcmV0dXJuCnQ9SC5iKG0uZ3UoKSkKQy5i
-LmsoYix0KQpsKz10Lmxlbmd0aCsyOysra31pZighbS5wKCkpe2lmKGs8PTUpcmV0dXJuCmlmKDA+PWIu
-bGVuZ3RoKXJldHVybiBILmkoYiwtMSkKcz1iLnBvcCgpCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILmko
-YiwtMSkKcj1iLnBvcCgpfWVsc2V7cT1tLmd1KCk7KytrCmlmKCFtLnAoKSl7aWYoazw9NCl7Qy5iLmso
-YixILmIocSkpCnJldHVybn1zPUguYihxKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5pKGIsLTEpCnI9
-Yi5wb3AoKQpsKz1zLmxlbmd0aCsyfWVsc2V7cD1tLmd1KCk7KytrCmZvcig7bS5wKCk7cT1wLHA9byl7
-bz1tLmd1KCk7KytrCmlmKGs+MTAwKXt3aGlsZSghMCl7aWYoIShsPjc1JiZrPjMpKWJyZWFrCmlmKDA+
-PWIubGVuZ3RoKXJldHVybiBILmkoYiwtMSkKbC09Yi5wb3AoKS5sZW5ndGgrMjstLWt9Qy5iLmsoYiwi
-Li4uIikKcmV0dXJufX1yPUguYihxKQpzPUguYihwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihr
-PmIubGVuZ3RoKzIpe2wrPTUKbj0iLi4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZi
-Lmxlbmd0aD4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5pKGIsLTEpCmwtPWIucG9wKCku
-bGVuZ3RoKzIKaWYobj09bnVsbCl7bCs9NQpuPSIuLi4ifX1pZihuIT1udWxsKUMuYi5rKGIsbikKQy5i
-LmsoYixyKQpDLmIuayhiLHMpfSwKaFQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5iTShiKQpmb3Io
-dD1hLmxlbmd0aCxzPTA7czxhLmxlbmd0aDthLmxlbmd0aD09PXR8fCgwLEguY3IpKGEpLCsrcylyLmso
-MCxiLmIoYVtzXSkpCnJldHVybiByfSwKaDM6ZnVuY3Rpb24oYSl7dmFyIHQscz17fQppZihQLmhuKGEp
-KXJldHVybiJ7Li4ufSIKdD1uZXcgUC5IKCIiKQp0cnl7Qy5iLmsoJC5YLGEpCnQuYSs9InsiCnMuYT0h
-MAphLkEoMCxuZXcgUC5lYShzLHQpKQp0LmErPSJ9In1maW5hbGx5e2lmKDA+PSQuWC5sZW5ndGgpcmV0
-dXJuIEguaSgkLlgsLTEpCiQuWC5wb3AoKX1zPXQuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6
-c30sCmM2OmZ1bmN0aW9uIGM2KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1fLmQ9Xy5jPV8uYj1u
-dWxsCl8ucj0wCl8uJHRpPWF9LApkdTpmdW5jdGlvbiBkdShhKXt0aGlzLmE9YQp0aGlzLmM9dGhpcy5i
-PW51bGx9LApiMDpmdW5jdGlvbiBiMChhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5j
-PW51bGwKXy4kdGk9Y30sCmJOOmZ1bmN0aW9uIGJOKCl7fSwKbDpmdW5jdGlvbiBsKCl7fSwKYlA6ZnVu
-Y3Rpb24gYlAoKXt9LAplYTpmdW5jdGlvbiBlYShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQjpmdW5j
-dGlvbiBCKCl7fSwKY2o6ZnVuY3Rpb24gY2ooKXt9LApiYzpmdW5jdGlvbiBiYygpe30sCmF6OmZ1bmN0
-aW9uIGF6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmFXOmZ1bmN0aW9uIGFXKCl7fSwKYlc6ZnVu
-Y3Rpb24gYlcoKXt9LApjZDpmdW5jdGlvbiBjZCgpe30sCmM3OmZ1bmN0aW9uIGM3KCl7fSwKY2U6ZnVu
-Y3Rpb24gY2UoKXt9LApicTpmdW5jdGlvbiBicSgpe30sCmw4OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHEKaWYodHlwZW9mIGEhPSJzdHJpbmciKXRocm93IEguYShILmFzKGEpKQp0PW51bGwKdHJ5e3Q9SlNP
-Ti5wYXJzZShhKX1jYXRjaChyKXtzPUguUShyKQpxPVAuQShTdHJpbmcocyksbnVsbCxudWxsKQp0aHJv
-dyBILmEocSl9cT1QLmY2KHQpCnJldHVybiBxfSwKZjY6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYT09bnVs
-bClyZXR1cm4gbnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGEKaWYoT2JqZWN0LmdldFBy
-b3RvdHlwZU9mKGEpIT09QXJyYXkucHJvdG90eXBlKXJldHVybiBuZXcgUC5kcyhhLE9iamVjdC5jcmVh
-dGUobnVsbCkpCmZvcih0PTA7dDxhLmxlbmd0aDsrK3QpYVt0XT1QLmY2KGFbdF0pCnJldHVybiBhfSwK
-a2E6ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpcmV0dXJuIFAua2Io
-ITEsYixjLGQpCnJldHVybiBudWxsfSwKa2I6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyPSQuamMo
-KQppZihyPT1udWxsKXJldHVybiBudWxsCnQ9MD09PWMKaWYodCYmITApcmV0dXJuIFAuaDgocixiKQpz
-PWIubGVuZ3RoCmQ9UC5hVihjLGQscykKaWYodCYmZD09PXMpcmV0dXJuIFAuaDgocixiKQpyZXR1cm4g
-UC5oOChyLGIuc3ViYXJyYXkoYyxkKSl9LApoODpmdW5jdGlvbihhLGIpe2lmKFAua2QoYikpcmV0dXJu
-IG51bGwKcmV0dXJuIFAua2UoYSxiKX0sCmtlOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp0cnl7dD1hLmRl
-Y29kZShiKQpyZXR1cm4gdH1jYXRjaChzKXtILlEocyl9cmV0dXJuIG51bGx9LAprZDpmdW5jdGlvbihh
-KXt2YXIgdCxzPWEubGVuZ3RoLTIKZm9yKHQ9MDt0PHM7Kyt0KWlmKGFbdF09PT0yMzcpaWYoKGFbdCsx
-XSYyMjQpPT09MTYwKXJldHVybiEwCnJldHVybiExfSwKa2M6ZnVuY3Rpb24oKXt2YXIgdCxzCnRyeXt0
-PW5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtmYXRhbDp0cnVlfSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5R
-KHMpfXJldHVybiBudWxsfSwKaUQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpmb3IodD1KLmFfKGEp
-LHM9YjtzPGM7KytzKXtyPXQuaihhLHMpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuUCgp
-CmlmKChyJjEyNykhPT1yKXJldHVybiBzLWJ9cmV0dXJuIGMtYn0sCmhJOmZ1bmN0aW9uKGEsYixjLGQs
-ZSxmKXtpZihDLmMuYWsoZiw0KSE9PTApdGhyb3cgSC5hKFAuQSgiSW52YWxpZCBiYXNlNjQgcGFkZGlu
-ZywgcGFkZGVkIGxlbmd0aCBtdXN0IGJlIG11bHRpcGxlIG9mIGZvdXIsIGlzICIrZixhLGMpKQppZihk
-K2UhPT1mKXRocm93IEguYShQLkEoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsICc9JyBub3QgYXQgdGhl
-IGVuZCIsYSxiKSkKaWYoZT4yKXRocm93IEguYShQLkEoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIG1v
-cmUgdGhhbiB0d28gJz0nIGNoYXJhY3RlcnMiLGEsYikpfSwKaXg6ZnVuY3Rpb24oYSl7YS5QKDAsNjQ1
-MTIpCnJldHVybiExfSwKa1Y6ZnVuY3Rpb24oYSxiKXtyZXR1cm4oQy5jLkIoNjU1MzYsYS5QKDAsMTAy
-MykuY3YoMCwxMCkpfGImMTAyMyk+Pj4wfSwKZHM6ZnVuY3Rpb24gZHMoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Ygp0aGlzLmM9bnVsbH0sCmR0OmZ1bmN0aW9uIGR0KGEpe3RoaXMuYT1hfSwKY3c6ZnVuY3Rpb24g
-Y3coKXt9LApjeDpmdW5jdGlvbiBjeCgpe30sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKYUs6ZnVuY3Rpb24g
-YUsoKXt9LApjRTpmdW5jdGlvbiBjRSgpe30sCmNNOmZ1bmN0aW9uIGNNKCl7fSwKY046ZnVuY3Rpb24g
-Y04oYSl7dGhpcy5hPWF9LApkZDpmdW5jdGlvbiBkZCgpe30sCmRmOmZ1bmN0aW9uIGRmKCl7fSwKZjQ6
-ZnVuY3Rpb24gZjQoYSl7dGhpcy5iPTAKdGhpcy5jPWF9LApkZTpmdW5jdGlvbiBkZShhKXt0aGlzLmE9
-YX0sCmYzOmZ1bmN0aW9uIGYzKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9ITAKXy5mPV8u
-ZT1fLmQ9MH0sCmRPOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILmg0KGEsYykKaWYodCE9bnVsbClyZXR1
-cm4gdAppZihiIT1udWxsKXJldHVybiBiLiQxKGEpCnRocm93IEguYShQLkEoYSxudWxsLG51bGwpKX0s
-CmpHOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBILmFJKXJldHVybiBhLmkoMCkKcmV0dXJuIklu
-c3RhbmNlIG9mICciK0guYihILmVmKGEpKSsiJyJ9LApoMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1I
-Lm4oW10sYy5oKCJGPDA+IikpCmZvcih0PUouYTkoYSk7dC5wKCk7KUMuYi5rKHMsYy5iKHQuZ3UoKSkp
-CnJldHVybiBzfSwKaDY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKEFycmF5LmlzQXJyYXkoYSkpe3Uu
-dC5iKGEpCnQ9YS5sZW5ndGgKYz1QLmFWKGIsYyx0KQpyZXR1cm4gSC5oWShiPjB8fGM8dD9DLmIuYnUo
-YSxiLGMpOmEpfWlmKHUuYm0uYyhhKSlyZXR1cm4gSC5rMChhLGIsUC5hVihiLGMsYS5sZW5ndGgpKQpy
-ZXR1cm4gUC5rNShhLGIsYyl9LAprNTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD1udWxsCmlm
-KGI8MCl0aHJvdyBILmEoUC5MKGIsMCxKLmF0KGEpLHAscCkpCnQ9Yz09bnVsbAppZighdCYmYzxiKXRo
-cm93IEguYShQLkwoYyxiLEouYXQoYSkscCxwKSkKcz1KLmE5KGEpCmZvcihyPTA7cjxiOysrcilpZigh
-cy5wKCkpdGhyb3cgSC5hKFAuTChiLDAscixwLHApKQpxPVtdCmlmKHQpZm9yKDtzLnAoKTspcS5wdXNo
-KHMuZ3UoKSkKZWxzZSBmb3Iocj1iO3I8YzsrK3Ipe2lmKCFzLnAoKSl0aHJvdyBILmEoUC5MKGMsYixy
-LHAscCkpCnEucHVzaChzLmd1KCkpfXJldHVybiBILmhZKHEpfSwKaV86ZnVuY3Rpb24oYSl7cmV0dXJu
-IG5ldyBILmNLKGEsSC5qTShhLCExLCEwLCExLCExLCExKSl9LAppMjpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQ9Si5hOShiKQppZighdC5wKCkpcmV0dXJuIGEKaWYoYy5sZW5ndGg9PT0wKXtkbyBhKz1ILmIodC5n
-dSgpKQp3aGlsZSh0LnAoKSl9ZWxzZXthKz1ILmIodC5ndSgpKQpmb3IoO3QucCgpOylhPWErYytILmIo
-dC5ndSgpKX1yZXR1cm4gYX0sCmhVOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBuZXcgUC5jVShhLGIs
-YyxkKX0sCmtSOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2Nzg5QUJD
-REVGIgppZihjPT09Qy5mKXt0PSQuamYoKS5iCnQ9dC50ZXN0KGIpfWVsc2UgdD0hMQppZih0KXJldHVy
-biBiCkgudihjKS5oKCJhMi5TIikuYihiKQpzPWMuZ2NhKCkuYUEoYikKZm9yKHQ9cy5sZW5ndGgscj0w
-LHE9IiI7cjx0Oysrcil7cD1zW3JdCmlmKHA8MTI4KXtvPXA+Pj40CmlmKG8+PTgpcmV0dXJuIEguaShh
-LG8pCm89KGFbb10mMTw8KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pcSs9SC5kXyhwKQplbHNlIHE9
-ZCYmcD09PTMyP3ErIisiOnErIiUiK25bcD4+PjQmMTVdK25bcCYxNV19cmV0dXJuIHEuY2hhckNvZGVB
-dCgwKT09MD9xOnF9LApqRDpmdW5jdGlvbihhKXt2YXIgdD1NYXRoLmFicyhhKSxzPWE8MD8iLSI6IiIK
-aWYodD49MTAwMClyZXR1cm4iIithCmlmKHQ+PTEwMClyZXR1cm4gcysiMCIrdAppZih0Pj0xMClyZXR1
-cm4gcysiMDAiK3QKcmV0dXJuIHMrIjAwMCIrdH0sCmpFOmZ1bmN0aW9uKGEpe2lmKGE+PTEwMClyZXR1
-cm4iIithCmlmKGE+PTEwKXJldHVybiIwIithCnJldHVybiIwMCIrYX0sCmNDOmZ1bmN0aW9uKGEpe2lm
-KGE+PTEwKXJldHVybiIiK2EKcmV0dXJuIjAiK2F9LAphTTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09
-Im51bWJlciJ8fEguZmQoYSl8fG51bGw9PWEpcmV0dXJuIEouYjIoYSkKaWYodHlwZW9mIGE9PSJzdHJp
-bmciKXJldHVybiBKU09OLnN0cmluZ2lmeShhKQpyZXR1cm4gUC5qRyhhKX0sCmZZOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC5idyhhKX0sCmI0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5hMSghMSxudWxs
-LG51bGwsYSl9LApmWDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLmExKCEwLGEsYixjKX0sCmVn
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLmFVKG51bGwsbnVsbCwhMCxhLGIsIlZhbHVlIG5vdCBp
-biByYW5nZSIpfSwKTDpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBuZXcgUC5hVShiLGMsITAsYSxk
-LCJJbnZhbGlkIHZhbHVlIil9LAphVjpmdW5jdGlvbihhLGIsYyl7aWYoMD5hfHxhPmMpdGhyb3cgSC5h
-KFAuTChhLDAsYywic3RhcnQiLG51bGwpKQppZihiIT1udWxsKXtpZihhPmJ8fGI+Yyl0aHJvdyBILmEo
-UC5MKGIsYSxjLCJlbmQiLG51bGwpKQpyZXR1cm4gYn1yZXR1cm4gY30sCmsxOmZ1bmN0aW9uKGEsYil7
-aWYodHlwZW9mIGEhPT0ibnVtYmVyIilyZXR1cm4gYS5EKCkKaWYoYTwwKXRocm93IEguYShQLkwoYSww
-LG51bGwsYixudWxsKSl9LAplNTpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PUgueChlPT1udWxsP0ou
-YXQoYik6ZSkKcmV0dXJuIG5ldyBQLmNHKHQsITAsYSxjLCJJbmRleCBvdXQgb2YgcmFuZ2UiKX0sCk46
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmRiKGEpfSwKZWw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQ
-LmQ5KGEpfSwKZDI6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmJoKGEpfSwKYXY6ZnVuY3Rpb24oYSl7
-cmV0dXJuIG5ldyBQLmN6KGEpfSwKQTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLmVfKGEsYixj
-KX0sCmpOOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUgubihbXSxjLmgoIkY8MD4iKSkKQy5iLnNtKHMs
-YSkKZm9yKHQ9MDt0PGE7Kyt0KUMuYi5sKHMsdCxiLiQxKHQpKQpyZXR1cm4gc30sCmk1OmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPW51bGwsZD1hLmxlbmd0aAppZihk
-Pj01KXt0PSgoSi5oRChhLDQpXjU4KSozfEMuYS50KGEsMCleMTAwfEMuYS50KGEsMSleOTd8Qy5hLnQo
-YSwyKV4xMTZ8Qy5hLnQoYSwzKV45Nyk+Pj4wCmlmKHQ9PT0wKXJldHVybiBQLmk0KGQ8ZD9DLmEubihh
-LDAsZCk6YSw1LGUpLmdicCgpCmVsc2UgaWYodD09PTMyKXJldHVybiBQLmk0KEMuYS5uKGEsNSxkKSww
-LGUpLmdicCgpfXM9bmV3IEFycmF5KDgpCnMuZml4ZWQkbGVuZ3RoPUFycmF5CnI9SC5uKHMsdS50KQpD
-LmIubChyLDAsMCkKQy5iLmwociwxLC0xKQpDLmIubChyLDIsLTEpCkMuYi5sKHIsNywtMSkKQy5iLmwo
-ciwzLDApCkMuYi5sKHIsNCwwKQpDLmIubChyLDUsZCkKQy5iLmwociw2LGQpCmlmKFAuaUMoYSwwLGQs
-MCxyKT49MTQpQy5iLmwociw3LGQpCnE9clsxXQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBx
-LmJyKCkKaWYocT49MClpZihQLmlDKGEsMCxxLDIwLHIpPT09MjApcls3XT1xCnM9clsyXQppZih0eXBl
-b2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkIoKQpwPXMrMQpvPXJbM10Kbj1yWzRdCm09cls1XQpsPXJb
-Nl0KaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5EKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVy
-IilyZXR1cm4gSC5haihtKQppZihsPG0pbT1sCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4u
-RCgpCmlmKG48cCluPW0KZWxzZSBpZihuPD1xKW49cSsxCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0
-dXJuIG8uRCgpCmlmKG88cClvPW4Kcz1yWzddCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMu
-RCgpCms9czwwCmlmKGspaWYocD5xKzMpe2o9ZQprPSExfWVsc2V7cz1vPjAKaWYocyYmbysxPT09bil7
-aj1lCms9ITF9ZWxzZXtpZighKG08ZCYmbT09PW4rMiYmSi5jdChhLCIuLiIsbikpKWk9bT5uKzImJkou
-Y3QoYSwiLy4uIixtLTMpCmVsc2UgaT0hMAppZihpKXtqPWUKaz0hMX1lbHNle2lmKHE9PT00KWlmKEou
-Y3QoYSwiZmlsZSIsMCkpe2lmKHA8PTApe2lmKCFDLmEuUyhhLCIvIixuKSl7aD0iZmlsZTovLy8iCnQ9
-M31lbHNle2g9ImZpbGU6Ly8iCnQ9Mn1hPWgrQy5hLm4oYSxuLGQpCnEtPTAKcz10LTAKbSs9cwpsKz1z
-CmQ9YS5sZW5ndGgKcD03Cm89NwpuPTd9ZWxzZSBpZihuPT09bSl7Zz1tKzE7KytsCmE9Qy5hLmEwKGEs
-bixtLCIvIik7KytkCm09Z31qPSJmaWxlIn1lbHNlIGlmKEMuYS5TKGEsImh0dHAiLDApKXtpZihzJiZv
-KzM9PT1uJiZDLmEuUyhhLCI4MCIsbysxKSl7Zj1uLTMKbS09MwpsLT0zCmE9Qy5hLmEwKGEsbyxuLCIi
-KQpkLT0zCm49Zn1qPSJodHRwIn1lbHNlIGo9ZQplbHNlIGlmKHE9PT01JiZKLmN0KGEsImh0dHBzIiww
-KSl7aWYocyYmbys0PT09biYmSi5jdChhLCI0NDMiLG8rMSkpe2Y9bi00Cm0tPTQKbC09NAphPUouanIo
-YSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHBzIn1lbHNlIGo9ZQprPSEwfX19ZWxzZSBqPWUKaWYoayl7
-cz1hLmxlbmd0aAppZihkPHMpe2E9Si5oSChhLDAsZCkKcS09MApwLT0wCm8tPTAKbi09MAptLT0wCmwt
-PTB9cmV0dXJuIG5ldyBQLmR6KGEscSxwLG8sbixtLGwsail9cmV0dXJuIFAua0MoYSwwLGQscSxwLG8s
-bixtLGwsail9LAppNzpmdW5jdGlvbihhKXt2YXIgdD11Lk4KcmV0dXJuIEMuYi5jYyhILm4oYS5zcGxp
-dCgiJiIpLHUucyksUC5lOSh0LHQpLG5ldyBQLmVxKEMuZiksdS5mKX0sCms5OmZ1bmN0aW9uKGEsYixj
-KXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwsbD0iSVB2NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4
-YWN0bHkgNCBwYXJ0cyIsaz0iZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1u
-ZXcgUC5lbihhKSxpPW5ldyBVaW50OEFycmF5KDQpCmZvcih0PWkubGVuZ3RoLHM9YixyPXMscT0wO3M8
-YzsrK3Mpe3A9Qy5hLnYoYSxzKQppZihwIT09NDYpe2lmKChwXjQ4KT45KWouJDIoImludmFsaWQgY2hh
-cmFjdGVyIixzKX1lbHNle2lmKHE9PT0zKWouJDIobCxzKQpvPVAuZE8oQy5hLm4oYSxyLHMpLG0sbSkK
-aWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5hTSgpCmlmKG8+MjU1KWouJDIoayxyKQpuPXEr
-MQppZihxPj10KXJldHVybiBILmkoaSxxKQppW3FdPW8Kcj1zKzEKcT1ufX1pZihxIT09MylqLiQyKGws
-YykKbz1QLmRPKEMuYS5uKGEscixjKSxtLG0pCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8u
-YU0oKQppZihvPjI1NSlqLiQyKGsscikKaWYocT49dClyZXR1cm4gSC5pKGkscSkKaVtxXT1vCnJldHVy
-biBpfSwKaTY6ZnVuY3Rpb24oYSxiLGEwKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYs
-ZSxkPW5ldyBQLmVvKGEpLGM9bmV3IFAuZXAoZCxhKQppZihhLmxlbmd0aDwyKWQuJDEoImFkZHJlc3Mg
-aXMgdG9vIHNob3J0IikKdD1ILm4oW10sdS50KQpmb3Iocz1iLHI9cyxxPSExLHA9ITE7czxhMDsrK3Mp
-e289Qy5hLnYoYSxzKQppZihvPT09NTgpe2lmKHM9PT1iKXsrK3MKaWYoQy5hLnYoYSxzKSE9PTU4KWQu
-JDIoImludmFsaWQgc3RhcnQgY29sb24uIixzKQpyPXN9aWYocz09PXIpe2lmKHEpZC4kMigib25seSBv
-bmUgd2lsZGNhcmQgYDo6YCBpcyBhbGxvd2VkIixzKQpDLmIuayh0LC0xKQpxPSEwfWVsc2UgQy5iLmso
-dCxjLiQyKHIscykpCnI9cysxfWVsc2UgaWYobz09PTQ2KXA9ITB9aWYodC5sZW5ndGg9PT0wKWQuJDEo
-InRvbyBmZXcgcGFydHMiKQpuPXI9PT1hMAptPUMuYi5nYWcodCkKaWYobiYmbSE9PS0xKWQuJDIoImV4
-cGVjdGVkIGEgcGFydCBhZnRlciBsYXN0IGA6YCIsYTApCmlmKCFuKWlmKCFwKUMuYi5rKHQsYy4kMihy
-LGEwKSkKZWxzZXtsPVAuazkoYSxyLGEwKQpDLmIuayh0LChsWzBdPDw4fGxbMV0pPj4+MCkKQy5iLmso
-dCwobFsyXTw8OHxsWzNdKT4+PjApfWlmKHEpe2lmKHQubGVuZ3RoPjcpZC4kMSgiYW4gYWRkcmVzcyB3
-aXRoIGEgd2lsZGNhcmQgbXVzdCBoYXZlIGxlc3MgdGhhbiA3IHBhcnRzIil9ZWxzZSBpZih0Lmxlbmd0
-aCE9PTgpZC4kMSgiYW4gYWRkcmVzcyB3aXRob3V0IGEgd2lsZGNhcmQgbXVzdCBjb250YWluIGV4YWN0
-bHkgOCBwYXJ0cyIpCms9bmV3IFVpbnQ4QXJyYXkoMTYpCmZvcihtPXQubGVuZ3RoLGo9ay5sZW5ndGgs
-aT05LW0scz0wLGg9MDtzPG07KytzKXtnPXRbc10KaWYoZz09PS0xKWZvcihmPTA7ZjxpOysrZil7aWYo
-aDwwfHxoPj1qKXJldHVybiBILmkoayxoKQprW2hdPTAKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5pKGss
-ZSkKa1tlXT0wCmgrPTJ9ZWxzZXtlPUMuYy5aKGcsOCkKaWYoaDwwfHxoPj1qKXJldHVybiBILmkoayxo
-KQprW2hdPWUKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5pKGssZSkKa1tlXT1nJjI1NQpoKz0yfX1yZXR1
-cm4ga30sCmtDOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpLGope3ZhciB0LHMscixxLHAsbyxuLG09
-bnVsbAppZihqPT1udWxsKWlmKGQ+YilqPVAua0woYSxiLGQpCmVsc2V7aWYoZD09PWIpUC5icihhLGIs
-IkludmFsaWQgZW1wdHkgc2NoZW1lIikKaj0iIn1pZihlPmIpe3Q9ZCszCnM9dDxlP1Aua00oYSx0LGUt
-MSk6IiIKcj1QLmtIKGEsZSxmLCExKQppZih0eXBlb2YgZiE9PSJudW1iZXIiKXJldHVybiBmLkIoKQpx
-PWYrMQppZih0eXBlb2YgZyE9PSJudW1iZXIiKXJldHVybiBILmFqKGcpCnA9cTxnP1Aua0ooUC5kTyhK
-LmhIKGEscSxnKSxuZXcgUC5mMShhLGYpLG0pLGopOm19ZWxzZXtwPW0Kcj1wCnM9IiJ9bz1QLmtJKGEs
-ZyxoLG0saixyIT1udWxsKQppZih0eXBlb2YgaCE9PSJudW1iZXIiKXJldHVybiBoLkQoKQpuPWg8aT9Q
-LmtLKGEsaCsxLGksbSk6bQpyZXR1cm4gbmV3IFAuY2soaixzLHIscCxvLG4saTxjP1Aua0coYSxpKzEs
-Yyk6bSl9LAppazpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAiKXJldHVybiA4MAppZihhPT09Imh0dHBz
-IilyZXR1cm4gNDQzCnJldHVybiAwfSwKYnI6ZnVuY3Rpb24oYSxiLGMpe3Rocm93IEguYShQLkEoYyxh
-LGIpKX0sCmtKOmZ1bmN0aW9uKGEsYil7aWYoYSE9bnVsbCYmYT09PVAuaWsoYikpcmV0dXJuIG51bGwK
-cmV0dXJuIGF9LAprSDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8KaWYoYT09bnVsbCly
-ZXR1cm4gbnVsbAppZihiPT09YylyZXR1cm4iIgppZihDLmEudihhLGIpPT09OTEpe2lmKHR5cGVvZiBj
-IT09Im51bWJlciIpcmV0dXJuIGMuY3coKQp0PWMtMQppZihDLmEudihhLHQpIT09OTMpUC5icihhLGIs
-Ik1pc3NpbmcgZW5kIGBdYCB0byBtYXRjaCBgW2AgaW4gaG9zdCIpCnM9YisxCnI9UC5rRShhLHMsdCkK
-aWYodHlwZW9mIHIhPT0ibnVtYmVyIilyZXR1cm4gci5EKCkKaWYocjx0KXtxPXIrMQpwPVAuaXEoYSxD
-LmEuUyhhLCIyNSIscSk/ciszOnEsdCwiJTI1Iil9ZWxzZSBwPSIiClAuaTYoYSxzLHIpCnJldHVybiBD
-LmEubihhLGIscikudG9Mb3dlckNhc2UoKStwKyJdIn1pZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVy
-biBILmFqKGMpCm89Ygpmb3IoO288YzsrK28paWYoQy5hLnYoYSxvKT09PTU4KXtyPUMuYS5hZShhLCIl
-IixiKQppZighKHI+PWImJnI8Yykpcj1jCmlmKHI8Yyl7cT1yKzEKcD1QLmlxKGEsQy5hLlMoYSwiMjUi
-LHEpP3IrMzpxLGMsIiUyNSIpfWVsc2UgcD0iIgpQLmk2KGEsYixyKQpyZXR1cm4iWyIrQy5hLm4oYSxi
-LHIpK3ArIl0ifXJldHVybiBQLmtPKGEsYixjKX0sCmtFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUMu
-YS5hZShhLCIlIixiKQppZihzPj1iKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILmFqKGMp
-CnQ9czxjfWVsc2UgdD0hMQpyZXR1cm4gdD9zOmN9LAppcTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGwsaz1kIT09IiI/bmV3IFAuSChkKTpudWxsCmlmKHR5cGVvZiBjIT09Im51bWJl
-ciIpcmV0dXJuIEguYWooYykKdD1iCnM9dApyPSEwCmZvcig7dDxjOyl7cT1DLmEudihhLHQpCmlmKHE9
-PT0zNyl7cD1QLmhlKGEsdCwhMCkKbz1wPT1udWxsCmlmKG8mJnIpe3QrPTMKY29udGludWV9aWYoaz09
-bnVsbClrPW5ldyBQLkgoIiIpCm49ay5hKz1DLmEubihhLHMsdCkKaWYobylwPUMuYS5uKGEsdCx0KzMp
-CmVsc2UgaWYocD09PSIlIilQLmJyKGEsdCwiWm9uZUlEIHNob3VsZCBub3QgY29udGFpbiAlIGFueW1v
-cmUiKQprLmE9bitwCnQrPTMKcz10CnI9ITB9ZWxzZXtpZihxPDEyNyl7bz1xPj4+NAppZihvPj04KXJl
-dHVybiBILmkoQy5rLG8pCm89KEMua1tvXSYxPDwocSYxNSkpIT09MH1lbHNlIG89ITEKaWYobyl7aWYo
-ciYmNjU8PXEmJjkwPj1xKXtpZihrPT1udWxsKWs9bmV3IFAuSCgiIikKaWYoczx0KXtrLmErPUMuYS5u
-KGEscyx0KQpzPXR9cj0hMX0rK3R9ZWxzZXtpZigocSY2NDUxMik9PT01NTI5NiYmdCsxPGMpe209Qy5h
-LnYoYSx0KzEpCmlmKChtJjY0NTEyKT09PTU2MzIwKXtxPTY1NTM2fChxJjEwMjMpPDwxMHxtJjEwMjMK
-bD0yfWVsc2UgbD0xfWVsc2UgbD0xCmlmKGs9PW51bGwpaz1uZXcgUC5IKCIiKQprLmErPUMuYS5uKGEs
-cyx0KQprLmErPVAuaGQocSkKdCs9bApzPXR9fX1pZihrPT1udWxsKXJldHVybiBDLmEubihhLGIsYykK
-aWYoczxjKWsuYSs9Qy5hLm4oYSxzLGMpCm89ay5hCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpv
-fSwKa086ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGoKaWYodHlwZW9mIGMh
-PT0ibnVtYmVyIilyZXR1cm4gSC5haihjKQp0PWIKcz10CnI9bnVsbApxPSEwCmZvcig7dDxjOyl7cD1D
-LmEudihhLHQpCmlmKHA9PT0zNyl7bz1QLmhlKGEsdCwhMCkKbj1vPT1udWxsCmlmKG4mJnEpe3QrPTMK
-Y29udGludWV9aWYocj09bnVsbClyPW5ldyBQLkgoIiIpCm09Qy5hLm4oYSxzLHQpCmw9ci5hKz0hcT9t
-LnRvTG93ZXJDYXNlKCk6bQppZihuKXtvPUMuYS5uKGEsdCx0KzMpCms9M31lbHNlIGlmKG89PT0iJSIp
-e289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQKcT0hMH1lbHNle2lmKHA8MTI3KXtu
-PXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguaShDLngsbikKbj0oQy54W25dJjE8PChwJjE1KSkhPT0wfWVs
-c2Ugbj0hMQppZihuKXtpZihxJiY2NTw9cCYmOTA+PXApe2lmKHI9PW51bGwpcj1uZXcgUC5IKCIiKQpp
-ZihzPHQpe3IuYSs9Qy5hLm4oYSxzLHQpCnM9dH1xPSExfSsrdH1lbHNle2lmKHA8PTkzKXtuPXA+Pj40
-CmlmKG4+PTgpcmV0dXJuIEguaShDLmgsbikKbj0oQy5oW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0h
-MQppZihuKVAuYnIoYSx0LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYoKHAmNjQ1MTIpPT09NTUy
-OTYmJnQrMTxjKXtqPUMuYS52KGEsdCsxKQppZigoaiY2NDUxMik9PT01NjMyMCl7cD02NTUzNnwocCYx
-MDIzKTw8MTB8aiYxMDIzCms9Mn1lbHNlIGs9MX1lbHNlIGs9MQppZihyPT1udWxsKXI9bmV3IFAuSCgi
-IikKbT1DLmEubihhLHMsdCkKci5hKz0hcT9tLnRvTG93ZXJDYXNlKCk6bQpyLmErPVAuaGQocCkKdCs9
-awpzPXR9fX19aWYocj09bnVsbClyZXR1cm4gQy5hLm4oYSxiLGMpCmlmKHM8Yyl7bT1DLmEubihhLHMs
-YykKci5hKz0hcT9tLnRvTG93ZXJDYXNlKCk6bX1uPXIuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0w
-P246bn0sCmtMOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihiPT09YylyZXR1cm4iIgppZigh
-UC5pbShKLmEwKGEpLnQoYSxiKSkpUC5icihhLGIsIlNjaGVtZSBub3Qgc3RhcnRpbmcgd2l0aCBhbHBo
-YWJldGljIGNoYXJhY3RlciIpCmZvcih0PWIscz0hMTt0PGM7Kyt0KXtyPUMuYS50KGEsdCkKaWYocjwx
-Mjgpe3E9cj4+PjQKaWYocT49OClyZXR1cm4gSC5pKEMuaixxKQpxPShDLmpbcV0mMTw8KHImMTUpKSE9
-PTB9ZWxzZSBxPSExCmlmKCFxKVAuYnIoYSx0LCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQppZig2
-NTw9ciYmcjw9OTApcz0hMH1hPUMuYS5uKGEsYixjKQpyZXR1cm4gUC5rRChzP2EudG9Mb3dlckNhc2Uo
-KTphKX0sCmtEOmZ1bmN0aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuImh0dHAiCmlmKGE9PT0iZmls
-ZSIpcmV0dXJuImZpbGUiCmlmKGE9PT0iaHR0cHMiKXJldHVybiJodHRwcyIKaWYoYT09PSJwYWNrYWdl
-IilyZXR1cm4icGFja2FnZSIKcmV0dXJuIGF9LAprTTpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbCly
-ZXR1cm4iIgpyZXR1cm4gUC5jbChhLGIsYyxDLlcsITEpfSwKa0k6ZnVuY3Rpb24oYSxiLGMsZCxlLGYp
-e3ZhciB0LHM9ZT09PSJmaWxlIixyPXN8fGYscT1hPT1udWxsCmlmKHEmJiEwKXJldHVybiBzPyIvIjoi
-Igp0PSFxP1AuY2woYSxiLGMsQy55LCEwKTpDLlEuYUYoZCxuZXcgUC5mMigpLHUuTikuVCgwLCIvIikK
-aWYodC5sZW5ndGg9PT0wKXtpZihzKXJldHVybiIvIn1lbHNlIGlmKHImJiFDLmEuSCh0LCIvIikpdD0i
-LyIrdApyZXR1cm4gUC5rTih0LGUsZil9LAprTjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Yi5sZW5ndGg9
-PT0wCmlmKHQmJiFjJiYhQy5hLkgoYSwiLyIpKXJldHVybiBQLmtQKGEsIXR8fGMpCnJldHVybiBQLmtR
-KGEpfSwKa0s6ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYSE9bnVsbClyZXR1cm4gUC5jbChhLGIsYyxDLmks
-ITApCnJldHVybiBudWxsfSwKa0c6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwK
-cmV0dXJuIFAuY2woYSxiLGMsQy5pLCEwKX0sCmhlOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxw
-LG89YisyCmlmKG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMuYS52KGEsYisxKQpzPUMuYS52KGEsbykK
-cj1ILmZ3KHQpCnE9SC5mdyhzKQppZihyPDB8fHE8MClyZXR1cm4iJSIKcD1yKjE2K3EKaWYocDwxMjcp
-e289Qy5jLloocCw0KQppZihvPj04KXJldHVybiBILmkoQy5rLG8pCm89KEMua1tvXSYxPDwocCYxNSkp
-IT09MH1lbHNlIG89ITEKaWYobylyZXR1cm4gSC5kXyhjJiY2NTw9cCYmOTA+PXA/KHB8MzIpPj4+MDpw
-KQppZih0Pj05N3x8cz49OTcpcmV0dXJuIEMuYS5uKGEsYixiKzMpLnRvVXBwZXJDYXNlKCkKcmV0dXJu
-IG51bGx9LApoZDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbj0iMDEyMzQ1Njc4OUFCQ0RFRiIK
-aWYoYTwxMjgpe3Q9bmV3IEFycmF5KDMpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5uKHQsdS50KQpD
-LmIubChzLDAsMzcpCkMuYi5sKHMsMSxDLmEudChuLGE+Pj40KSkKQy5iLmwocywyLEMuYS50KG4sYSYx
-NSkpfWVsc2V7aWYoYT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQwCnE9NH1lbHNle3I9MjI0CnE9M31lbHNl
-e3I9MTkyCnE9Mn10PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5uKHQsdS50
-KQpmb3IocD0wOy0tcSxxPj0wO3I9MTI4KXtvPUMuYy5iWChhLDYqcSkmNjN8cgpDLmIubChzLHAsMzcp
-CkMuYi5sKHMscCsxLEMuYS50KG4sbz4+PjQpKQpDLmIubChzLHArMixDLmEudChuLG8mMTUpKQpwKz0z
-fX1yZXR1cm4gUC5oNihzLDAsbnVsbCl9LApjbDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PVAuaXAo
-YSxiLGMsZCxlKQpyZXR1cm4gdD09bnVsbD9DLmEubihhLGIsYyk6dH0sCmlwOmZ1bmN0aW9uKGEsYixj
-LGQsZSl7dmFyIHQscyxyLHEscCxvPW51bGwsbj0hZSxtPWIsbD1tLGs9bwp3aGlsZSghMCl7aWYodHlw
-ZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5EKCkKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4g
-SC5haihjKQppZighKG08YykpYnJlYWsKYyQwOnt0PUMuYS52KGEsbSkKaWYodDwxMjcpe3M9dD4+PjQK
-aWYocz49OClyZXR1cm4gSC5pKGQscykKcz0oZFtzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKaWYo
-cykrK20KZWxzZXtpZih0PT09Mzcpe3I9UC5oZShhLG0sITEpCmlmKHI9PW51bGwpe20rPTMKYnJlYWsg
-YyQwfWlmKCIlIj09PXIpe3I9IiUyNSIKcT0xfWVsc2UgcT0zfWVsc2V7aWYobilpZih0PD05Myl7cz10
-Pj4+NAppZihzPj04KXJldHVybiBILmkoQy5oLHMpCnM9KEMuaFtzXSYxPDwodCYxNSkpIT09MH1lbHNl
-IHM9ITEKZWxzZSBzPSExCmlmKHMpe1AuYnIoYSxtLCJJbnZhbGlkIGNoYXJhY3RlciIpCnE9bwpyPXF9
-ZWxzZXtpZigodCY2NDUxMik9PT01NTI5Nil7cz1tKzEKaWYoczxjKXtwPUMuYS52KGEscykKaWYoKHAm
-NjQ1MTIpPT09NTYzMjApe3Q9NjU1MzZ8KHQmMTAyMyk8PDEwfHAmMTAyMwpxPTJ9ZWxzZSBxPTF9ZWxz
-ZSBxPTF9ZWxzZSBxPTEKcj1QLmhkKHQpfX1pZihrPT1udWxsKWs9bmV3IFAuSCgiIikKay5hKz1DLmEu
-bihhLGwsbSkKay5hKz1ILmIocikKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5haihxKQpt
-Kz1xCmw9bX19fWlmKGs9PW51bGwpcmV0dXJuIG8KaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4g
-bC5EKCkKaWYobDxjKWsuYSs9Qy5hLm4oYSxsLGMpCm49ay5hCnJldHVybiBuLmNoYXJDb2RlQXQoMCk9
-PTA/bjpufSwKaW86ZnVuY3Rpb24oYSl7aWYoQy5hLkgoYSwiLiIpKXJldHVybiEwCnJldHVybiBDLmEu
-YmYoYSwiLy4iKSE9PS0xfSwKa1E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4KaWYoIVAuaW8o
-YSkpcmV0dXJuIGEKdD1ILm4oW10sdS5zKQpmb3Iocz1hLnNwbGl0KCIvIikscj1zLmxlbmd0aCxxPSEx
-LHA9MDtwPHI7KytwKXtvPXNbcF0KaWYoSi5jcyhvLCIuLiIpKXtuPXQubGVuZ3RoCmlmKG4hPT0wKXtp
-ZigwPj1uKXJldHVybiBILmkodCwtMSkKdC5wb3AoKQppZih0Lmxlbmd0aD09PTApQy5iLmsodCwiIil9
-cT0hMH1lbHNlIGlmKCIuIj09PW8pcT0hMAplbHNle0MuYi5rKHQsbykKcT0hMX19aWYocSlDLmIuayh0
-LCIiKQpyZXR1cm4gQy5iLlQodCwiLyIpfSwKa1A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8K
-aWYoIVAuaW8oYSkpcmV0dXJuIWI/UC5pbChhKTphCnQ9SC5uKFtdLHUucykKZm9yKHM9YS5zcGxpdCgi
-LyIpLHI9cy5sZW5ndGgscT0hMSxwPTA7cDxyOysrcCl7bz1zW3BdCmlmKCIuLiI9PT1vKWlmKHQubGVu
-Z3RoIT09MCYmQy5iLmdhZyh0KSE9PSIuLiIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBILmkodCwtMSkK
-dC5wb3AoKQpxPSEwfWVsc2V7Qy5iLmsodCwiLi4iKQpxPSExfWVsc2UgaWYoIi4iPT09bylxPSEwCmVs
-c2V7Qy5iLmsodCxvKQpxPSExfX1zPXQubGVuZ3RoCmlmKHMhPT0wKWlmKHM9PT0xKXtpZigwPj1zKXJl
-dHVybiBILmkodCwwKQpzPXRbMF0ubGVuZ3RoPT09MH1lbHNlIHM9ITEKZWxzZSBzPSEwCmlmKHMpcmV0
-dXJuIi4vIgppZihxfHxDLmIuZ2FnKHQpPT09Ii4uIilDLmIuayh0LCIiKQppZighYil7aWYoMD49dC5s
-ZW5ndGgpcmV0dXJuIEguaSh0LDApCkMuYi5sKHQsMCxQLmlsKHRbMF0pKX1yZXR1cm4gQy5iLlQodCwi
-LyIpfSwKaWw6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS5sZW5ndGgKaWYocT49MiYmUC5pbShKLmhE
-KGEsMCkpKWZvcih0PTE7dDxxOysrdCl7cz1DLmEudChhLHQpCmlmKHM9PT01OClyZXR1cm4gQy5hLm4o
-YSwwLHQpKyIlM0EiK0MuYS5VKGEsdCsxKQppZihzPD0xMjcpe3I9cz4+PjQKaWYocj49OClyZXR1cm4g
-SC5pKEMuaixyKQpyPShDLmpbcl0mMTw8KHMmMTUpKT09PTB9ZWxzZSByPSEwCmlmKHIpYnJlYWt9cmV0
-dXJuIGF9LAprRjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpmb3IodD0wLHM9MDtzPDI7KytzKXtyPUMu
-YS50KGEsYitzKQppZig0ODw9ciYmcjw9NTcpdD10KjE2K3ItNDgKZWxzZXtyfD0zMgppZig5Nzw9ciYm
-cjw9MTAyKXQ9dCoxNityLTg3CmVsc2UgdGhyb3cgSC5hKFAuYjQoIkludmFsaWQgVVJMIGVuY29kaW5n
-IikpfX1yZXR1cm4gdH0sCmhmOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscD1iCndoaWxl
-KCEwKXtpZighKHA8Yykpe3Q9ITAKYnJlYWt9cz1DLmEudChhLHApCmlmKHM8PTEyNylpZihzIT09Mzcp
-cj1zPT09NDMKZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyKXt0PSExCmJyZWFrfSsrcH1pZih0KXtpZihD
-LmYhPT1kKXI9ITEKZWxzZSByPSEwCmlmKHIpcmV0dXJuIEMuYS5uKGEsYixjKQplbHNlIHE9bmV3IEgu
-Y3koQy5hLm4oYSxiLGMpKX1lbHNle3E9SC5uKFtdLHUudCkKZm9yKHI9YS5sZW5ndGgscD1iO3A8Yzsr
-K3Ape3M9Qy5hLnQoYSxwKQppZihzPjEyNyl0aHJvdyBILmEoUC5iNCgiSWxsZWdhbCBwZXJjZW50IGVu
-Y29kaW5nIGluIFVSSSIpKQppZihzPT09Mzcpe2lmKHArMz5yKXRocm93IEguYShQLmI0KCJUcnVuY2F0
-ZWQgVVJJIikpCkMuYi5rKHEsUC5rRihhLHArMSkpCnArPTJ9ZWxzZSBpZihzPT09NDMpQy5iLmsocSwz
-MikKZWxzZSBDLmIuayhxLHMpfX11LkwuYihxKQpyZXR1cm4gbmV3IFAuZGUoITEpLmFBKHEpfSwKaW06
-ZnVuY3Rpb24oYSl7dmFyIHQ9YXwzMgpyZXR1cm4gOTc8PXQmJnQ8PTEyMn0sCmk0OmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9IkludmFsaWQgTUlNRSB0eXBlIixrPUgubihbYi0xXSx1
-LnQpCmZvcih0PWEubGVuZ3RoLHM9YixyPS0xLHE9bnVsbDtzPHQ7KytzKXtxPUMuYS50KGEscykKaWYo
-cT09PTQ0fHxxPT09NTkpYnJlYWsKaWYocT09PTQ3KXtpZihyPDApe3I9cwpjb250aW51ZX10aHJvdyBI
-LmEoUC5BKGwsYSxzKSl9fWlmKHI8MCYmcz5iKXRocm93IEguYShQLkEobCxhLHMpKQpmb3IoO3EhPT00
-NDspe0MuYi5rKGsscyk7KytzCmZvcihwPS0xO3M8dDsrK3Mpe3E9Qy5hLnQoYSxzKQppZihxPT09NjEp
-e2lmKHA8MClwPXN9ZWxzZSBpZihxPT09NTl8fHE9PT00NClicmVha31pZihwPj0wKUMuYi5rKGsscCkK
-ZWxzZXtvPUMuYi5nYWcoaykKaWYocSE9PTQ0fHxzIT09bys3fHwhQy5hLlMoYSwiYmFzZTY0IixvKzEp
-KXRocm93IEguYShQLkEoIkV4cGVjdGluZyAnPSciLGEscykpCmJyZWFrfX1DLmIuayhrLHMpCm49cysx
-CmlmKChrLmxlbmd0aCYxKT09PTEpYT1DLkQuY2soYSxuLHQpCmVsc2V7bT1QLmlwKGEsbix0LEMuaSwh
-MCkKaWYobSE9bnVsbClhPUMuYS5hMChhLG4sdCxtKX1yZXR1cm4gbmV3IFAuZW0oYSxrLGMpfSwKa1c6
+PTEwMilyZXR1cm4gdC04NwpyZXR1cm4tMX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1AuazEoYiwic3Rh
+cnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILnZoKFAuVEUoYiwwLGMsInN0YXJ0
+IixudWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApXcDpmdW5jdGlvbigp
+e3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKZFU6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFAu
+bGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigiVG9v
+IGZldyBlbGVtZW50cyIpfSwKcWo6ZnVuY3Rpb24gcWooYSl7dGhpcy5hPWF9LApiUTpmdW5jdGlvbiBi
+USgpe30sCmFMOmZ1bmN0aW9uIGFMKCl7fSwKbkg6ZnVuY3Rpb24gbkgoYSxiLGMsZCl7dmFyIF89dGhp
+cwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKYTc6ZnVuY3Rpb24gYTcoYSxiLGMpe3ZhciBfPXRo
+aXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCkE4OmZ1bmN0aW9uIEE4KGEsYixj
+KXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKVTU6ZnVuY3Rpb24gVTUoYSxiLGMpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApTTzpmdW5jdGlvbiBTTyhhLGIsYyl7dGhpcy5hPWEKdGhp
+cy5iPWIKdGhpcy4kdGk9Y30sClNVOmZ1bmN0aW9uIFNVKCl7fSwKUmU6ZnVuY3Rpb24gUmUoKXt9LApY
+QzpmdW5jdGlvbiBYQygpe30sCnd2OmZ1bmN0aW9uIHd2KGEpe3RoaXMuYT1hfSwKZGM6ZnVuY3Rpb24o
+KXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgTWFwIikpfSwKTlE6ZnVu
+Y3Rpb24oYSl7dmFyIHQscz1ILkpnKGEpCmlmKHR5cGVvZiBzPT0ic3RyaW5nIilyZXR1cm4gcwp0PSJt
+aW5pZmllZDoiK2EKcmV0dXJuIHR9LAp3VjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGIhPW51bGwpe3Q9
+Yi54CmlmKHQhPW51bGwpcmV0dXJuIHR9cmV0dXJuIHUuYVUuYyhhKX0sCmQ6ZnVuY3Rpb24oYSl7dmFy
+IHQKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYo
+YSE9PTApcmV0dXJuIiIrYX1lbHNlIGlmKCEwPT09YSlyZXR1cm4idHJ1ZSIKZWxzZSBpZighMT09PWEp
+cmV0dXJuImZhbHNlIgplbHNlIGlmKGE9PW51bGwpcmV0dXJuIm51bGwiCnQ9Si5qKGEpCmlmKHR5cGVv
+ZiB0IT0ic3RyaW5nIil0aHJvdyBILmIoSC50TChhKSkKcmV0dXJuIHR9LAplUTpmdW5jdGlvbihhKXt2
+YXIgdD1hLiRpZGVudGl0eUhhc2gKaWYodD09bnVsbCl7dD1NYXRoLnJhbmRvbSgpKjB4M2ZmZmZmZmZ8
+MAphLiRpZGVudGl0eUhhc2g9dH1yZXR1cm4gdH0sCkhwOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEs
+cCxvPW51bGwsbj0vXlxzKlsrLV0/KCgweFthLWYwLTldKyl8KFxkKyl8KFthLXowLTldKykpXHMqJC9p
+LmV4ZWMoYSkKaWYobj09bnVsbClyZXR1cm4gbwppZigzPj1uLmxlbmd0aClyZXR1cm4gSC5PSChuLDMp
+CnQ9SC55KG5bM10pCmlmKGI9PW51bGwpe2lmKHQhPW51bGwpcmV0dXJuIHBhcnNlSW50KGEsMTApCmlm
+KG5bMl0hPW51bGwpcmV0dXJuIHBhcnNlSW50KGEsMTYpCnJldHVybiBvfWlmKGI8Mnx8Yj4zNil0aHJv
+dyBILmIoUC5URShiLDIsMzYsInJhZGl4IixvKSkKaWYoYj09PTEwJiZ0IT1udWxsKXJldHVybiBwYXJz
+ZUludChhLDEwKQppZihiPDEwfHx0PT1udWxsKXtzPWI8PTEwPzQ3K2I6ODYrYgpyPW5bMV0KZm9yKHE9
+ci5sZW5ndGgscD0wO3A8cTsrK3ApaWYoKEMueEIuVyhyLHApfDMyKT5zKXJldHVybiBvfXJldHVybiBw
+YXJzZUludChhLGIpfSwKTTpmdW5jdGlvbihhKXt2YXIgdD1ILkg1KGEpCnJldHVybiB0fSwKSDU6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyCmlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIEguZG0oSC56SyhhKSxu
+dWxsKQppZihKLmlhKGEpPT09Qy5Pa3x8dS5hay5jKGEpKXt0PUMuTzQoYSkKaWYoSC5mKHQpKXJldHVy
+biB0CnM9YS5jb25zdHJ1Y3RvcgppZih0eXBlb2Ygcz09ImZ1bmN0aW9uIil7cj1zLm5hbWUKaWYodHlw
+ZW9mIHI9PSJzdHJpbmciJiZILmYocikpcmV0dXJuIHJ9fXJldHVybiBILmRtKEgueksoYSksbnVsbCl9
+LApmOmZ1bmN0aW9uKGEpe3ZhciB0PWEhPT0iT2JqZWN0IiYmYSE9PSIiCnJldHVybiB0fSwKTTA6ZnVu
+Y3Rpb24oKXtpZighIXNlbGYubG9jYXRpb24pcmV0dXJuIHNlbGYubG9jYXRpb24uaHJlZgpyZXR1cm4g
+bnVsbH0sClZLOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YS5sZW5ndGgKaWYocDw9NTAwKXJldHVy
+biBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9IiIscz0wO3M8cDtzPXIpe3I9
+cys1MDAKcT1yPHA/cjpwCnQrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnNsaWNlKHMs
+cSkpfXJldHVybiB0fSwKUEw6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9SC5WTShbXSx1LnQpCmZvcih0
+PWEubGVuZ3RoLHM9MDtzPGEubGVuZ3RoO2EubGVuZ3RoPT09dHx8KDAsSC5saykoYSksKytzKXtyPWFb
+c10KaWYoIUgub2socikpdGhyb3cgSC5iKEgudEwocikpCmlmKHI8PTY1NTM1KUMuTm0uaShxLHIpCmVs
+c2UgaWYocjw9MTExNDExMSl7Qy5ObS5pKHEsNTUyOTYrKEMuam4ud0coci02NTUzNiwxMCkmMTAyMykp
+CkMuTm0uaShxLDU2MzIwKyhyJjEwMjMpKX1lbHNlIHRocm93IEguYihILnRMKHIpKX1yZXR1cm4gSC5W
+SyhxKX0sCmVUOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7
+cj1hW3NdCmlmKCFILm9rKHIpKXRocm93IEguYihILnRMKHIpKQppZihyPDApdGhyb3cgSC5iKEgudEwo
+cikpCmlmKHI+NjU1MzUpcmV0dXJuIEguUEwoYSl9cmV0dXJuIEguVksoYSl9LApmdzpmdW5jdGlvbihh
+LGIsYyl7dmFyIHQscyxyLHEKaWYoYzw9NTAwJiZiPT09MCYmYz09PWEubGVuZ3RoKXJldHVybiBTdHJp
+bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHQ9YixzPSIiO3Q8Yzt0PXIpe3I9dCs1MDAK
+cT1yPGM/cjpjCnMrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhLnN1YmFycmF5KHQscSkp
+fXJldHVybiBzfSwKTHc6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoMDw9YSl7aWYoYTw9NjU1MzUpcmV0dXJu
+IFN0cmluZy5mcm9tQ2hhckNvZGUoYSkKaWYoYTw9MTExNDExMSl7dD1hLTY1NTM2CnJldHVybiBTdHJp
+bmcuZnJvbUNoYXJDb2RlKCg1NTI5NnxDLmpuLndHKHQsMTApKT4+PjAsNTYzMjB8dCYxMDIzKX19dGhy
+b3cgSC5iKFAuVEUoYSwwLDExMTQxMTEsbnVsbCxudWxsKSl9LApvMjpmdW5jdGlvbihhKXtpZihhLmRh
+dGU9PT12b2lkIDApYS5kYXRlPW5ldyBEYXRlKGEuYSkKcmV0dXJuIGEuZGF0ZX0sCnRKOmZ1bmN0aW9u
+KGEpe3ZhciB0PUgubzIoYSkuZ2V0RnVsbFllYXIoKSswCnJldHVybiB0fSwKTlM6ZnVuY3Rpb24oYSl7
+dmFyIHQ9SC5vMihhKS5nZXRNb250aCgpKzEKcmV0dXJuIHR9LApqQTpmdW5jdGlvbihhKXt2YXIgdD1I
+Lm8yKGEpLmdldERhdGUoKSswCnJldHVybiB0fSwKS0w6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5n
+ZXRIb3VycygpKzAKcmV0dXJuIHR9LApjaDpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1pbnV0
+ZXMoKSswCnJldHVybiB0fSwKSmQ6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRTZWNvbmRzKCkr
+MApyZXR1cm4gdH0sCm8xOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0TWlsbGlzZWNvbmRzKCkr
+MApyZXR1cm4gdH0sCnpvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9e30Kci5hPTAKdD1bXQpzPVtd
+CnIuYT1iLmxlbmd0aApDLk5tLkZWKHQsYikKci5iPSIiCmlmKGMhPW51bGwmJmMuYSE9PTApYy5LKDAs
+bmV3IEguQ2oocixzLHQpKQoiIityLmEKcmV0dXJuIEouSnkoYSxuZXcgSC5MSShDLlRlLDAsdCxzLDAp
+KX0sCkVrOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihiIGluc3RhbmNlb2YgQXJyYXkpdD1j
+PT1udWxsfHxjLmE9PT0wCmVsc2UgdD0hMQppZih0KXtzPWIKcj1zLmxlbmd0aAppZihyPT09MCl7aWYo
+ISFhLiQwKXJldHVybiBhLiQwKCl9ZWxzZSBpZihyPT09MSl7aWYoISFhLiQxKXJldHVybiBhLiQxKHNb
+MF0pfWVsc2UgaWYocj09PTIpe2lmKCEhYS4kMilyZXR1cm4gYS4kMihzWzBdLHNbMV0pfWVsc2UgaWYo
+cj09PTMpe2lmKCEhYS4kMylyZXR1cm4gYS4kMyhzWzBdLHNbMV0sc1syXSl9ZWxzZSBpZihyPT09NCl7
+aWYoISFhLiQ0KXJldHVybiBhLiQ0KHNbMF0sc1sxXSxzWzJdLHNbM10pfWVsc2UgaWYocj09PTUpaWYo
+ISFhLiQ1KXJldHVybiBhLiQ1KHNbMF0sc1sxXSxzWzJdLHNbM10sc1s0XSkKcT1hWyIiKyIkIityXQpp
+ZihxIT1udWxsKXJldHVybiBxLmFwcGx5KGEscyl9cmV0dXJuIEguRXcoYSxiLGMpfSwKRXc6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPWIgaW5zdGFuY2VvZiBBcnJheT9iOlAuQ0go
+YiwhMCx1LnopLGo9ay5sZW5ndGgsaT1hLiRSCmlmKGo8aSlyZXR1cm4gSC56byhhLGssYykKdD1hLiRE
+CnM9dD09bnVsbApyPSFzP3QoKTpudWxsCnE9Si5pYShhKQpwPXEuJEMKaWYodHlwZW9mIHA9PSJzdHJp
+bmciKXA9cVtwXQppZihzKXtpZihjIT1udWxsJiZjLmEhPT0wKXJldHVybiBILnpvKGEsayxjKQppZihq
+PT09aSlyZXR1cm4gcC5hcHBseShhLGspCnJldHVybiBILnpvKGEsayxjKX1pZihyIGluc3RhbmNlb2Yg
+QXJyYXkpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0dXJuIEguem8oYSxrLGMpCmlmKGo+aStyLmxlbmd0
+aClyZXR1cm4gSC56byhhLGssbnVsbCkKQy5ObS5GVihrLHIuc2xpY2Uoai1pKSkKcmV0dXJuIHAuYXBw
+bHkoYSxrKX1lbHNle2lmKGo+aSlyZXR1cm4gSC56byhhLGssYykKbz1PYmplY3Qua2V5cyhyKQppZihj
+PT1udWxsKWZvcihzPW8ubGVuZ3RoLG49MDtuPG8ubGVuZ3RoO28ubGVuZ3RoPT09c3x8KDAsSC5sayko
+byksKytuKUMuTm0uaShrLHJbSC55KG9bbl0pXSkKZWxzZXtmb3Iocz1vLmxlbmd0aCxtPTAsbj0wO248
+by5sZW5ndGg7by5sZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24pe2w9SC55KG9bbl0pCmlmKGMueDQo
+bCkpeysrbQpDLk5tLmkoayxjLnEoMCxsKSl9ZWxzZSBDLk5tLmkoayxyW2xdKX1pZihtIT09Yy5hKXJl
+dHVybiBILnpvKGEsayxjKX1yZXR1cm4gcC5hcHBseShhLGspfX0sCnBZOmZ1bmN0aW9uKGEpe3Rocm93
+IEguYihILnRMKGEpKX0sCk9IOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClKLkhtKGEpCnRocm93IEgu
+YihILkhZKGEsYikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9ImluZGV4IgppZighSC5vayhi
+KSlyZXR1cm4gbmV3IFAudSghMCxiLHIsbnVsbCkKdD1ILlNjKEouSG0oYSkpCmlmKCEoYjwwKSl7aWYo
+dHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gSC5wWSh0KQpzPWI+PXR9ZWxzZSBzPSEwCmlmKHMpcmV0
+dXJuIFAuQ2YoYixhLHIsbnVsbCx0KQpyZXR1cm4gUC54KGIscil9LAphdTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQ9IkludmFsaWQgdmFsdWUiCmlmKGE+YylyZXR1cm4gbmV3IFAuYkooMCxjLCEwLGEsInN0YXJ0
+Iix0KQppZihiIT1udWxsKXtpZighSC5vayhiKSlyZXR1cm4gbmV3IFAudSghMCxiLCJlbmQiLG51bGwp
+CmlmKGI8YXx8Yj5jKXJldHVybiBuZXcgUC5iSihhLGMsITAsYiwiZW5kIix0KX1yZXR1cm4gbmV3IFAu
+dSghMCxiLCJlbmQiLG51bGwpfSwKdEw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLnUoITAsYSxudWxs
+LG51bGwpfSwKYjpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKWE9bmV3IFAubigpCnQ9bmV3IEVy
+cm9yKCkKdC5kYXJ0RXhjZXB0aW9uPWEKaWYoImRlZmluZVByb3BlcnR5IiBpbiBPYmplY3Qpe09iamVj
+dC5kZWZpbmVQcm9wZXJ0eSh0LCJtZXNzYWdlIix7Z2V0OkguaH0pCnQubmFtZT0iIn1lbHNlIHQudG9T
+dHJpbmc9SC5oCnJldHVybiB0fSwKaDpmdW5jdGlvbigpe3JldHVybiBKLmoodGhpcy5kYXJ0RXhjZXB0
+aW9uKX0sCnZoOmZ1bmN0aW9uKGEpe3Rocm93IEguYihhKX0sCmxrOmZ1bmN0aW9uKGEpe3Rocm93IEgu
+YihQLmE0KGEpKX0sCmNNOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbwphPUguZUEoYS5yZXBsYWNl
+KFN0cmluZyh7fSksJyRyZWNlaXZlciQnKSkKdD1hLm1hdGNoKC9cXFwkW2EtekEtWl0rXFxcJC9nKQpp
+Zih0PT1udWxsKXQ9SC5WTShbXSx1LnMpCnM9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNcXCQiKQpyPXQu
+aW5kZXhPZigiXFwkYXJndW1lbnRzRXhwclxcJCIpCnE9dC5pbmRleE9mKCJcXCRleHByXFwkIikKcD10
+LmluZGV4T2YoIlxcJG1ldGhvZFxcJCIpCm89dC5pbmRleE9mKCJcXCRyZWNlaXZlclxcJCIpCnJldHVy
+biBuZXcgSC5acihhLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c1xcXFxcXCQnLCdn
+JyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRhcmd1bWVudHNFeHBy
+XFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGV4
+cHJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwk
+bWV0aG9kXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxc
+XFxcJHJlY2VpdmVyXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLHMscixxLHAsbyl9LApTNzpm
+dW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24oJGV4cHIkKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJn
+dW1lbnRzJCcKdHJ5eyRleHByJC4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHQpe3JldHVy
+biB0Lm1lc3NhZ2V9fShhKX0sCk1qOmZ1bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhwciQpe3Ry
+eXskZXhwciQuJG1ldGhvZCR9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKSWo6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gbmV3IEguVzAoYSxiPT1udWxsP251bGw6Yi5tZXRob2QpfSwKVDM6ZnVuY3Rp
+b24oYSxiKXt2YXIgdD1iPT1udWxsLHM9dD9udWxsOmIubWV0aG9kCnJldHVybiBuZXcgSC5heihhLHMs
+dD9udWxsOmIucmVjZWl2ZXIpfSwKUnU6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
+aixpLGgsZyxmPW51bGwsZT1uZXcgSC5BbShhKQppZihhPT1udWxsKXJldHVybiBmCmlmKHR5cGVvZiBh
+IT09Im9iamVjdCIpcmV0dXJuIGEKaWYoImRhcnRFeGNlcHRpb24iIGluIGEpcmV0dXJuIGUuJDEoYS5k
+YXJ0RXhjZXB0aW9uKQplbHNlIGlmKCEoIm1lc3NhZ2UiIGluIGEpKXJldHVybiBhCnQ9YS5tZXNzYWdl
+CmlmKCJudW1iZXIiIGluIGEmJnR5cGVvZiBhLm51bWJlcj09Im51bWJlciIpe3M9YS5udW1iZXIKcj1z
+JjY1NTM1CmlmKChDLmpuLndHKHMsMTYpJjgxOTEpPT09MTApc3dpdGNoKHIpe2Nhc2UgNDM4OnJldHVy
+biBlLiQxKEguVDMoSC5kKHQpKyIgKEVycm9yICIrcisiKSIsZikpCmNhc2UgNDQ1OmNhc2UgNTAwNzpy
+ZXR1cm4gZS4kMShILklqKEguZCh0KSsiIChFcnJvciAiK3IrIikiLGYpKX19aWYoYSBpbnN0YW5jZW9m
+IFR5cGVFcnJvcil7cT0kLlNuKCkKcD0kLmxxKCkKbz0kLk45KCkKbj0kLmlJKCkKbT0kLktmKCkKbD0k
+LlpoKCkKaz0kLnJOKCkKJC5jMygpCmo9JC5ISygpCmk9JC5yMSgpCmg9cS5xUyh0KQppZihoIT1udWxs
+KXJldHVybiBlLiQxKEguVDMoSC55KHQpLGgpKQplbHNle2g9cC5xUyh0KQppZihoIT1udWxsKXtoLm1l
+dGhvZD0iY2FsbCIKcmV0dXJuIGUuJDEoSC5UMyhILnkodCksaCkpfWVsc2V7aD1vLnFTKHQpCmlmKGg9
+PW51bGwpe2g9bi5xUyh0KQppZihoPT1udWxsKXtoPW0ucVModCkKaWYoaD09bnVsbCl7aD1sLnFTKHQp
+CmlmKGg9PW51bGwpe2g9ay5xUyh0KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1q
+LnFTKHQpCmlmKGg9PW51bGwpe2g9aS5xUyh0KQpnPWghPW51bGx9ZWxzZSBnPSEwfWVsc2UgZz0hMH1l
+bHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwCmlmKGcpcmV0dXJu
+IGUuJDEoSC5JaihILnkodCksaCkpfX1yZXR1cm4gZS4kMShuZXcgSC52Vih0eXBlb2YgdD09InN0cmlu
+ZyI/dDoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5nZUVycm9yKXtpZih0eXBlb2YgdD09InN0cmluZyIm
+JnQuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEpcmV0dXJuIG5ldyBQLktZKCkKdD1mdW5jdGlvbihi
+KXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChkKXt9cmV0dXJuIG51bGx9KGEpCnJldHVybiBlLiQx
+KG5ldyBQLnUoITEsZixmLHR5cGVvZiB0PT0ic3RyaW5nIj90LnJlcGxhY2UoL15SYW5nZUVycm9yOlxz
+Ki8sIiIpOnQpKX1pZih0eXBlb2YgSW50ZXJuYWxFcnJvcj09ImZ1bmN0aW9uIiYmYSBpbnN0YW5jZW9m
+IEludGVybmFsRXJyb3IpaWYodHlwZW9mIHQ9PSJzdHJpbmciJiZ0PT09InRvbyBtdWNoIHJlY3Vyc2lv
+biIpcmV0dXJuIG5ldyBQLktZKCkKcmV0dXJuIGF9LAp0czpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1u
+dWxsKXJldHVybiBuZXcgSC5YTyhhKQp0PWEuJGNhY2hlZFRyYWNlCmlmKHQhPW51bGwpcmV0dXJuIHQK
+cmV0dXJuIGEuJGNhY2hlZFRyYWNlPW5ldyBILlhPKGEpfSwKQjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHIscT1hLmxlbmd0aApmb3IodD0wO3Q8cTt0PXIpe3M9dCsxCnI9cysxCmIuWSgwLGFbdF0sYVtzXSl9
+cmV0dXJuIGJ9LApmdDpmdW5jdGlvbihhLGIsYyxkLGUsZil7dS5aLmIoYSkKc3dpdGNoKEguU2MoYikp
+e2Nhc2UgMDpyZXR1cm4gYS4kMCgpCmNhc2UgMTpyZXR1cm4gYS4kMShjKQpjYXNlIDI6cmV0dXJuIGEu
+JDIoYyxkKQpjYXNlIDM6cmV0dXJuIGEuJDMoYyxkLGUpCmNhc2UgNDpyZXR1cm4gYS4kNChjLGQsZSxm
+KX10aHJvdyBILmIobmV3IFAuQ0QoIlVuc3VwcG9ydGVkIG51bWJlciBvZiBhcmd1bWVudHMgZm9yIHdy
+YXBwZWQgY2xvc3VyZSIpKX0sCnRSOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4g
+bnVsbAp0PWEuJGlkZW50aXR5CmlmKCEhdClyZXR1cm4gdAp0PWZ1bmN0aW9uKGMsZCxlKXtyZXR1cm4g
+ZnVuY3Rpb24oZixnLGgsaSl7cmV0dXJuIGUoYyxkLGYsZyxoLGkpfX0oYSxiLEguZnQpCmEuJGlkZW50
+aXR5PXQKcmV0dXJuIHR9LAppQTpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2YXIgdCxzLHIscSxwLG8s
+bixtLGw9bnVsbCxrPWJbMF0saj1rLiRjYWxsTmFtZSxpPWU/T2JqZWN0LmNyZWF0ZShuZXcgSC56eCgp
+LmNvbnN0cnVjdG9yLnByb3RvdHlwZSk6T2JqZWN0LmNyZWF0ZShuZXcgSC5yVChsLGwsbCxsKS5jb25z
+dHJ1Y3Rvci5wcm90b3R5cGUpCmkuJGluaXRpYWxpemU9aS5jb25zdHJ1Y3RvcgppZihlKXQ9ZnVuY3Rp
+b24gc3RhdGljX3RlYXJfb2ZmKCl7dGhpcy4kaW5pdGlhbGl6ZSgpfQplbHNle3M9JC55agppZih0eXBl
+b2YgcyE9PSJudW1iZXIiKXJldHVybiBzLmgoKQokLnlqPXMrMQpzPW5ldyBGdW5jdGlvbigiYSxiLGMs
+ZCIrcywidGhpcy4kaW5pdGlhbGl6ZShhLGIsYyxkIitzKyIpIikKdD1zfWkuY29uc3RydWN0b3I9dAp0
+LnByb3RvdHlwZT1pCmlmKCFlKXtyPUguYngoYSxrLGYpCnIuJHJlZmxlY3Rpb25JbmZvPWR9ZWxzZXtp
+LiRzdGF0aWNfbmFtZT1nCnI9a31xPUguaW0oZCxlLGYpCmkuJFM9cQppW2pdPXIKZm9yKHA9cixvPTE7
+bzxiLmxlbmd0aDsrK28pe249YltvXQptPW4uJGNhbGxOYW1lCmlmKG0hPW51bGwpe249ZT9uOkguYngo
+YSxuLGYpCmlbbV09bn1pZihvPT09Yyl7bi4kcmVmbGVjdGlvbkluZm89ZApwPW59fWkuJEM9cAppLiRS
+PWsuJFIKaS4kRD1rLiRECnJldHVybiB0fSwKaW06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKHR5cGVv
+ZiBhPT0ibnVtYmVyIilyZXR1cm4gZnVuY3Rpb24oZCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4g
+ZChlKX19KEguQnAsYSkKaWYodHlwZW9mIGE9PSJzdHJpbmciKXtpZihiKXRocm93IEguYigiQ2Fubm90
+IGNvbXB1dGUgc2lnbmF0dXJlIGZvciBzdGF0aWMgdGVhcm9mZi4iKQp0PWM/SC5QVzpILlRuCnJldHVy
+biBmdW5jdGlvbihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBlKHRoaXMsZCl9fShhLHQpfXRo
+cm93IEguYigiRXJyb3IgaW4gZnVuY3Rpb25UeXBlIG9mIHRlYXJvZmYiKX0sCnZxOmZ1bmN0aW9uKGEs
+YixjLGQpe3ZhciB0PUguRFYKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnJldHVybiBmdW5jdGlvbihlLGYp
+e3JldHVybiBmdW5jdGlvbigpe3JldHVybiBmKHRoaXMpW2VdKCl9fShjLHQpCmNhc2UgMTpyZXR1cm4g
+ZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyl7cmV0dXJuIGYodGhpcylbZV0oZyl9fShjLHQp
+CmNhc2UgMjpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoKXtyZXR1cm4gZih0
+aGlzKVtlXShnLGgpfX0oYyx0KQpjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0
+aW9uKGcsaCxpKXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSl9fShjLHQpCmNhc2UgNDpyZXR1cm4gZnVu
+Y3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyxoLGks
+ail9fShjLHQpCmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGks
+aixrKXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSxqLGspfX0oYyx0KQpkZWZhdWx0OnJldHVybiBmdW5j
+dGlvbihlLGYpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBlLmFwcGx5KGYodGhpcyksYXJndW1lbnRz
+KX19KGQsdCl9fSwKYng6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuCmlmKGMpcmV0dXJu
+IEguSGYoYSxiKQp0PWIuJHN0dWJOYW1lCnM9Yi5sZW5ndGgKcj1hW3RdCnE9Yj09bnVsbD9yPT1udWxs
+OmI9PT1yCnA9IXF8fHM+PTI3CmlmKHApcmV0dXJuIEgudnEocywhcSx0LGIpCmlmKHM9PT0wKXtxPSQu
+eWoKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS5oKCkKJC55aj1xKzEKbz0ic2VsZiIrcQpx
+PSJyZXR1cm4gZnVuY3Rpb24oKXt2YXIgIitvKyIgPSB0aGlzLiIKcD0kLm1KCnJldHVybiBuZXcgRnVu
+Y3Rpb24ocStILmQocD09bnVsbD8kLm1KPUguRTIoInNlbGYiKTpwKSsiO3JldHVybiAiK28rIi4iK0gu
+ZCh0KSsiKCk7fSIpKCl9bj0iYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxp
+Y2UoMCxzKS5qb2luKCIsIikKcT0kLnlqCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuaCgp
+CiQueWo9cSsxCm4rPXEKcT0icmV0dXJuIGZ1bmN0aW9uKCIrbisiKXtyZXR1cm4gdGhpcy4iCnA9JC5t
+SgpyZXR1cm4gbmV3IEZ1bmN0aW9uKHErSC5kKHA9PW51bGw/JC5tSj1ILkUyKCJzZWxmIik6cCkrIi4i
+K0guZCh0KSsiKCIrbisiKTt9IikoKX0sClo0OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PUguRFYscz1I
+LnlTCnN3aXRjaChiPy0xOmEpe2Nhc2UgMDp0aHJvdyBILmIoSC5FZigiSW50ZXJjZXB0ZWQgZnVuY3Rp
+b24gd2l0aCBubyBhcmd1bWVudHMuIikpCmNhc2UgMTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVy
+biBmdW5jdGlvbigpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcykpfX0oYyx0LHMpCmNhc2UgMjpyZXR1
+cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
+aXMpLGgpfX0oYyx0LHMpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlv
+bihoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpKX19KGMsdCxzKQpjYXNlIDQ6cmV0dXJu
+IGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGco
+dGhpcyksaCxpLGopfX0oYyx0LHMpCmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBm
+dW5jdGlvbihoLGksaixrKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGspfX0oYyx0LHMp
+CmNhc2UgNjpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksaixrLGwpe3Jl
+dHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayxsKX19KGMsdCxzKQpkZWZhdWx0OnJldHVybiBm
+dW5jdGlvbihlLGYsZyxoKXtyZXR1cm4gZnVuY3Rpb24oKXtoPVtnKHRoaXMpXQpBcnJheS5wcm90b3R5
+cGUucHVzaC5hcHBseShoLGFyZ3VtZW50cykKcmV0dXJuIGUuYXBwbHkoZih0aGlzKSxoKX19KGQsdCxz
+KX19LApIZjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG09JC5tSgppZihtPT1udWxsKW09
+JC5tSj1ILkUyKCJzZWxmIikKdD0kLlA0CmlmKHQ9PW51bGwpdD0kLlA0PUguRTIoInJlY2VpdmVyIikK
+cz1iLiRzdHViTmFtZQpyPWIubGVuZ3RoCnE9YVtzXQpwPWI9PW51bGw/cT09bnVsbDpiPT09cQpvPSFw
+fHxyPj0yOAppZihvKXJldHVybiBILlo0KHIsIXAscyxiKQppZihyPT09MSl7bT0icmV0dXJuIGZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMuIitILmQobSkrIi4iK0guZChzKSsiKHRoaXMuIitILmQodCkrIik7Igp0
+PSQueWoKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5oKCkKJC55aj10KzEKcmV0dXJuIG5l
+dyBGdW5jdGlvbihtK3QrIn0iKSgpfW49ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgi
+Iikuc3BsaWNlKDAsci0xKS5qb2luKCIsIikKbT0icmV0dXJuIGZ1bmN0aW9uKCIrbisiKXtyZXR1cm4g
+dGhpcy4iK0guZChtKSsiLiIrSC5kKHMpKyIodGhpcy4iK0guZCh0KSsiLCAiK24rIik7Igp0PSQueWoK
+aWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5oKCkKJC55aj10KzEKcmV0dXJuIG5ldyBGdW5j
+dGlvbihtK3QrIn0iKSgpfSwKS3E6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7cmV0dXJuIEguaUEoYSxi
+LGMsZCwhIWUsISFmLGcpfSwKVG46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJz
+ZSxILnpLKGEuYSksYil9LApQVzpmdW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNl
+LEgueksoYS5jKSxiKX0sCkRWOmZ1bmN0aW9uKGEpe3JldHVybiBhLmF9LAp5UzpmdW5jdGlvbihhKXty
+ZXR1cm4gYS5jfSwKRTI6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9bmV3IEguclQoInNlbGYiLCJ0YXJn
+ZXQiLCJyZWNlaXZlciIsIm5hbWUiKSxwPUouRXAoT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocSkp
+CmZvcih0PXAubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPXBbc10KaWYocVtyXT09PWEpcmV0dXJuIHJ9fSwK
+b1Q6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClILmZPKCJib29sZWFuIGV4cHJlc3Npb24gbXVzdCBub3Qg
+YmUgbnVsbCIpCnJldHVybiBhfSwKZk86ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5ldyBILmtZKGEpKX0s
+CmFnOmZ1bmN0aW9uKGEpe3Rocm93IEguYihuZXcgUC5jKGEpKX0sCkVmOmZ1bmN0aW9uKGEpe3JldHVy
+biBuZXcgSC5FcShhKX0sCllnOmZ1bmN0aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApW
+TTpmdW5jdGlvbihhLGIpe2EuJHRpPWIKcmV0dXJuIGF9LApvWDpmdW5jdGlvbihhKXtpZihhPT1udWxs
+KXJldHVybiBudWxsCnJldHVybiBhLiR0aX0sCklNOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSC5ZOShh
+WyIkYSIrSC5kKGMpXSxILm9YKGIpKX0sClk5OmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClyZXR1cm4g
+YgphPWEuYXBwbHkobnVsbCxiKQppZihhPT1udWxsKXJldHVybiBudWxsCmlmKEFycmF5LmlzQXJyYXko
+YSkpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIGEuYXBwbHkobnVsbCxiKQpy
+ZXR1cm4gYn0sCklHOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYS5hcHBseShiLEguWTkoSi5pYShiKVsi
+JGEiK0guZChjKV0sSC5vWChiKSkpfSwKaXc6ZnVuY3Rpb24oYSxiLGMpe09iamVjdC5kZWZpbmVQcm9w
+ZXJ0eShhLGIse3ZhbHVlOmMsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJs
+ZTp0cnVlfSl9LAp3MzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPUgueSgkLk5GLiQxKGEpKSxvPSQu
+bndbcF0KaWYobyE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRjaFByb3BlcnR5
+TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRy
+dWV9KQpyZXR1cm4gby5pfXQ9JC52dltwXQppZih0IT1udWxsKXJldHVybiB0CnM9di5pbnRlcmNlcHRv
+cnNCeVRhZ1twXQppZihzPT1udWxsKXtwPUgueSgkLlRYLiQyKGEscCkpCmlmKHAhPW51bGwpe289JC5u
+d1twXQppZihvIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlO
+YW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1
+ZX0pCnJldHVybiBvLml9dD0kLnZ2W3BdCmlmKHQhPW51bGwpcmV0dXJuIHQKcz12LmludGVyY2VwdG9y
+c0J5VGFnW3BdfX1pZihzPT1udWxsKXJldHVybiBudWxsCnQ9cy5wcm90b3R5cGUKcj1wWzBdCmlmKHI9
+PT0iISIpe289SC5WYSh0KQokLm53W3BdPW8KT2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRj
+aFByb3BlcnR5TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmln
+dXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfWlmKHI9PT0ifiIpeyQudnZbcF09dApyZXR1cm4gdH1pZihy
+PT09Ii0iKXtxPUguVmEodCkKT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVP
+ZihhKSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFi
+bGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBxLml9aWYocj09PSIrIilyZXR1cm4gSC5M
+YyhhLHQpCmlmKHI9PT0iKiIpdGhyb3cgSC5iKFAuU1kocCkpCmlmKHYubGVhZlRhZ3NbcF09PT10cnVl
+KXtxPUguVmEodCkKT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSx2
+LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1
+ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBxLml9ZWxzZSByZXR1cm4gSC5MYyhhLHQpfSwKTGM6
+ZnVuY3Rpb24oYSxiKXt2YXIgdD1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkKT2JqZWN0LmRlZmluZVBy
+b3BlcnR5KHQsdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6Si5RdShiLHQsbnVsbCxudWxsKSxl
+bnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gYn0s
+ClZhOmZ1bmN0aW9uKGEpe3JldHVybiBKLlF1KGEsITEsbnVsbCwhIWEuJGlYail9LApWRjpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQ9Yi5wcm90b3R5cGUKaWYodi5sZWFmVGFnc1thXT09PXRydWUpcmV0dXJuIEgu
+VmEodCkKZWxzZSByZXR1cm4gSi5RdSh0LGMsbnVsbCxudWxsKX0sClhEOmZ1bmN0aW9uKCl7aWYoITA9
+PT0kLkJ2KXJldHVybgokLkJ2PSEwCkguWjEoKX0sCloxOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxv
+LG4sbQokLm53PU9iamVjdC5jcmVhdGUobnVsbCkKJC52dj1PYmplY3QuY3JlYXRlKG51bGwpCkgua08o
+KQp0PXYuaW50ZXJjZXB0b3JzQnlUYWcKcz1PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0KQppZih0
+eXBlb2Ygd2luZG93IT0idW5kZWZpbmVkIil7d2luZG93CnI9ZnVuY3Rpb24oKXt9CmZvcihxPTA7cTxz
+Lmxlbmd0aDsrK3Epe3A9c1txXQpvPSQueDcuJDEocCkKaWYobyE9bnVsbCl7bj1ILlZGKHAsdFtwXSxv
+KQppZihuIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkobyx2LmRpc3BhdGNoUHJvcGVydHlOYW1l
+LHt2YWx1ZTpuLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0p
+CnIucHJvdG90eXBlPW99fX19Zm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCmlmKC9eW0EtWmEt
+el9dLy50ZXN0KHApKXttPXRbcF0KdFsiISIrcF09bQp0WyJ+IitwXT1tCnRbIi0iK3BdPW0KdFsiKyIr
+cF09bQp0WyIqIitwXT1tfX19LAprTzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuPUMuWXEoKQpu
+PUgudWQoQy5LVSxILnVkKEMuZlEsSC51ZChDLmk3LEgudWQoQy5pNyxILnVkKEMueGksSC51ZChDLmRr
+LEgudWQoQy53YihDLk80KSxuKSkpKSkpKQppZih0eXBlb2YgZGFydE5hdGl2ZURpc3BhdGNoSG9va3NU
+cmFuc2Zvcm1lciE9InVuZGVmaW5lZCIpe3Q9ZGFydE5hdGl2ZURpc3BhdGNoSG9va3NUcmFuc2Zvcm1l
+cgppZih0eXBlb2YgdD09ImZ1bmN0aW9uIil0PVt0XQppZih0LmNvbnN0cnVjdG9yPT1BcnJheSlmb3Io
+cz0wO3M8dC5sZW5ndGg7KytzKXtyPXRbc10KaWYodHlwZW9mIHI9PSJmdW5jdGlvbiIpbj1yKG4pfHxu
+fX1xPW4uZ2V0VGFnCnA9bi5nZXRVbmtub3duVGFnCm89bi5wcm90b3R5cGVGb3JUYWcKJC5ORj1uZXcg
+SC5kQyhxKQokLlRYPW5ldyBILndOKHApCiQueDc9bmV3IEguVlgobyl9LAp1ZDpmdW5jdGlvbihhLGIp
+e3JldHVybiBhKGIpfHxifSwKdjQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0PWI/Im0iOiIiLHM9
+Yz8iIjoiaSIscj1kPyJ1IjoiIixxPWU/InMiOiIiLHA9Zj8iZyI6IiIsbz1mdW5jdGlvbihnLGgpe3Ry
+eXtyZXR1cm4gbmV3IFJlZ0V4cChnLGgpfWNhdGNoKG4pe3JldHVybiBufX0oYSx0K3MrcitxK3ApCmlm
+KG8gaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIG8KdGhyb3cgSC5iKFAucnIoIklsbGVnYWwgUmVnRXhw
+IHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51bGwpKX0sCm0yOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dAppZih0eXBlb2YgYj09InN0cmluZyIpcmV0dXJuIGEuaW5kZXhPZihiLGMpPj0wCmVsc2UgaWYoYiBp
+bnN0YW5jZW9mIEguVlIpe3Q9Qy54Qi5HKGEsYykKcmV0dXJuIGIuYi50ZXN0KHQpfWVsc2V7dD1KLkZM
+KGIsQy54Qi5HKGEsYykpCnJldHVybiF0LmdsMCh0KX19LApBNDpmdW5jdGlvbihhKXtpZihhLmluZGV4
+T2YoIiQiLDApPj0wKXJldHVybiBhLnJlcGxhY2UoL1wkL2csIiQkJCQiKQpyZXR1cm4gYX0sCmVBOmZ1
+bmN0aW9uKGEpe2lmKC9bW1xde30oKSorPy5cXF4kfF0vLnRlc3QoYSkpcmV0dXJuIGEucmVwbGFjZSgv
+W1tcXXt9KCkqKz8uXFxeJHxdL2csIlxcJCYiKQpyZXR1cm4gYX0sCnlzOmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdD1ILm5NKGEsYixjKQpyZXR1cm4gdH0sCm5NOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQpp
+ZihiPT09IiIpe2lmKGE9PT0iIilyZXR1cm4gYwp0PWEubGVuZ3RoCmZvcihzPWMscj0wO3I8dDsrK3Ip
+cz1zK2Fbcl0rYwpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c31xPWEuaW5kZXhPZihiLDApCmlm
+KHE8MClyZXR1cm4gYQppZihhLmxlbmd0aDw1MDB8fGMuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEu
+c3BsaXQoYikuam9pbihjKQpyZXR1cm4gYS5yZXBsYWNlKG5ldyBSZWdFeHAoSC5lQShiKSwnZycpLEgu
+QTQoYykpfSwKUEQ6ZnVuY3Rpb24gUEQoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKV1U6ZnVuY3Rp
+b24gV1UoKXt9LApMUDpmdW5jdGlvbiBMUChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
+Yz1jCl8uJHRpPWR9LApMSTpmdW5jdGlvbiBMSShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5j
+PWIKXy5kPWMKXy5lPWQKXy5mPWV9LApDajpmdW5jdGlvbiBDaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5i
+PWIKdGhpcy5jPWN9LApacjpmdW5jdGlvbiBacihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpf
+LmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClcwOmZ1bmN0aW9uIFcwKGEsYil7dGhpcy5hPWEK
+dGhpcy5iPWJ9LAphejpmdW5jdGlvbiBheihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LAp2VjpmdW5jdGlvbiB2VihhKXt0aGlzLmE9YX0sCkFtOmZ1bmN0aW9uIEFtKGEpe3RoaXMuYT1hfSwK
+WE86ZnVuY3Rpb24gWE8oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LApUcDpmdW5jdGlvbiBUcCgpe30s
+CmxjOmZ1bmN0aW9uIGxjKCl7fSwKeng6ZnVuY3Rpb24gengoKXt9LApyVDpmdW5jdGlvbiByVChhLGIs
+YyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKRXE6ZnVuY3Rpb24gRXEoYSl7
+dGhpcy5hPWF9LAprWTpmdW5jdGlvbiBrWShhKXt0aGlzLmE9YX0sCk41OmZ1bmN0aW9uIE41KGEpe3Zh
+ciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApkYjpm
+dW5jdGlvbiBkYihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVu
+Y3Rpb24gaTUoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhh
+KXt0aGlzLmE9YX0sCndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7
+dGhpcy5hPWF9LApWUjpmdW5jdGlvbiBWUihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8u
+Yz1udWxsfSwKRUs6ZnVuY3Rpb24gRUsoYSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7
+dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhp
+cwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEK
+dGhpcy5jPWJ9LAp1bjpmdW5jdGlvbiB1bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApTZDpmdW5jdGlvbiBTZChhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVs
+bH0sClhGOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKRFE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBJbnQ4
+QXJyYXkoYSl9LApvZDpmdW5jdGlvbihhLGIsYyl7aWYoYT4+PjAhPT1hfHxhPj1jKXRocm93IEguYihI
+LkhZKGIsYSkpfSwKck06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKCEoYT4+PjAhPT1hKSl0PWI+Pj4w
+IT09Ynx8YT5ifHxiPmMKZWxzZSB0PSEwCmlmKHQpdGhyb3cgSC5iKEguYXUoYSxiLGMpKQpyZXR1cm4g
+Yn0sCkVUOmZ1bmN0aW9uIEVUKCl7fSwKYjA6ZnVuY3Rpb24gYjAoKXt9LApEZzpmdW5jdGlvbiBEZygp
+e30sClBnOmZ1bmN0aW9uIFBnKCl7fSwKeGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgp
+e30sClpBOmZ1bmN0aW9uIFpBKCl7fSwKd2Y6ZnVuY3Rpb24gd2YoKXt9LApQcTpmdW5jdGlvbiBQcSgp
+e30sCmVFOmZ1bmN0aW9uIGVFKCl7fSwKVjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygp
+e30sClZQOmZ1bmN0aW9uIFZQKCl7fSwKV0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygp
+e30sCnhaOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5kCnJldHVybiB0PT1udWxsP2IuZD1ILkooYSwiYjgi
+LFtiLlFdKTp0fSwKUTE6ZnVuY3Rpb24oYSl7dmFyIHQ9YS56CmlmKHQ9PT02fHx0PT09N3x8dD09PTgp
+cmV0dXJuIEguUTEoYS5RKQpyZXR1cm4gdD09PTExfHx0PT09MTJ9LAptRDpmdW5jdGlvbihhKXtyZXR1
+cm4gYS5kYn0sCk4wOmZ1bmN0aW9uKGEpe3JldHVybiBILkUodi50eXBlVW5pdmVyc2UsYSl9LApKUzpm
+dW5jdGlvbihhKXt2YXIgdD1hLiRTCmlmKHQhPW51bGwpe2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1
+cm4gSC5CcCh0KQpyZXR1cm4gYS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIg
+dAppZihILlExKGIpKWlmKGEgaW5zdGFuY2VvZiBILlRwKXt0PUguSlMoYSkKaWYodCE9bnVsbClyZXR1
+cm4gdH1yZXR1cm4gSC56SyhhKX0sCnpLOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGEgaW5zdGFuY2VvZiBQ
+Lmspe3Q9YS4kdGkKcmV0dXJuIHQhPW51bGw/dDpILlZVKGEpfWlmKEFycmF5LmlzQXJyYXkoYSkpcmV0
+dXJuIEgudDYoYSkKcmV0dXJuIEguVlUoSi5pYShhKSl9LAp0NjpmdW5jdGlvbihhKXt2YXIgdD1hLiR0
+aSxzPXUuYgppZih0PT1udWxsKXJldHVybiBzCmlmKHQuY29uc3RydWN0b3IhPT1zLmNvbnN0cnVjdG9y
+KXJldHVybiBzCnJldHVybiB0fSwKTGg6ZnVuY3Rpb24oYSl7dmFyIHQ9YS4kdGkKcmV0dXJuIHQhPW51
+bGw/dDpILlZVKGEpfSwKVlU6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5jb25zdHJ1Y3RvcixzPXQuJGNjYWNo
+ZQppZihzIT1udWxsKXJldHVybiBzCnJldHVybiBILnI5KGEsdCl9LApyOTpmdW5jdGlvbihhLGIpe3Zh
+ciB0PWEgaW5zdGFuY2VvZiBILlRwP2EuX19wcm90b19fLl9fcHJvdG9fXy5jb25zdHJ1Y3RvcjpiLHM9
+SC5haSh2LnR5cGVVbml2ZXJzZSx0Lm5hbWUpCmIuJGNjYWNoZT1zCnJldHVybiBzfSwKQnA6ZnVuY3Rp
+b24oYSl7dmFyIHQscz1hLHI9di50eXBlcyxxPXJbc10KaWYodHlwZW9mIHE9PSJzdHJpbmciKXt0PUgu
+RSh2LnR5cGVVbml2ZXJzZSxxKQpyW3NdPXQKcmV0dXJuIHR9cmV0dXJuIHF9LApKSjpmdW5jdGlvbihh
+KXt2YXIgdCxzPXRoaXMscj1zLnoscT1ILllPCmlmKEguY2Mocykpe3E9SC5JdwpzLmI9cy5hPUguaG59
+ZWxzZSBpZihyPT09OSl7dD1zLmRiCmlmKCJLTiI9PT10KXE9SC5vawplbHNlIGlmKCJDUCI9PT10KXE9
+SC5LSAplbHNlIGlmKCJGSyI9PT10KXE9SC5LSAplbHNlIGlmKCJxVSI9PT10KXE9SC5NTQplbHNlIGlm
+KCJhMiI9PT10KXE9SC5sCmVsc2V7cj1zLlEKaWYocy5jaC5ldmVyeShILmNjKSl7cy54PSIkaSIrcgpx
+PUgudDR9fX1zLmM9cQpyZXR1cm4gcy5jKGEpfSwKWU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwpyZXR1
+cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEsdCksbnVsbCx0LG51bGwpfSwKdDQ6ZnVuY3Rpb24o
+YSl7dmFyIHQ9dGhpcy54CmlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuISFhW3RdCnJldHVybiEhSi5p
+YShhKVt0XX0sCk96OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIGEKdD10aGlzCmlm
+KHQuYyhhKSlyZXR1cm4gYQp0aHJvdyBILmIoSC5RNShILldLKGEsSC5VZShhLHQpLEguZG0odCxudWxs
+KSkpKX0sCkF2OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIGEKdD10aGlzCmlmKHQu
+YyhhKSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYyhILldLKGEsSC5VZShhLHQpLEguZG0odCxudWxsKSkp
+KX0sCkRoOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PW51bGwKaWYoSC5XZSh2LnR5cGVVbml2ZXJzZSxh
+LHQsYix0KSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYygiVGhlIHR5cGUgYXJndW1lbnQgJyIrSC5kKEgu
+ZG0oYSx0KSkrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitI
+LmQoSC5kbShiLHQpKSsiJyBvZiB0eXBlIHZhcmlhYmxlICciK2MrIicgaW4gJyIrSC5kKGQpKyInLiIp
+KX0sCldLOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLnAoYSkscz1ILmRtKGI9PW51bGw/SC56SyhhKTpi
+LG51bGwpCnJldHVybiB0KyI6IHR5cGUgJyIrSC5kKHMpKyInIGlzIG5vdCBhIHN1YnR5cGUgb2YgdHlw
+ZSAnIitILmQoYykrIicifSwKUTU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmh6KCJDYXN0RXJyb3I6
+ICIrYSl9LApQdjpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5oeigiQ2FzdEVycm9yOiAiK0guV0so
+YSxudWxsLGIpKX0sClpjOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5pTSgiVHlwZUVycm9yOiAiK2Ep
+fSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5pTSgiVHlwZUVycm9yOiAiK0guV0soYSxudWxs
+LGIpKX0sCkl3OmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKaG46ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LAps
+OmZ1bmN0aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKRTk6ZnVuY3Rpb24oYSl7aWYoITA9PT1h
+fHwhMT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJib29s
+IikpfSwKeGQ6ZnVuY3Rpb24oYSl7aWYoITA9PT1hfHwhMT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbCly
+ZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImJvb2wiKSl9LApkajpmdW5jdGlvbihhKXtpZih0eXBlb2Yg
+YT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJk
+b3VibGUiKSl9LApJZzpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYo
+YT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImRvdWJsZSIpKX0sCm9rOmZ1bmN0aW9uKGEp
+e3JldHVybiB0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwKU0g6ZnVuY3Rpb24o
+YSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1u
+dWxsKXJldHVybiBhCnRocm93IEguYihILlB2KGEsImludCIpKX0sClNjOmZ1bmN0aW9uKGEpe2lmKHR5
+cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1
+cm4gYQp0aHJvdyBILmIoSC5xKGEsImludCIpKX0sCktIOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2Yg
+YT09Im51bWJlciJ9LAp1VTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEK
+aWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJudW0iKSl9LApETjpmdW5jdGlvbihh
+KXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBI
+LmIoSC5xKGEsIm51bSIpKX0sCk1NOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09InN0cmluZyJ9
+LApjMDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbCly
+ZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJTdHJpbmciKSl9LAp5OmZ1bmN0aW9uKGEpe2lmKHR5cGVv
+ZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwi
+U3RyaW5nIikpfSwKaW86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9IiIscz0iIixyPTA7cjxh
+Lmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMueEIuaChzLEguZG0oYVtyXSxiKSkKcmV0dXJuIHR9LApiSTpm
+dW5jdGlvbihhMCxhMSxhMil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIs
+YT0iLCAiCmlmKGEyIT1udWxsKXt0PWEyLmxlbmd0aAppZihhMT09bnVsbCl7YTE9SC5WTShbXSx1LnMp
+CnM9bnVsbH1lbHNlIHM9YTEubGVuZ3RoCnI9YTEubGVuZ3RoCmZvcihxPXQ7cT4wOy0tcSlDLk5tLmko
+YTEsIlQiKyhyK3EpKQpmb3IocD0iPCIsbz0iIixxPTA7cTx0OysrcSxvPWEpe3ArPW8Kbj1hMS5sZW5n
+dGgKbT1uLTEtcQppZihtPDApcmV0dXJuIEguT0goYTEsbSkKcD1DLnhCLmgocCxhMVttXSkKbD1hMltx
+XQppZighSC5jYyhsKSlwKz1DLnhCLmgoIiBleHRlbmRzICIsSC5kbShsLGExKSl9cCs9Ij4ifWVsc2V7
+cD0iIgpzPW51bGx9bj1hMC5RCms9YTAuY2gKaj1rLmEKaT1qLmxlbmd0aApoPWsuYgpnPWgubGVuZ3Ro
+CmY9ay5jCmU9Zi5sZW5ndGgKZD1ILmRtKG4sYTEpCmZvcihjPSIiLGI9IiIscT0wO3E8aTsrK3EsYj1h
+KWMrPUMueEIuaChiLEguZG0oaltxXSxhMSkpCmlmKGc+MCl7Yys9YisiWyIKZm9yKGI9IiIscT0wO3E8
+ZzsrK3EsYj1hKWMrPUMueEIuaChiLEguZG0oaFtxXSxhMSkpCmMrPSJdIn1pZihlPjApe2MrPWIrInsi
+CmZvcihiPSIiLHE9MDtxPGU7cSs9MixiPWEpYys9Qy54Qi5oKGIsSC5kbShmW3ErMV0sYTEpKSsiICIr
+ZltxXQpjKz0ifSJ9aWYocyE9bnVsbClhMS5sZW5ndGg9cwpyZXR1cm4gcCsiKCIrYysiKSA9PiAiK0gu
+ZChkKX0sCmRtOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD1hLnoKaWYocD09PTUpcmV0dXJuImVy
+YXNlZCIKaWYocD09PTIpcmV0dXJuImR5bmFtaWMiCmlmKHA9PT0zKXJldHVybiJ2b2lkIgppZihwPT09
+MSlyZXR1cm4iTmV2ZXIiCmlmKHA9PT00KXJldHVybiJhbnkiCmlmKHA9PT02KXJldHVybiBILmQoSC5k
+bShhLlEsYikpKyIqIgppZihwPT09NylyZXR1cm4gSC5kKEguZG0oYS5RLGIpKSsiPyIKaWYocD09PTgp
+cmV0dXJuIkZ1dHVyZU9yPCIrSC5kKEguZG0oYS5RLGIpKSsiPiIKaWYocD09PTkpe3Q9SC5vMyhhLlEp
+CnM9YS5jaApyZXR1cm4gcy5sZW5ndGghPT0wP3QrKCI8IitILmlvKHMsYikrIj4iKTp0fWlmKHA9PT0x
+MSlyZXR1cm4gSC5iSShhLGIsbnVsbCkKaWYocD09PTEyKXJldHVybiBILmJJKGEuUSxiLGEuY2gpCmlm
+KHA9PT0xMyl7cj1hLlEKcT1iLmxlbmd0aApyPXEtMS1yCmlmKHI8MHx8cj49cSlyZXR1cm4gSC5PSChi
+LHIpCnJldHVybiBiW3JdfXJldHVybiI/In0sCm8zOmZ1bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQpp
+ZihzIT1udWxsKXJldHVybiBzCnQ9Im1pbmlmaWVkOiIrYQpyZXR1cm4gdH0sClFvOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQ9YS50UltiXQpmb3IoO3R5cGVvZiB0PT0ic3RyaW5nIjspdD1hLnRSW3RdCnJldHVybiB0
+fSwKYWk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89YS5lVCxuPW9bYl0KaWYobj09bnVsbCly
+ZXR1cm4gSC5FKGEsYikKZWxzZSBpZih0eXBlb2Ygbj09Im51bWJlciIpe3Q9bgpzPUgubShhLDUsIiMi
+KQpyPVtdCmZvcihxPTA7cTx0OysrcSlyLnB1c2gocykKcD1ILkooYSxiLHIpCm9bYl09cApyZXR1cm4g
+cH1lbHNlIHJldHVybiBufSwKeGI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLnRSLGIpfSwKRkY6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLmVULGIpfSwKRTpmdW5jdGlvbihhLGIpe3ZhciB0LHM9
+YS5lQyxyPXMuZ2V0KGIpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1ILnooYSxudWxsLGIpCnMuc2V0KGIs
+dCkKcmV0dXJuIHR9LApjRTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPWIuY3gKaWYocj09bnVsbCly
+PWIuY3g9bmV3IE1hcCgpCnQ9ci5nZXQoYykKaWYodCE9bnVsbClyZXR1cm4gdApzPUgueihhLGIsYykK
+ci5zZXQoYyxzKQpyZXR1cm4gc30sCnY1OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1iLmN5Cmlm
+KHE9PW51bGwpcT1iLmN5PW5ldyBNYXAoKQp0PWMuZGIKcz1xLmdldCh0KQppZihzIT1udWxsKXJldHVy
+biBzCnI9SC5hKGEsYixjLno9PT0xMD9jLmNoOltjXSkKcS5zZXQodCxyKQpyZXR1cm4gcn0sCno6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciB0PUguaShILm8oYSxiLGMpKQpyZXR1cm4gdH0sCldHOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQ9Yi5kYgphLmVDLnNldCh0LGIpCmIuYT1ILk96CmIuYj1ILkF2CmIuYz1ILkpKCnJldHVy
+biBifSwKbTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1hLmVDLmdldChjKQppZihzIT1udWxsKXJldHVy
+biBzCnQ9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnQuej1iCnQuZGI9YwpyZXR1cm4gSC5XRyhhLHQp
+fSwKdjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzPWEuZUMuZ2V0KGQpCmlmKHMhPW51bGwpcmV0dXJu
+IHMKdD1uZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKdC56PWIKdC5RPWMKdC5kYj1kCnJldHVybiBILldH
+KGEsdCl9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHQscz0iIitiKyJeIixyPWEuZUMuZ2V0KHMpCmlmKHIh
+PW51bGwpcmV0dXJuIHIKdD1uZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKdC56PTEzCnQuUT1iCnQuZGI9
+cwpyZXR1cm4gSC5XRyhhLHQpfSwKVXg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS5sZW5ndGgKZm9y
+KHQ9IiIscz0iIixyPTA7cjxxOysrcixzPSIsIil0Kz1zK2Fbcl0uZGIKcmV0dXJuIHR9LApTNDpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscSxwLG89YS5sZW5ndGgKZm9yKHQ9IiIscz0iIixyPTA7cjxvO3IrPTIs
+cz0iLCIpe3E9YVtyXQpwPWFbcisxXS5kYgp0Kz1zK3ErIjoiK3B9cmV0dXJuIHR9LApKOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdCxzLHI9YgppZihjLmxlbmd0aCE9PTApcis9IjwiK0guVXgoYykrIj4iCnQ9YS5l
+Qy5nZXQocikKaWYodCE9bnVsbClyZXR1cm4gdApzPW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQpzLno9
+OQpzLlE9YgpzLmNoPWMKaWYoYy5sZW5ndGg+MClzLmQ9Y1swXQpzLmRiPXIKcmV0dXJuIEguV0coYSxz
+KX0sCmE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAKaWYoYi56PT09MTApe3Q9Yi5RCnM9Yi5j
+aC5jb25jYXQoYyl9ZWxzZXtzPWMKdD1ifXI9dC5kYisiOyIrKCI8IitILlV4KHMpKyI+IikKcT1hLmVD
+LmdldChyKQppZihxIT1udWxsKXJldHVybiBxCnA9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnAuej0x
+MApwLlE9dApwLmNoPXMKcC5kYj1yCnJldHVybiBILldHKGEscCl9LApDOmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdCxzLHIscT1iLmRiLHA9Yy5hLG89cC5sZW5ndGgsbj1jLmIsbT1uLmxlbmd0aCxsPWMuYyxrPWwu
+bGVuZ3RoLGo9IigiK0guVXgocCkKaWYobT4wKWorPShvPjA/IiwiOiIiKSsiWyIrSC5VeChuKSsiXSIK
+aWYoaz4wKWorPShvPjA/IiwiOiIiKSsieyIrSC5TNChsKSsifSIKdD1xKyhqKyIpIikKcz1hLmVDLmdl
+dCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnIuej0xMQpy
+LlE9YgpyLmNoPWMKci5kYj10CnJldHVybiBILldHKGEscil9LApEOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzPWIuZGIrIjwiK0guVXgoYykrIj4iLHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0
+PW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQp0Lno9MTIKdC5RPWIKdC5jaD1jCnQuZGI9cwpyZXR1cm4g
+SC5XRyhhLHQpfSwKbzpmdW5jdGlvbihhLGIsYyl7cmV0dXJue3U6YSxlOmIscjpjLHM6W10scDowfX0s
+Cmk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZz1hLnIsZj1hLnMKZm9y
+KHQ9Zy5sZW5ndGgscz0wO3M8dDspe3I9Zy5jaGFyQ29kZUF0KHMpCmlmKHI+PTQ4JiZyPD01NylzPUgu
+QShzKzEscixnLGYpCmVsc2UgaWYoKCgocnwzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHI9PT05NXx8cj09
+PTM2KXM9SC50KGEscyxnLGYsITEpCmVsc2UgaWYocj09PTQ2KXM9SC50KGEscyxnLGYsITApCmVsc2V7
+KytzCnN3aXRjaChyKXtjYXNlIDQ0OmJyZWFrCmNhc2UgNTg6YnJlYWsKY2FzZSA1OTpmLnB1c2goSC5L
+KGEudSxhLmUsZi5wb3AoKSkpCmJyZWFrCmNhc2UgOTQ6Zi5wdXNoKEguSChhLnUsZi5wb3AoKSkpCmJy
+ZWFrCmNhc2UgMzU6Zi5wdXNoKEgubShhLnUsNSwiIyIpKQpicmVhawpjYXNlIDY0OmYucHVzaChILm0o
+YS51LDIsIkAiKSkKYnJlYWsKY2FzZSAxMjY6Zi5wdXNoKEgubShhLnUsMywifiIpKQpicmVhawpjYXNl
+IDYwOmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDYyOnE9YS51CnA9Zi5zcGxpY2Uo
+YS5wKQpILnIoYS51LGEuZSxwKQphLnA9Zi5wb3AoKQpvPWYucG9wKCkKaWYodHlwZW9mIG89PSJzdHJp
+bmciKWYucHVzaChILkoocSxvLHApKQplbHNle249SC5LKHEsYS5lLG8pCnN3aXRjaChuLnope2Nhc2Ug
+MTE6Zi5wdXNoKEguRChxLG4scCkpCmJyZWFrCmRlZmF1bHQ6Zi5wdXNoKEguYShxLG4scCkpCmJyZWFr
+fX1icmVhawpjYXNlIDM4OkguSShhLGYpCmJyZWFrCmNhc2UgNDI6bT1hLnUKbD1ILksobSxhLmUsZi5w
+b3AoKSkKZi5wdXNoKEgudihtLDYsbCxsLmRiKyIqIikpCmJyZWFrCmNhc2UgNjM6bT1hLnUKbD1ILkso
+bSxhLmUsZi5wb3AoKSkKZi5wdXNoKEgudihtLDcsbCxsLmRiKyI/IikpCmJyZWFrCmNhc2UgNDc6bT1h
+LnUKbD1ILksobSxhLmUsZi5wb3AoKSkKZi5wdXNoKEgudihtLDgsbCxsLmRiKyIvIikpCmJyZWFrCmNh
+c2UgNDA6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgNDE6cT1hLnUKaz1uZXcgSC5H
+KCkKaj1xLnNFQQppPXEuc0VBCm89Zi5wb3AoKQppZih0eXBlb2Ygbz09Im51bWJlciIpc3dpdGNoKG8p
+e2Nhc2UtMTpqPWYucG9wKCkKYnJlYWsKY2FzZS0yOmk9Zi5wb3AoKQpicmVhawpkZWZhdWx0OmYucHVz
+aChvKQpicmVha31lbHNlIGYucHVzaChvKQpwPWYuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUscCkKYS5w
+PWYucG9wKCkKay5hPXAKay5iPWoKay5jPWkKZi5wdXNoKEguQyhxLEguSyhxLGEuZSxmLnBvcCgpKSxr
+KSkKYnJlYWsKY2FzZSA5MTpmLnB1c2goYS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2FzZSA5MzpwPWYu
+c3BsaWNlKGEucCkKSC5yKGEudSxhLmUscCkKYS5wPWYucG9wKCkKZi5wdXNoKHApCmYucHVzaCgtMSkK
+YnJlYWsKY2FzZSAxMjM6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgMTI1OnA9Zi5z
+cGxpY2UoYS5wKQpILkIoYS51LGEuZSxwKQphLnA9Zi5wb3AoKQpmLnB1c2gocCkKZi5wdXNoKC0yKQpi
+cmVhawpkZWZhdWx0OnRocm93IkJhZCBjaGFyYWN0ZXIgIityfX19aD1mLnBvcCgpCnJldHVybiBILkso
+YS51LGEuZSxoKX0sCkE6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5n
+dGg7YTx0OysrYSl7cz1jLmNoYXJDb2RlQXQoYSkKaWYoIShzPj00OCYmczw9NTcpKWJyZWFrCnI9ciox
+MCsocy00OCl9ZC5wdXNoKHIpCnJldHVybiBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMs
+cixxLHAsbyxuPWIrMQpmb3IodD1jLmxlbmd0aDtuPHQ7KytuKXtzPWMuY2hhckNvZGVBdChuKQppZihz
+PT09NDYpe2lmKGUpYnJlYWsKZT0hMH1lbHNle2lmKCEoKCgoc3wzMik+Pj4wKS05NyY2NTUzNSk8MjZ8
+fHM9PT05NXx8cz09PTM2KSlyPXM+PTQ4JiZzPD01NwplbHNlIHI9ITAKaWYoIXIpYnJlYWt9fXE9Yy5z
+dWJzdHJpbmcoYixuKQppZihlKXt0PWEudQpwPWEuZQppZihwLno9PT0xMClwPXAuUQpvPUguUW8odCxw
+LlEpW3FdCmlmKG89PW51bGwpSC52aCgnTm8gIicrcSsnIiBpbiAiJytILm1EKHApKyciJykKZC5wdXNo
+KEguY0UodCxwLG8pKX1lbHNlIGQucHVzaChxKQpyZXR1cm4gbn0sCkk6ZnVuY3Rpb24oYSxiKXt2YXIg
+dD1iLnBvcCgpCmlmKDA9PT10KXtiLnB1c2goSC5tKGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQp
+e2IucHVzaChILm0oYS51LDQsIjEmIikpCnJldHVybn10aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBl
+eHRlbmRlZCBvcGVyYXRpb24gIitILmQodCkpKX0sCks6ZnVuY3Rpb24oYSxiLGMpe2lmKHR5cGVvZiBj
+PT0ic3RyaW5nIilyZXR1cm4gSC5KKGEsYyxhLnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIp
+cmV0dXJuIEguVFYoYSxiLGMpCmVsc2UgcmV0dXJuIGN9LApyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+PWMubGVuZ3RoCmZvcih0PTA7dDxzOysrdCljW3RdPUguSyhhLGIsY1t0XSl9LApCOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdCxzPWMubGVuZ3RoCmZvcih0PTE7dDxzO3QrPTIpY1t0XT1ILksoYSxiLGNbdF0pfSwK
+VFY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj1iLnoKaWYocj09PTEwKXtpZihjPT09MClyZXR1cm4g
+Yi5RCnQ9Yi5jaApzPXQubGVuZ3RoCmlmKGM8PXMpcmV0dXJuIHRbYy0xXQpjLT1zCmI9Yi5RCnI9Yi56
+fWVsc2UgaWYoYz09PTApcmV0dXJuIGIKaWYociE9PTkpdGhyb3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFz
+ZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0eXBlIikpCnQ9Yi5jaAppZihjPD10Lmxlbmd0aClyZXR1cm4g
+dFtjLTFdCnRocm93IEguYihQLmhWKCJCYWQgaW5kZXggIitjKyIgZm9yICIrYi53KDApKSl9LApXZTpm
+dW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrCmlmKGI9PT1kKXJldHVybiEw
+CmlmKEguY2MoZCkpcmV0dXJuITAKdD1iLnoKaWYodD09PTQpcmV0dXJuITAKaWYoSC5jYyhiKSlyZXR1
+cm4hMQppZihiPT09dS5QKXJldHVybiEwCnM9dD09PTEzCmlmKHMpaWYoSC5XZShhLGNbYi5RXSxjLGQs
+ZSkpcmV0dXJuITAKcj1kLnoKaWYodD09PTYpcmV0dXJuIEguV2UoYSxiLlEsYyxkLGUpCmlmKHI9PT02
+KXtxPWQuUQpyZXR1cm4gSC5XZShhLGIsYyxxLGUpfWlmKHQ9PT04KXtpZighSC5XZShhLGIuUSxjLGQs
+ZSkpcmV0dXJuITEKcmV0dXJuIEguV2UoYSxILnhaKGEsYiksYyxkLGUpfWlmKHQ9PT03KXtxPUguV2Uo
+YSxiLlEsYyxkLGUpCnJldHVybiBxfWlmKHI9PT04KXtpZihILldlKGEsYixjLGQuUSxlKSlyZXR1cm4h
+MApyZXR1cm4gSC5XZShhLGIsYyxILnhaKGEsZCksZSl9aWYocj09PTcpe3E9SC5XZShhLGIsYyxkLlEs
+ZSkKcmV0dXJuIHF9aWYocylyZXR1cm4hMQpxPXQhPT0xMQppZigoIXF8fHQ9PT0xMikmJmQ9PT11Llop
+cmV0dXJuITAKaWYocj09PTEyKXtpZihiPT09dS5nKXJldHVybiEwCmlmKHQhPT0xMilyZXR1cm4hMQpw
+PWIuY2gKbz1kLmNoCm49cC5sZW5ndGgKaWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmZvcihxPXUuYXYs
+bT0wO208bjsrK20pe2w9cFttXQprPW9bbV0KcS5iKGwpCnEuYihrKQppZighSC5XZShhLGwsYyxrLGUp
+fHwhSC5XZShhLGssZSxsLGMpKXJldHVybiExfWM9Yz09bnVsbD9wOnAuY29uY2F0KGMpCmU9ZT09bnVs
+bD9vOm8uY29uY2F0KGUpCnJldHVybiBILmJPKGEsYi5RLGMsZC5RLGUpfWlmKHI9PT0xMSl7aWYoYj09
+PXUuZylyZXR1cm4hMAppZihxKXJldHVybiExCnJldHVybiBILmJPKGEsYixjLGQsZSl9aWYodD09PTkp
+e2lmKHIhPT05KXJldHVybiExCnJldHVybiBILnBHKGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5j
+dGlvbihhMCxhMSxhMixhMyxhNCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxj
+LGIsYQppZighSC5XZShhMCxhMS5RLGEyLGEzLlEsYTQpKXJldHVybiExCnQ9YTEuY2gKcz1hMy5jaApy
+PXQuYQpxPXMuYQpwPXIubGVuZ3RoCm89cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5i
+Cmw9cy5iCms9bS5sZW5ndGgKaj1sLmxlbmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxw
+OysraSl7aD1yW2ldCmlmKCFILldlKGEwLHFbaV0sYTQsaCxhMikpcmV0dXJuITF9Zm9yKGk9MDtpPG47
+KytpKXtoPW1baV0KaWYoIUguV2UoYTAscVtwK2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxq
+OysraSl7aD1tW24raV0KaWYoIUguV2UoYTAsbFtpXSxhNCxoLGEyKSlyZXR1cm4hMX1nPXQuYwpmPXMu
+YwplPWcubGVuZ3RoCmQ9Zi5sZW5ndGgKZm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihp
+Pj1lKXJldHVybiExCmE9Z1tpXQppKz0yfXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFd
+CmlmKCFILldlKGEwLGZbYysxXSxhNCxoLGEyKSlyZXR1cm4hMX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9u
+KGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPWIuUSxrPWQuUQppZihsPT09ayl7dD1iLmNo
+CnM9ZC5jaApyPXQubGVuZ3RoCmZvcihxPTA7cTxyOysrcSl7cD10W3FdCm89c1txXQppZighSC5XZShh
+LHAsYyxvLGUpKXJldHVybiExfXJldHVybiEwfW49SC5RbyhhLGwpCmlmKG49PW51bGwpcmV0dXJuITEK
+bT1uW2tdCmlmKG09PW51bGwpcmV0dXJuITEKcj1tLmxlbmd0aApzPWQuY2gKZm9yKHE9MDtxPHI7Kytx
+KWlmKCFILldlKGEsSC5jRShhLGIsbVtxXSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKY2M6
+ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT09dS5LKXJldHVybiEwCnQ9YS56CmlmKHQhPT0yKWlmKHQh
+PT0zKWlmKHQhPT00KWlmKHQhPT01KXM9dD09PTgmJkguY2MoYS5RKQplbHNlIHM9ITAKZWxzZSBzPSEw
+CmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0dXJuIHN9LApJeDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1P
+YmplY3Qua2V5cyhiKSxxPXIubGVuZ3RoCmZvcih0PTA7dDxxOysrdCl7cz1yW3RdCmFbc109YltzXX19
+LApKYzpmdW5jdGlvbiBKYyhhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLnk9Xy54
+PV8uZD1udWxsCl8uej0wCl8uZGI9Xy5jeT1fLmN4PV8uY2g9Xy5RPW51bGx9LApHOmZ1bmN0aW9uIEco
+KXt0aGlzLmM9dGhpcy5iPXRoaXMuYT1udWxsfSwKdTk6ZnVuY3Rpb24gdTkoKXt9LApoejpmdW5jdGlv
+biBoeihhKXt0aGlzLmE9YX0sCmlNOmZ1bmN0aW9uIGlNKGEpe3RoaXMuYT1hfSwKUjk6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHUuZC5jKGEpfHx1LkIuYyhhKXx8dS53LmMoYSl8fHUuSS5jKGEpfHx1LkEuYyhhKXx8
+dS5nNC5jKGEpfHx1LmcyLmMoYSl9LApKZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5tYW5nbGVkR2xvYmFs
+TmFtZXNbYV19fSxKPXsKUXU6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJue2k6YSxwOmIsZTpjLHg6ZH19
+LAprczpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0KaWYo
+cD09bnVsbClpZigkLkJ2PT1udWxsKXtILlhEKCkKcD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdfWlm
+KHAhPW51bGwpe3Q9cC5wCmlmKCExPT09dClyZXR1cm4gcC5pCmlmKCEwPT09dClyZXR1cm4gYQpzPU9i
+amVjdC5nZXRQcm90b3R5cGVPZihhKQppZih0PT09cylyZXR1cm4gcC5pCmlmKHAuZT09PXMpdGhyb3cg
+SC5iKFAuU1koIlJldHVybiBpbnRlcmNlcHRvciBmb3IgIitILmQodChhLHApKSkpfXI9YS5jb25zdHJ1
+Y3RvcgpxPXI9PW51bGw/bnVsbDpyWyQuVU4oKV0KaWYocSE9bnVsbClyZXR1cm4gcQpxPUgudzMoYSkK
+aWYocSE9bnVsbClyZXR1cm4gcQppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwp0PU9i
+amVjdC5nZXRQcm90b3R5cGVPZihhKQppZih0PT1udWxsKXJldHVybiBDLlpRCmlmKHQ9PT1PYmplY3Qu
+cHJvdG90eXBlKXJldHVybiBDLlpRCmlmKHR5cGVvZiByPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5l
+UHJvcGVydHkociwkLlVOKCkse3ZhbHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVl
+LGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApRaTpmdW5jdGlvbihh
+LGIpe2lmKGE8MHx8YT40Mjk0OTY3Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1LCJsZW5n
+dGgiLG51bGwpKQpyZXR1cm4gSi5weShuZXcgQXJyYXkoYSksYil9LApweTpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBKLkVwKEguVk0oYSxiLkMoImpkPDA+IikpKX0sCkVwOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVu
+Z3RoPUFycmF5CnJldHVybiBhfSwKekM6ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKYS5p
+bW11dGFibGUkbGlzdD1BcnJheQpyZXR1cm4gYX0sCkdhOmZ1bmN0aW9uKGEpe2lmKGE8MjU2KXN3aXRj
+aChhKXtjYXNlIDk6Y2FzZSAxMDpjYXNlIDExOmNhc2UgMTI6Y2FzZSAxMzpjYXNlIDMyOmNhc2UgMTMz
+OmNhc2UgMTYwOnJldHVybiEwCmRlZmF1bHQ6cmV0dXJuITF9c3dpdGNoKGEpe2Nhc2UgNTc2MDpjYXNl
+IDgxOTI6Y2FzZSA4MTkzOmNhc2UgODE5NDpjYXNlIDgxOTU6Y2FzZSA4MTk2OmNhc2UgODE5NzpjYXNl
+IDgxOTg6Y2FzZSA4MTk5OmNhc2UgODIwMDpjYXNlIDgyMDE6Y2FzZSA4MjAyOmNhc2UgODIzMjpjYXNl
+IDgyMzM6Y2FzZSA4MjM5OmNhc2UgODI4NzpjYXNlIDEyMjg4OmNhc2UgNjUyNzk6cmV0dXJuITAKZGVm
+YXVsdDpyZXR1cm4hMX19LAptbTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKZm9yKHQ9YS5sZW5ndGg7Yjx0
+Oyl7cz1DLnhCLlcoYSxiKQppZihzIT09MzImJnMhPT0xMyYmIUouR2EocykpYnJlYWs7KytifXJldHVy
+biBifSwKYzE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmZvcig7Yj4wO2I9dCl7dD1iLTEKcz1DLnhCLm0o
+YSx0KQppZihzIT09MzImJnMhPT0xMyYmIUouR2EocykpYnJlYWt9cmV0dXJuIGJ9LApSRTpmdW5jdGlv
+bihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9
+PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQ
+LmspcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51
+bWJlciIpcmV0dXJuIEoucUkucHJvdG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5E
+ci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1
+cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0
+aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1
+cm4gYQpyZXR1cm4gSi5rcyhhKX0sClU2OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIily
+ZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1B
+cnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2Yg
+YT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9m
+IFAuaylyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sCmlhOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0i
+bnVtYmVyIil7aWYoTWF0aC5mbG9vcihhKT09YSlyZXR1cm4gSi51ci5wcm90b3R5cGUKcmV0dXJuIEou
+VkEucHJvdG90eXBlfWlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYo
+YT09bnVsbClyZXR1cm4gSi5ZRS5wcm90b3R5cGUKaWYodHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4g
+Si55RS5wcm90b3R5cGUKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBl
+CmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUu
+cHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEoua3Mo
+YSl9LApyWTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90
+eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoIShhIGluc3RhbmNlb2YgUC5rKSlyZXR1cm4gSi5rZC5w
+cm90b3R5cGUKcmV0dXJuIGF9LAp3MTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKGEu
+Y29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVj
+dCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1p
+ZihhIGluc3RhbmNlb2YgUC5rKXJldHVybiBhCnJldHVybiBKLmtzKGEpfSwKQ006ZnVuY3Rpb24oYSxi
+LGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApGTDpmdW5jdGlvbihhLGIpe3JldHVybiBK
+LnJZKGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3JldHVybiBKLncxKGEpLkUoYSxiKX0sCkht
+OmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2KGEpLmdBKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEou
+dzEoYSkuZ2t6KGEpfSwKSnk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5pYShhKS5lNyhhLGIpfSwKS1Y6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5HKGEsYil9LApMdDpmdW5jdGlvbihhKXtyZXR1cm4g
+Si5SRShhKS53ZyhhKX0sCk0xOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi53MShhKS5FMihhLGIsYyl9
+LApRejpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLlcoYSxiKX0sClJNOmZ1bmN0aW9uKGEsYil7
+aWYoYT09bnVsbClyZXR1cm4gYj09bnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGIhPW51
+bGwmJmE9PT1iCnJldHVybiBKLmlhKGEpLkROKGEsYil9LApUMDpmdW5jdGlvbihhKXtyZXR1cm4gSi5y
+WShhKS5iUyhhKX0sCmE2OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkubShhLGIpfSwKYlQ6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuRDQoYSl9LApiYjpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBh
+PT0ibnVtYmVyIiYmdHlwZW9mIGI9PSJudW1iZXIiKXJldHVybiBhK2IKcmV0dXJuIEouVEooYSkuaChh
+LGIpfSwKY0g6ZnVuY3Rpb24oYSl7cmV0dXJuIEouclkoYSkuaGMoYSl9LApkUjpmdW5jdGlvbihhKXty
+ZXR1cm4gSi5SRShhKS5nRChhKX0sCmRaOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLlJFKGEpLk9u
+KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkudG4oYSl9LApoZjpmdW5jdGlv
+bihhKXtyZXR1cm4gSi5pYShhKS5naU8oYSl9LAppZzpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5n
+UWcoYSl9LApqOmZ1bmN0aW9uKGEpe3JldHVybiBKLmlhKGEpLncoYSl9LApsNTpmdW5jdGlvbihhLGIp
+e3JldHVybiBKLlJFKGEpLnNoZihhLGIpfSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEp
+Lk5qKGEsYixjKX0sCnEwOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5yWShhKS5RaShhLGIsYyl9LApx
+RjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nVmwoYSl9LAp0SDpmdW5jdGlvbihhLGIsYyl7cmV0
+dXJuIEouUkUoYSkucGsoYSxiLGMpfSwKdzI6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJudW1i
+ZXIiKWlmKGEuY29uc3RydWN0b3I9PUFycmF5fHx0eXBlb2YgYT09InN0cmluZyJ8fEgud1YoYSxhW3Yu
+ZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdKSlpZihiPj4+MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFbYl0K
+cmV0dXJuIEouVTYoYSkucShhLGIpfSwKeVE6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouclkoYSku
+aTcoYSxiLGMsZCl9LAp6bDpmdW5jdGlvbihhLGIpe3JldHVybiBKLlU2KGEpLnRnKGEsYil9LAp2Qjpm
+dW5jdGlvbiB2Qigpe30sCnlFOmZ1bmN0aW9uIHlFKCl7fSwKWUU6ZnVuY3Rpb24gWUUoKXt9LApNRjpm
+dW5jdGlvbiBNRigpe30sCmlDOmZ1bmN0aW9uIGlDKCl7fSwKa2Q6ZnVuY3Rpb24ga2QoKXt9LApjNTpm
+dW5jdGlvbiBjNSgpe30sCmpkOmZ1bmN0aW9uIGpkKGEpe3RoaXMuJHRpPWF9LApQbzpmdW5jdGlvbiBQ
+byhhKXt0aGlzLiR0aT1hfSwKbTE6ZnVuY3Rpb24gbTEoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
+PWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCnFJOmZ1bmN0aW9uIHFJKCl7fSwKdXI6ZnVuY3Rpb24g
+dXIoKXt9LApWQTpmdW5jdGlvbiBWQSgpe30sCkRyOmZ1bmN0aW9uIERyKCl7fX0sUD17Ck9qOmZ1bmN0
+aW9uKCl7dmFyIHQscyxyPXt9CmlmKHNlbGYuc2NoZWR1bGVJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAu
+RVgoKQppZihzZWxmLk11dGF0aW9uT2JzZXJ2ZXIhPW51bGwmJnNlbGYuZG9jdW1lbnQhPW51bGwpe3Q9
+c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKQpzPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxl
+bWVudCgic3BhbiIpCnIuYT1udWxsCm5ldyBzZWxmLk11dGF0aW9uT2JzZXJ2ZXIoSC50UihuZXcgUC50
+aChyKSwxKSkub2JzZXJ2ZSh0LHtjaGlsZExpc3Q6dHJ1ZX0pCnJldHVybiBuZXcgUC5oYShyLHQscyl9
+ZWxzZSBpZihzZWxmLnNldEltbWVkaWF0ZSE9bnVsbClyZXR1cm4gUC55dCgpCnJldHVybiBQLnFXKCl9
+LApaVjpmdW5jdGlvbihhKXtzZWxmLnNjaGVkdWxlSW1tZWRpYXRlKEgudFIobmV3IFAuVnModS5NLmIo
+YSkpLDApKX0sCm9BOmZ1bmN0aW9uKGEpe3NlbGYuc2V0SW1tZWRpYXRlKEgudFIobmV3IFAuRnQodS5N
+LmIoYSkpLDApKX0sCkJ6OmZ1bmN0aW9uKGEpe3UuTS5iKGEpClAuUU4oMCxhKX0sClFOOmZ1bmN0aW9u
+KGEsYil7dmFyIHQ9bmV3IFAuVzMoKQp0LkNZKGEsYikKcmV0dXJuIHR9LAprMzpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMscgpiLmE9MQp0cnl7YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNo
+KHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5yYihuZXcgUC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxzPT09MjspYT10LmIoYS5jKQppZihzPj00KXty
+PWIuYWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHIpfWVsc2V7cj11LnguYihiLmMpCmIuYT0yCmIu
+Yz1hCmEualEocil9fSwKSFo6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
+aCxnLGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9
+Yy5hPT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYihjLmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1y
+ZXR1cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5hPW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1j
+LmMKcS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNl
+IGs9ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEK
+aWYoaSl7dC5iKG0pClAuTDIoZSxlLGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQu
+WDM9agplbHNlIGg9ZQpjPWIuYwppZigoYyYxNSk9PT04KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxz
+ZSBpZihsKXtpZigoYyYxKSE9PTApbmV3IFAucnEocSxiLG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTAp
+bmV3IFAuUlcoZCxxLGIpLiQwKCkKaWYoaCE9bnVsbCkkLlgzPWgKYz1xLmIKaWYoci5jKGMpKXtpZihj
+LmE+PTQpe2c9cy5iKGsuYykKay5jPW51bGwKYj1rLk44KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpj
+b250aW51ZX1lbHNlIFAuQTkoYyxrKQpyZXR1cm59fWY9Yi5iCmc9cy5iKGYuYykKZi5jPW51bGwKYj1m
+Lk44KGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5kLmIobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmIo
+bCkKZi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dS5ZCmlmKHQu
+YyhhKSlyZXR1cm4gdC5iKGEpCnQ9dS55CmlmKHQuYyhhKSlyZXR1cm4gdC5iKGEpCnRocm93IEguYihQ
+LkwzKGEsIm9uRXJyb3IiLCJFcnJvciBoYW5kbGVyIG11c3QgYWNjZXB0IG9uZSBPYmplY3Qgb3Igb25l
+IE9iamVjdCBhbmQgYSBTdGFja1RyYWNlIGFzIGFyZ3VtZW50cywgYW5kIHJldHVybiBhIGEgdmFsaWQg
+cmVzdWx0IikpfSwKcHU6ZnVuY3Rpb24oKXt2YXIgdCxzCmZvcig7dD0kLlM2LHQhPW51bGw7KXskLm1n
+PW51bGwKcz10LmIKJC5TNj1zCmlmKHM9PW51bGwpJC5rOD1udWxsCnQuYS4kMCgpfX0sCmVOOmZ1bmN0
+aW9uKCl7JC5VRD0hMAp0cnl7UC5wdSgpfWZpbmFsbHl7JC5tZz1udWxsCiQuVUQ9ITEKaWYoJC5TNiE9
+bnVsbCkkLnV0KCkuJDEoUC5VSSgpKX19LAplVzpmdW5jdGlvbihhKXt2YXIgdD1uZXcgUC5PTShhKQpp
+ZigkLlM2PT1udWxsKXskLlM2PSQuazg9dAppZighJC5VRCkkLnV0KCkuJDEoUC5VSSgpKX1lbHNlICQu
+azg9JC5rOC5iPXR9LApyUjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9JC5TNgppZihyPT1udWxsKXtQLmVX
+KGEpCiQubWc9JC5rOApyZXR1cm59dD1uZXcgUC5PTShhKQpzPSQubWcKaWYocz09bnVsbCl7dC5iPXIK
+JC5TNj0kLm1nPXR9ZWxzZXt0LmI9cy5iCiQubWc9cy5iPXQKaWYodC5iPT1udWxsKSQuazg9dH19LApy
+YjpmdW5jdGlvbihhKXt2YXIgdD1udWxsLHM9JC5YMwppZihDLk5VPT09cyl7UC5Uayh0LHQsQy5OVSxh
+KQpyZXR1cm59UC5Uayh0LHQscyx1Lk0uYihzLkdZKGEpKSl9LApMMjpmdW5jdGlvbihhLGIsYyxkLGUp
+e3ZhciB0PXt9CnQuYT1kClAuclIobmV3IFAucEsodCxlKSl9LApUODpmdW5jdGlvbihhLGIsYyxkLGUp
+e3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMCgpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMCgp
+CnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sCnl2OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0
+LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMShlKQokLlgzPWMKdD1zCnRyeXtzPWQuJDEoZSkKcmV0
+dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKUXg6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxoLGkpe3ZhciB0
+LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMihlLGYpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMihlLGYp
+CnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sClRrOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0CnUuTS5i
+KGQpCnQ9Qy5OVSE9PWMKaWYodClkPSEoIXR8fCExKT9jLkdZKGQpOmMuUlQoZCx1LkgpClAuZVcoZCl9
+LAp0aDpmdW5jdGlvbiB0aChhKXt0aGlzLmE9YX0sCmhhOmZ1bmN0aW9uIGhhKGEsYixjKXt0aGlzLmE9
+YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClZzOmZ1bmN0aW9uIFZzKGEpe3RoaXMuYT1hfSwKRnQ6ZnVuY3Rp
+b24gRnQoYSl7dGhpcy5hPWF9LApXMzpmdW5jdGlvbiBXMygpe30sCnlIOmZ1bmN0aW9uIHlIKGEsYil7
+dGhpcy5hPWEKdGhpcy5iPWJ9LApQZjpmdW5jdGlvbiBQZigpe30sClpmOmZ1bmN0aW9uIFpmKGEsYil7
+dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCkZlOmZ1bmN0aW9uIEZlKGEsYixjLGQsZSl7dmFyIF89dGhpcwpf
+LmE9bnVsbApfLmI9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwKdnM6ZnVuY3Rpb24gdnMoYSxi
+KXt2YXIgXz10aGlzCl8uYT0wCl8uYj1hCl8uYz1udWxsCl8uJHRpPWJ9LApkYTpmdW5jdGlvbiBkYShh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKb1E6ZnVuY3Rpb24gb1EoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCnBWOmZ1bmN0aW9uIHBWKGEpe3RoaXMuYT1hfSwKVTc6ZnVuY3Rpb24gVTcoYSl7dGhpcy5hPWF9
+LAp2cjpmdW5jdGlvbiB2cihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApySDpmdW5j
+dGlvbiBySChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKS0Y6ZnVuY3Rpb24gS0YoYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sClpMOmZ1bmN0aW9uIFpMKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
+Y30sClJUOmZ1bmN0aW9uIFJUKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5k
+PWR9LApqWjpmdW5jdGlvbiBqWihhKXt0aGlzLmE9YX0sCnJxOmZ1bmN0aW9uIHJxKGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClJXOmZ1bmN0aW9uIFJXKGEsYixjKXt0aGlzLmE9YQp0aGlz
+LmI9Ygp0aGlzLmM9Y30sCk9NOmZ1bmN0aW9uIE9NKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKcWg6
+ZnVuY3Rpb24gcWgoKXt9LApCNTpmdW5jdGlvbiBCNShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKUEk6
+ZnVuY3Rpb24gUEkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1POmZ1bmN0aW9uIE1PKCl7fSwKa1Q6
+ZnVuY3Rpb24ga1QoKXt9LApDdzpmdW5jdGlvbiBDdyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKbTA6
+ZnVuY3Rpb24gbTAoKXt9LApwSzpmdW5jdGlvbiBwSyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSmk6
+ZnVuY3Rpb24gSmkoKXt9LApoajpmdW5jdGlvbiBoaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
+cy5jPWN9LApWcDpmdW5jdGlvbiBWcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24g
+T1IoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3Jl
+dHVybiBiLkMoIkA8MD4iKS5LcShjKS5DKCJGbzwxLDI+IikuYihILkI3KGEsbmV3IEguTjUoYi5DKCJA
+PDA+IikuS3EoYykuQygiTjU8MSwyPiIpKSkpfSwKRmw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEgu
+TjUoYS5DKCJAPDA+IikuS3EoYikuQygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgUC5iNihhLkMoImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24oKXt2YXIgdD1PYmplY3QuY3JlYXRlKG51
+bGwpCnRbIjxub24taWRlbnRpZmllci1rZXk+Il09dApkZWxldGUgdFsiPG5vbi1pZGVudGlmaWVyLWtl
+eT4iXQpyZXR1cm4gdH0sCnJqOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1uZXcgUC5sbShhLGIsYy5DKCJs
+bTwwPiIpKQp0LmM9YS5lCnJldHVybiB0fSwKRVA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5o
+QihhKSl7aWYoYj09PSIoIiYmYz09PSIpIilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9dD1I
+LlZNKFtdLHUucykKQy5ObS5pKCQueGcsYSkKdHJ5e1AuVnIoYSx0KX1maW5hbGx5e2lmKDA+PSQueGcu
+bGVuZ3RoKXJldHVybiBILk9IKCQueGcsLTEpCiQueGcucG9wKCl9cz1QLnZnKGIsdS5SLmIodCksIiwg
+IikrYwpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c30sCldFOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzCmlmKFAuaEIoYSkpcmV0dXJuIGIrIi4uLiIrYwp0PW5ldyBQLlJuKGIpCkMuTm0uaSgkLnhnLGEp
+CnRyeXtzPXQKcy5hPVAudmcocy5hLGEsIiwgIil9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1
+cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXQuYSs9YwpzPXQuYQpyZXR1cm4gcy5jaGFyQ29kZUF0
+KDApPT0wP3M6c30sCmhCOmZ1bmN0aW9uKGEpe3ZhciB0LHMKZm9yKHQ9JC54Zy5sZW5ndGgscz0wO3M8
+dDsrK3MpaWYoYT09PSQueGdbc10pcmV0dXJuITAKcmV0dXJuITF9LApWcjpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscixxLHAsbyxuLG09YS5na3ooYSksbD0wLGs9MAp3aGlsZSghMCl7aWYoIShsPDgwfHxrPDMp
+KWJyZWFrCmlmKCFtLkYoKSlyZXR1cm4KdD1ILmQobS5nbCgpKQpDLk5tLmkoYix0KQpsKz10Lmxlbmd0
+aCsyOysra31pZighbS5GKCkpe2lmKGs8PTUpcmV0dXJuCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9I
+KGIsLTEpCnM9Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIucG9wKCl9
+ZWxzZXtxPW0uZ2woKTsrK2sKaWYoIW0uRigpKXtpZihrPD00KXtDLk5tLmkoYixILmQocSkpCnJldHVy
+bn1zPUguZChxKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIucG9wKCkKbCs9cy5s
+ZW5ndGgrMn1lbHNle3A9bS5nbCgpOysrawpmb3IoO20uRigpO3E9cCxwPW8pe289bS5nbCgpOysrawpp
+ZihrPjEwMCl7d2hpbGUoITApe2lmKCEobD43NSYmaz4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1
+cm4gSC5PSChiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyOy0ta31DLk5tLmkoYiwiLi4uIikKcmV0dXJu
+fX1yPUguZChxKQpzPUguZChwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihrPmIubGVuZ3RoKzIp
+e2wrPTUKbj0iLi4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZiLmxlbmd0aD4zKSli
+cmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyCmlm
+KG49PW51bGwpe2wrPTUKbj0iLi4uIn19aWYobiE9bnVsbClDLk5tLmkoYixuKQpDLk5tLmkoYixyKQpD
+Lk5tLmkoYixzKX0sCnRNOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPVAuTHMoYikKZm9yKHQ9YS5sZW5n
+dGgscz0wO3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpci5pKDAsYi5iKGFb
+c10pKQpyZXR1cm4gcn0sCm5POmZ1bmN0aW9uKGEpe3ZhciB0LHM9e30KaWYoUC5oQihhKSlyZXR1cm4i
+ey4uLn0iCnQ9bmV3IFAuUm4oIiIpCnRyeXtDLk5tLmkoJC54ZyxhKQp0LmErPSJ7IgpzLmE9ITAKYS5L
+KDAsbmV3IFAucmEocyx0KSkKdC5hKz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4g
+SC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXM9dC5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpz
+fSwKYjY6ZnVuY3Rpb24gYjYoYSl7dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5lPV8uZD1fLmM9Xy5iPW51
+bGwKXy5yPTAKXy4kdGk9YX0sCmJuOmZ1bmN0aW9uIGJuKGEpe3RoaXMuYT1hCnRoaXMuYz10aGlzLmI9
+bnVsbH0sCmxtOmZ1bmN0aW9uIGxtKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9
+bnVsbApfLiR0aT1jfSwKbVc6ZnVuY3Rpb24gbVcoKXt9LApMVTpmdW5jdGlvbiBMVSgpe30sCmxEOmZ1
+bmN0aW9uIGxEKCl7fSwKaWw6ZnVuY3Rpb24gaWwoKXt9LApyYTpmdW5jdGlvbiByYShhLGIpe3RoaXMu
+YT1hCnRoaXMuYj1ifSwKWWs6ZnVuY3Rpb24gWWsoKXt9LApLUDpmdW5jdGlvbiBLUCgpe30sClBuOmZ1
+bmN0aW9uIFBuKCl7fSwKR2o6ZnVuY3Rpb24gR2ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKbGY6
+ZnVuY3Rpb24gbGYoKXt9LApWajpmdW5jdGlvbiBWaigpe30sClh2OmZ1bmN0aW9uIFh2KCl7fSwKblk6
+ZnVuY3Rpb24gblkoKXt9LApXWTpmdW5jdGlvbiBXWSgpe30sClJVOmZ1bmN0aW9uIFJVKCl7fSwKQlM6
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQppZih0eXBlb2YgYSE9InN0cmluZyIpdGhyb3cgSC5iKEgu
+dEwoYSkpCnQ9bnVsbAp0cnl7dD1KU09OLnBhcnNlKGEpfWNhdGNoKHIpe3M9SC5SdShyKQpxPVAucnIo
+U3RyaW5nKHMpLG51bGwsbnVsbCkKdGhyb3cgSC5iKHEpfXE9UC5RZSh0KQpyZXR1cm4gcX0sClFlOmZ1
+bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYodHlwZW9mIGEhPSJvYmplY3Qi
+KXJldHVybiBhCmlmKE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSE9PUFycmF5LnByb3RvdHlwZSlyZXR1
+cm4gbmV3IFAudXcoYSxPYmplY3QuY3JlYXRlKG51bGwpKQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KWFb
+dF09UC5RZShhW3RdKQpyZXR1cm4gYX0sCmt5OmZ1bmN0aW9uKGEsYixjLGQpe2lmKGIgaW5zdGFuY2Vv
+ZiBVaW50OEFycmF5KXJldHVybiBQLlJQKCExLGIsYyxkKQpyZXR1cm4gbnVsbH0sClJQOmZ1bmN0aW9u
+KGEsYixjLGQpe3ZhciB0LHMscj0kLnJmKCkKaWYocj09bnVsbClyZXR1cm4gbnVsbAp0PTA9PT1jCmlm
+KHQmJiEwKXJldHVybiBQLk9RKHIsYikKcz1iLmxlbmd0aApkPVAuakIoYyxkLHMpCmlmKHQmJmQ9PT1z
+KXJldHVybiBQLk9RKHIsYikKcmV0dXJuIFAuT1EocixiLnN1YmFycmF5KGMsZCkpfSwKT1E6ZnVuY3Rp
+b24oYSxiKXtpZihQLkJlKGIpKXJldHVybiBudWxsCnJldHVybiBQLkpoKGEsYil9LApKaDpmdW5jdGlv
+bihhLGIpe3ZhciB0LHMKdHJ5e3Q9YS5kZWNvZGUoYikKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKX1y
+ZXR1cm4gbnVsbH0sCkJlOmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS5sZW5ndGgtMgpmb3IodD0wO3Q8czsr
+K3QpaWYoYVt0XT09PTIzNylpZigoYVt0KzFdJjIyNCk9PT0xNjApcmV0dXJuITAKcmV0dXJuITF9LApX
+STpmdW5jdGlvbigpe3ZhciB0LHMKdHJ5e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFsOnRy
+dWV9KQpyZXR1cm4gdH1jYXRjaChzKXtILlJ1KHMpfXJldHVybiBudWxsfSwKY1A6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0LHMscgpmb3IodD1KLlU2KGEpLHM9YjtzPGM7KytzKXtyPXQucShhLHMpCmlmKHR5cGVv
+ZiByIT09Im51bWJlciIpcmV0dXJuIHIuek0oKQppZigociYxMjcpIT09cilyZXR1cm4gcy1ifXJldHVy
+biBjLWJ9LAp4TTpmdW5jdGlvbihhLGIsYyxkLGUsZil7aWYoQy5qbi56WShmLDQpIT09MCl0aHJvdyBI
+LmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgcGFkZGVkIGxlbmd0aCBtdXN0IGJlIG11bHRp
+cGxlIG9mIGZvdXIsIGlzICIrZixhLGMpKQppZihkK2UhPT1mKXRocm93IEguYihQLnJyKCJJbnZhbGlk
+IGJhc2U2NCBwYWRkaW5nLCAnPScgbm90IGF0IHRoZSBlbmQiLGEsYikpCmlmKGU+Mil0aHJvdyBILmIo
+UC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywgbW9yZSB0aGFuIHR3byAnPScgY2hhcmFjdGVycyIs
+YSxiKSl9LApNZDpmdW5jdGlvbihhKXthLnpNKDAsNjQ1MTIpCnJldHVybiExfSwKWlo6ZnVuY3Rpb24o
+YSxiKXtyZXR1cm4oQy5qbi5oKDY1NTM2LGEuek0oMCwxMDIzKS55RSgwLDEwKSl8YiYxMDIzKT4+PjB9
+LAp1dzpmdW5jdGlvbiB1dyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1udWxsfSwKaTg6ZnVu
+Y3Rpb24gaTgoYSl7dGhpcy5hPWF9LApDVjpmdW5jdGlvbiBDVigpe30sClU4OmZ1bmN0aW9uIFU4KCl7
+fSwKVWs6ZnVuY3Rpb24gVWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0aW9uIFppKCl7
+fSwKYnk6ZnVuY3Rpb24gYnkoKXt9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0sCnU1OmZ1bmN0
+aW9uIHU1KCl7fSwKRTM6ZnVuY3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0aGlzLmI9MAp0
+aGlzLmM9YX0sCkdZOmZ1bmN0aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24gYnooYSxiKXt2
+YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0hMApfLmY9Xy5lPV8uZD0wfSwKUUE6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0PUguSHAoYSxjKQppZih0IT1udWxsKXJldHVybiB0CmlmKGIhPW51bGwpcmV0dXJuIGIu
+JDEoYSkKdGhyb3cgSC5iKFAucnIoYSxudWxsLG51bGwpKX0sCkY6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0
+YW5jZW9mIEguVHApcmV0dXJuIGEudygwKQpyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTShhKSkr
+IicifSwKTzg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Si5RaShhLGMpCmlmKGEhPT0wJiYhMClmb3Io
+dD0wO3Q8cy5sZW5ndGg7Kyt0KUMuTm0uWShzLHQsYikKcmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscz1ILlZNKFtdLGMuQygiamQ8MD4iKSkKZm9yKHQ9Si5JVChhKTt0LkYoKTspQy5ObS5p
+KHMsYy5iKHQuZ2woKSkpCmlmKGIpcmV0dXJuIHMKcmV0dXJuIGMuQygiek08MD4iKS5iKEouRXAocykp
+fSwKT1c6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYi5DKCJ6TTwwPiIpLmIoSi56QyhQLkNIKGEsITEsYikp
+KX0sCkhNOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZihBcnJheS5pc0FycmF5KGEpKXt1LnQuYihhKQp0
+PWEubGVuZ3RoCmM9UC5qQihiLGMsdCkKcmV0dXJuIEguZVQoYj4wfHxjPHQ/Qy5ObS5hTShhLGIsYyk6
+YSl9aWYodS5ibS5jKGEpKXJldHVybiBILmZ3KGEsYixQLmpCKGIsYyxhLmxlbmd0aCkpCnJldHVybiBQ
+LmJ3KGEsYixjKX0sCk9vOmZ1bmN0aW9uKGEpe3JldHVybiBILkx3KGEpfSwKYnc6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0LHMscixxLHA9bnVsbAppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLEouSG0oYSkscCxw
+KSkKdD1jPT1udWxsCmlmKCF0JiZjPGIpdGhyb3cgSC5iKFAuVEUoYyxiLEouSG0oYSkscCxwKSkKcz1K
+LklUKGEpCmZvcihyPTA7cjxiOysrcilpZighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYiwwLHIscCxwKSkK
+cT1bXQppZih0KWZvcig7cy5GKCk7KXEucHVzaChzLmdsKCkpCmVsc2UgZm9yKHI9YjtyPGM7KytyKXtp
+Zighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHIscCxwKSkKcS5wdXNoKHMuZ2woKSl9cmV0dXJuIEgu
+ZVQocSl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEs
+ITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1KLklUKGIpCmlmKCF0LkYoKSlyZXR1cm4gYQpp
+ZihjLmxlbmd0aD09PTApe2RvIGErPUguZCh0LmdsKCkpCndoaWxlKHQuRigpKX1lbHNle2ErPUguZCh0
+LmdsKCkpCmZvcig7dC5GKCk7KWE9YStjK0guZCh0LmdsKCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rpb24o
+YSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgdD1ILk0w
+KCkKaWYodCE9bnVsbClyZXR1cm4gUC5oSyh0KQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBpcyBu
+b3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG49IjAx
+MjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXt0PSQuejQoKS5iCnQ9dC50ZXN0KGIpfWVsc2UgdD0h
+MQppZih0KXJldHVybiBiCkguTGgoYykuQygiVWsuUyIpLmIoYikKcz1jLmdaRSgpLldKKGIpCmZvcih0
+PXMubGVuZ3RoLHI9MCxxPSIiO3I8dDsrK3Ipe3A9c1tyXQppZihwPDEyOCl7bz1wPj4+NAppZihvPj04
+KXJldHVybiBILk9IKGEsbykKbz0oYVtvXSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYobylxKz1I
+Lkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsiJSIrbltwPj4+NCYxNV0rbltwJjE1XX1yZXR1
+cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCkdxOmZ1bmN0aW9uKGEpe3ZhciB0PU1hdGguYWJzKGEp
+LHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIiK2EKaWYodD49MTAwKXJldHVybiBzKyIwIit0
+CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4gcysiMDAwIit0fSwKVng6ZnVuY3Rpb24oYSl7
+aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJuIjAwIithfSwKaDA6
+ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCnA6ZnVuY3Rpb24oYSl7
+aWYodHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSl8fG51bGw9PWEpcmV0dXJuIEouaihhKQppZih0eXBl
+b2YgYT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLkYoYSl9LApoVjpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAu
+dSghMSxudWxsLG51bGwsYSl9LApMMzpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLnUoITAsYSxi
+LGMpfSwKeDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5iSihudWxsLG51bGwsITAsYSxiLCJWYWx1
+ZSBub3QgaW4gcmFuZ2UiKX0sClRFOmZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0dXJuIG5ldyBQLmJKKGIs
+YywhMCxhLGQsIkludmFsaWQgdmFsdWUiKX0sCndBOmZ1bmN0aW9uKGEsYixjLGQpe2lmKGE8Ynx8YT5j
+KXRocm93IEguYihQLlRFKGEsYixjLGQsbnVsbCkpfSwKakI6ZnVuY3Rpb24oYSxiLGMpe2lmKDA+YXx8
+YT5jKXRocm93IEguYihQLlRFKGEsMCxjLCJzdGFydCIsbnVsbCkpCmlmKGIhPW51bGwpe2lmKGE+Ynx8
+Yj5jKXRocm93IEguYihQLlRFKGIsYSxjLCJlbmQiLG51bGwpKQpyZXR1cm4gYn1yZXR1cm4gY30sCmsx
+OmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGEhPT0ibnVtYmVyIilyZXR1cm4gYS5KKCkKaWYoYTwwKXRo
+cm93IEguYihQLlRFKGEsMCxudWxsLGIsbnVsbCkpfSwKQ2Y6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIg
+dD1ILlNjKGU9PW51bGw/Si5IbShiKTplKQpyZXR1cm4gbmV3IFAuZVkodCwhMCxhLGMsIkluZGV4IG91
+dCBvZiByYW5nZSIpfSwKTDQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLnViKGEpfSwKU1k6ZnVuY3Rp
+b24oYSl7cmV0dXJuIG5ldyBQLmRzKGEpfSwKUFY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmxqKGEp
+fSwKYTQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLlVWKGEpfSwKcnI6ZnVuY3Rpb24oYSxiLGMpe3Jl
+dHVybiBuZXcgUC5hRShhLGIsYyl9LApkSDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzPUguVk0oW10s
+ZC5DKCJqZDwwPiIpKQpDLk5tLnNBKHMsYSkKZm9yKHQ9MDt0PGE7Kyt0KUMuTm0uWShzLHQsYi4kMSh0
+KSkKcmV0dXJuIHN9LApoSzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxn
+LGYsZT1udWxsLGQ9YS5sZW5ndGgKaWYoZD49NSl7dD0oKEouUXooYSw0KV41OCkqM3xDLnhCLlcoYSww
+KV4xMDB8Qy54Qi5XKGEsMSleOTd8Qy54Qi5XKGEsMileMTE2fEMueEIuVyhhLDMpXjk3KT4+PjAKaWYo
+dD09PTApcmV0dXJuIFAuS0QoZDxkP0MueEIuTmooYSwwLGQpOmEsNSxlKS5nbFIoKQplbHNlIGlmKHQ9
+PT0zMilyZXR1cm4gUC5LRChDLnhCLk5qKGEsNSxkKSwwLGUpLmdsUigpfXM9bmV3IEFycmF5KDgpCnMu
+Zml4ZWQkbGVuZ3RoPUFycmF5CnI9SC5WTShzLHUudCkKQy5ObS5ZKHIsMCwwKQpDLk5tLlkociwxLC0x
+KQpDLk5tLlkociwyLC0xKQpDLk5tLlkociw3LC0xKQpDLk5tLlkociwzLDApCkMuTm0uWShyLDQsMCkK
+Qy5ObS5ZKHIsNSxkKQpDLk5tLlkociw2LGQpCmlmKFAuVUIoYSwwLGQsMCxyKT49MTQpQy5ObS5ZKHIs
+NyxkKQpxPXJbMV0KaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS50QigpCmlmKHE+PTApaWYo
+UC5VQihhLDAscSwyMCxyKT09PTIwKXJbN109cQpzPXJbMl0KaWYodHlwZW9mIHMhPT0ibnVtYmVyIily
+ZXR1cm4gcy5oKCkKcD1zKzEKbz1yWzNdCm49cls0XQptPXJbNV0KbD1yWzZdCmlmKHR5cGVvZiBsIT09
+Im51bWJlciIpcmV0dXJuIGwuSigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkK
+aWYobDxtKW09bAppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVybiBuLkooKQppZihuPHApbj1tCmVs
+c2UgaWYobjw9cSluPXErMQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLkooKQppZihvPHAp
+bz1uCnM9cls3XQppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkooKQprPXM8MAppZihrKWlm
+KHA+cSszKXtqPWUKaz0hMX1lbHNle3M9bz4wCmlmKHMmJm8rMT09PW4pe2o9ZQprPSExfWVsc2V7aWYo
+IShtPGQmJm09PT1uKzImJkoucTAoYSwiLi4iLG4pKSlpPW0+bisyJiZKLnEwKGEsIi8uLiIsbS0zKQpl
+bHNlIGk9ITAKaWYoaSl7aj1lCms9ITF9ZWxzZXtpZihxPT09NClpZihKLnEwKGEsImZpbGUiLDApKXtp
+ZihwPD0wKXtpZighQy54Qi5RaShhLCIvIixuKSl7aD0iZmlsZTovLy8iCnQ9M31lbHNle2g9ImZpbGU6
+Ly8iCnQ9Mn1hPWgrQy54Qi5OaihhLG4sZCkKcS09MApzPXQtMAptKz1zCmwrPXMKZD1hLmxlbmd0aApw
+PTcKbz03Cm49N31lbHNlIGlmKG49PT1tKXtnPW0rMTsrK2wKYT1DLnhCLmk3KGEsbixtLCIvIik7Kytk
+Cm09Z31qPSJmaWxlIn1lbHNlIGlmKEMueEIuUWkoYSwiaHR0cCIsMCkpe2lmKHMmJm8rMz09PW4mJkMu
+eEIuUWkoYSwiODAiLG8rMSkpe2Y9bi0zCm0tPTMKbC09MwphPUMueEIuaTcoYSxvLG4sIiIpCmQtPTMK
+bj1mfWo9Imh0dHAifWVsc2Ugaj1lCmVsc2UgaWYocT09PTUmJkoucTAoYSwiaHR0cHMiLDApKXtpZihz
+JiZvKzQ9PT1uJiZKLnEwKGEsIjQ0MyIsbysxKSl7Zj1uLTQKbS09NApsLT00CmE9Si55UShhLG8sbiwi
+IikKZC09MwpuPWZ9aj0iaHR0cHMifWVsc2Ugaj1lCms9ITB9fX1lbHNlIGo9ZQppZihrKXtzPWEubGVu
+Z3RoCmlmKGQ8cyl7YT1KLmxkKGEsMCxkKQpxLT0wCnAtPTAKby09MApuLT0wCm0tPTAKbC09MH1yZXR1
+cm4gbmV3IFAuVWYoYSxxLHAsbyxuLG0sbCxqKX1yZXR1cm4gUC5qdihhLDAsZCxxLHAsbyxuLG0sbCxq
+KX0sCk10OmZ1bmN0aW9uKGEpe0gueShhKQpyZXR1cm4gUC5rdShhLDAsYS5sZW5ndGgsQy54TSwhMSl9
+LApXWDpmdW5jdGlvbihhKXt2YXIgdD11Lk4KcmV0dXJuIEMuTm0uTjAoSC5WTShhLnNwbGl0KCImIiks
+dS5zKSxQLkZsKHQsdCksbmV3IFAubjEoQy54TSksdS5mKX0sCkhoOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHIscSxwLG8sbixtPW51bGwsbD0iSVB2NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4YWN0bHkg
+NCBwYXJ0cyIsaz0iZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1uZXcgUC5j
+UyhhKSxpPW5ldyBVaW50OEFycmF5KDQpCmZvcih0PWkubGVuZ3RoLHM9YixyPXMscT0wO3M8YzsrK3Mp
+e3A9Qy54Qi5tKGEscykKaWYocCE9PTQ2KXtpZigocF40OCk+OSlqLiQyKCJpbnZhbGlkIGNoYXJhY3Rl
+ciIscyl9ZWxzZXtpZihxPT09MylqLiQyKGwscykKbz1QLlFBKEMueEIuTmooYSxyLHMpLG0sbSkKaWYo
+dHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5vcygpCmlmKG8+MjU1KWouJDIoayxyKQpuPXErMQpp
+ZihxPj10KXJldHVybiBILk9IKGkscSkKaVtxXT1vCnI9cysxCnE9bn19aWYocSE9PTMpai4kMihsLGMp
+Cm89UC5RQShDLnhCLk5qKGEscixjKSxtLG0pCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8u
+b3MoKQppZihvPjI1NSlqLiQyKGsscikKaWYocT49dClyZXR1cm4gSC5PSChpLHEpCmlbcV09bwpyZXR1
+cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxm
+LGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLnRwKGQsYSkKaWYoYS5sZW5ndGg8MilkLiQxKCJhZGRyZXNz
+IGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1LnQpCmZvcihzPWIscj1zLHE9ITEscD0hMTtzPGEwOysr
+cyl7bz1DLnhCLm0oYSxzKQppZihvPT09NTgpe2lmKHM9PT1iKXsrK3MKaWYoQy54Qi5tKGEscykhPT01
+OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNvbG9uLiIscykKcj1zfWlmKHM9PT1yKXtpZihxKWQuJDIoIm9u
+bHkgb25lIHdpbGRjYXJkIGA6OmAgaXMgYWxsb3dlZCIscykKQy5ObS5pKHQsLTEpCnE9ITB9ZWxzZSBD
+Lk5tLmkodCxjLiQyKHIscykpCnI9cysxfWVsc2UgaWYobz09PTQ2KXA9ITB9aWYodC5sZW5ndGg9PT0w
+KWQuJDEoInRvbyBmZXcgcGFydHMiKQpuPXI9PT1hMAptPUMuTm0uZ3JaKHQpCmlmKG4mJm0hPT0tMSlk
+LiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0ZXIgbGFzdCBgOmAiLGEwKQppZighbilpZighcClDLk5tLmko
+dCxjLiQyKHIsYTApKQplbHNle2w9UC5IaChhLHIsYTApCkMuTm0uaSh0LChsWzBdPDw4fGxbMV0pPj4+
+MCkKQy5ObS5pKHQsKGxbMl08PDh8bFszXSk+Pj4wKX1pZihxKXtpZih0Lmxlbmd0aD43KWQuJDEoImFu
+IGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJkIG11c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2Ug
+aWYodC5sZW5ndGghPT04KWQuJDEoImFuIGFkZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29u
+dGFpbiBleGFjdGx5IDggcGFydHMiKQprPW5ldyBVaW50OEFycmF5KDE2KQpmb3IobT10Lmxlbmd0aCxq
+PWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7czxtOysrcyl7Zz10W3NdCmlmKGc9PT0tMSlmb3IoZj0wO2Y8
+aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1cm4gSC5PSChrLGgpCmtbaF09MAplPWgrMQppZihlPj1qKXJl
+dHVybiBILk9IKGssZSkKa1tlXT0wCmgrPTJ9ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PWop
+cmV0dXJuIEguT0goayxoKQprW2hdPWUKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5PSChrLGUpCmtbZV09
+ZyYyNTUKaCs9Mn19cmV0dXJuIGt9LApqdjpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIg
+dCxzLHIscSxwLG8sbixtPW51bGwKaWYoaj09bnVsbClpZihkPmIpaj1QLlBpKGEsYixkKQplbHNle2lm
+KGQ9PT1iKVAuUjMoYSxiLCJJbnZhbGlkIGVtcHR5IHNjaGVtZSIpCmo9IiJ9aWYoZT5iKXt0PWQrMwpz
+PXQ8ZT9QLnpSKGEsdCxlLTEpOiIiCnI9UC5PZShhLGUsZiwhMSkKaWYodHlwZW9mIGYhPT0ibnVtYmVy
+IilyZXR1cm4gZi5oKCkKcT1mKzEKaWYodHlwZW9mIGchPT0ibnVtYmVyIilyZXR1cm4gSC5wWShnKQpw
+PXE8Zz9QLndCKFAuUUEoSi5sZChhLHEsZyksbmV3IFAuZTEoYSxmKSxtKSxqKTptfWVsc2V7cD1tCnI9
+cApzPSIifW89UC5rYShhLGcsaCxtLGosciE9bnVsbCkKaWYodHlwZW9mIGghPT0ibnVtYmVyIilyZXR1
+cm4gaC5KKCkKbj1oPGk/UC5sZShhLGgrMSxpLG0pOm0KcmV0dXJuIG5ldyBQLkRuKGoscyxyLHAsbyxu
+LGk8Yz9QLnRHKGEsaSsxLGMpOm0pfSwKd0s6ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1cm4g
+ODAKaWYoYT09PSJodHRwcyIpcmV0dXJuIDQ0MwpyZXR1cm4gMH0sClIzOmZ1bmN0aW9uKGEsYixjKXt0
+aHJvdyBILmIoUC5ycihjLGEsYikpfSwKa0U6ZnVuY3Rpb24oYSxiKXtDLk5tLksoYSxuZXcgUC5OWSgh
+MSkpfSwKSE46ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpmb3IodD1ILnFDKGEsYyxudWxsLEgudDYo
+YSkuZCksdD1uZXcgSC5hNyh0LHQuZ0EodCksdC4kdGkuQygiYTc8YUwuRT4iKSk7dC5GKCk7KXtzPXQu
+ZApyPVAubnUoJ1siKi86PD4/XFxcXHxdJykKcy50b1N0cmluZwppZihILm0yKHMsciwwKSl7dD1QLkw0
+KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRoOiAiK3MpCnRocm93IEguYih0KX19fSwKcmc6ZnVuY3Rp
+b24oYSxiKXt2YXIgdAppZighKDY1PD1hJiZhPD05MCkpdD05Nzw9YSYmYTw9MTIyCmVsc2UgdD0hMApp
+Zih0KXJldHVybgp0PVAuTDQoIklsbGVnYWwgZHJpdmUgbGV0dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5i
+KHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihhIT1udWxsJiZhPT09UC53SyhiKSlyZXR1cm4gbnVsbApy
+ZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbwppZihhPT1udWxsKXJl
+dHVybiBudWxsCmlmKGI9PT1jKXJldHVybiIiCmlmKEMueEIubShhLGIpPT09OTEpe2lmKHR5cGVvZiBj
+IT09Im51bWJlciIpcmV0dXJuIGMuSE4oKQp0PWMtMQppZihDLnhCLm0oYSx0KSE9PTkzKVAuUjMoYSxi
+LCJNaXNzaW5nIGVuZCBgXWAgdG8gbWF0Y2ggYFtgIGluIGhvc3QiKQpzPWIrMQpyPVAudG8oYSxzLHQp
+CmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuSigpCmlmKHI8dCl7cT1yKzEKcD1QLk9BKGEs
+Qy54Qi5RaShhLCIyNSIscSk/ciszOnEsdCwiJTI1Iil9ZWxzZSBwPSIiClAuZWcoYSxzLHIpCnJldHVy
+biBDLnhCLk5qKGEsYixyKS50b0xvd2VyQ2FzZSgpK3ArIl0ifWlmKHR5cGVvZiBjIT09Im51bWJlciIp
+cmV0dXJuIEgucFkoYykKbz1iCmZvcig7bzxjOysrbylpZihDLnhCLm0oYSxvKT09PTU4KXtyPUMueEIu
+WFUoYSwiJSIsYikKaWYoIShyPj1iJiZyPGMpKXI9YwppZihyPGMpe3E9cisxCnA9UC5PQShhLEMueEIu
+UWkoYSwiMjUiLHEpP3IrMzpxLGMsIiUyNSIpfWVsc2UgcD0iIgpQLmVnKGEsYixyKQpyZXR1cm4iWyIr
+Qy54Qi5OaihhLGIscikrcCsiXSJ9cmV0dXJuIFAuT0woYSxiLGMpfSwKdG86ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0LHM9Qy54Qi5YVShhLCIlIixiKQppZihzPj1iKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJl
+dHVybiBILnBZKGMpCnQ9czxjfWVsc2UgdD0hMQpyZXR1cm4gdD9zOmN9LApPQTpmdW5jdGlvbihhLGIs
+YyxkKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbAppZih0eXBl
+b2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj0hMApmb3IoO3Q8Yzspe3E9Qy54
+Qi5tKGEsdCkKaWYocT09PTM3KXtwPVAucnYoYSx0LCEwKQpvPXA9PW51bGwKaWYobyYmcil7dCs9Mwpj
+b250aW51ZX1pZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCm49ay5hKz1DLnhCLk5qKGEscyx0KQppZihv
+KXA9Qy54Qi5OaihhLHQsdCszKQplbHNlIGlmKHA9PT0iJSIpUC5SMyhhLHQsIlpvbmVJRCBzaG91bGQg
+bm90IGNvbnRhaW4gJSBhbnltb3JlIikKay5hPW4rcAp0Kz0zCnM9dApyPSEwfWVsc2V7aWYocTwxMjcp
+e289cT4+PjQKaWYobz49OClyZXR1cm4gSC5PSChDLkYzLG8pCm89KEMuRjNbb10mMTw8KHEmMTUpKSE9
+PTB9ZWxzZSBvPSExCmlmKG8pe2lmKHImJjY1PD1xJiY5MD49cSl7aWYoaz09bnVsbClrPW5ldyBQLlJu
+KCIiKQppZihzPHQpe2suYSs9Qy54Qi5OaihhLHMsdCkKcz10fXI9ITF9Kyt0fWVsc2V7aWYoKHEmNjQ1
+MTIpPT09NTUyOTYmJnQrMTxjKXttPUMueEIubShhLHQrMSkKaWYoKG0mNjQ1MTIpPT09NTYzMjApe3E9
+NjU1MzZ8KHEmMTAyMyk8PDEwfG0mMTAyMwpsPTJ9ZWxzZSBsPTF9ZWxzZSBsPTEKaWYoaz09bnVsbClr
+PW5ldyBQLlJuKCIiKQprLmErPUMueEIuTmooYSxzLHQpCmsuYSs9UC56WChxKQp0Kz1sCnM9dH19fWlm
+KGs9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHM8YylrLmErPUMueEIuTmooYSxzLGMpCm89
+ay5hCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwKT0w6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscixxLHAsbyxuLG0sbCxrLGoKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQp0
+PWIKcz10CnI9bnVsbApxPSEwCmZvcig7dDxjOyl7cD1DLnhCLm0oYSx0KQppZihwPT09Mzcpe289UC5y
+dihhLHQsITApCm49bz09bnVsbAppZihuJiZxKXt0Kz0zCmNvbnRpbnVlfWlmKHI9PW51bGwpcj1uZXcg
+UC5SbigiIikKbT1DLnhCLk5qKGEscyx0KQpsPXIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0KaWYobil7
+bz1DLnhCLk5qKGEsdCx0KzMpCms9M31lbHNlIGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0z
+CnIuYT1sK28KdCs9awpzPXQKcT0hMH1lbHNle2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJu
+IEguT0goQy5lYSxuKQpuPShDLmVhW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKXtpZihx
+JiY2NTw9cCYmOTA+PXApe2lmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKaWYoczx0KXtyLmErPUMueEIu
+TmooYSxzLHQpCnM9dH1xPSExfSsrdH1lbHNle2lmKHA8PTkzKXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJu
+IEguT0goQy5hayxuKQpuPShDLmFrW25dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKVAuUjMo
+YSx0LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXtq
+PUMueEIubShhLHQrMSkKaWYoKGomNjQ1MTIpPT09NTYzMjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGom
+MTAyMwprPTJ9ZWxzZSBrPTF9ZWxzZSBrPTEKaWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQptPUMueEIu
+TmooYSxzLHQpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0Kci5hKz1QLnpYKHApCnQrPWsKcz10fX19
+fWlmKHI9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHM8Yyl7bT1DLnhCLk5qKGEscyxjKQpy
+LmErPSFxP20udG9Mb3dlckNhc2UoKTptfW49ci5hCnJldHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpu
+fSwKUGk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGI9PT1jKXJldHVybiIiCmlmKCFQLkV0
+KEouclkoYSkuVyhhLGIpKSlQLlIzKGEsYiwiU2NoZW1lIG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0
+aWMgY2hhcmFjdGVyIikKZm9yKHQ9YixzPSExO3Q8YzsrK3Qpe3I9Qy54Qi5XKGEsdCkKaWYocjwxMjgp
+e3E9cj4+PjQKaWYocT49OClyZXR1cm4gSC5PSChDLm1LLHEpCnE9KEMubUtbcV0mMTw8KHImMTUpKSE9
+PTB9ZWxzZSBxPSExCmlmKCFxKVAuUjMoYSx0LCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQppZig2
+NTw9ciYmcjw9OTApcz0hMH1hPUMueEIuTmooYSxiLGMpCnJldHVybiBQLllhKHM/YS50b0xvd2VyQ2Fz
+ZSgpOmEpfSwKWWE6ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1cm4iaHR0cCIKaWYoYT09PSJm
+aWxlIilyZXR1cm4iZmlsZSIKaWYoYT09PSJodHRwcyIpcmV0dXJuImh0dHBzIgppZihhPT09InBhY2th
+Z2UiKXJldHVybiJwYWNrYWdlIgpyZXR1cm4gYX0sCnpSOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxs
+KXJldHVybiIiCnJldHVybiBQLnVPKGEsYixjLEMudG8sITEpfSwKa2E6ZnVuY3Rpb24oYSxiLGMsZCxl
+LGYpe3ZhciB0LHM9ZT09PSJmaWxlIixyPXN8fGYscT1hPT1udWxsCmlmKHEmJiEwKXJldHVybiBzPyIv
+IjoiIgp0PSFxP1AudU8oYSxiLGMsQy5XZCwhMCk6Qy5qTi5FMihkLG5ldyBQLlJaKCksdS5OKS5IKDAs
+Ii8iKQppZih0Lmxlbmd0aD09PTApe2lmKHMpcmV0dXJuIi8ifWVsc2UgaWYociYmIUMueEIubih0LCIv
+IikpdD0iLyIrdApyZXR1cm4gUC5Kcih0LGUsZil9LApKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Yi5s
+ZW5ndGg9PT0wCmlmKHQmJiFjJiYhQy54Qi5uKGEsIi8iKSlyZXR1cm4gUC53RihhLCF0fHxjKQpyZXR1
+cm4gUC54ZShhKX0sCmxlOmZ1bmN0aW9uKGEsYixjLGQpe2lmKGEhPW51bGwpcmV0dXJuIFAudU8oYSxi
+LGMsQy5WQywhMCkKcmV0dXJuIG51bGx9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1
+cm4gbnVsbApyZXR1cm4gUC51TyhhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHIscSxwLG89YisyCmlmKG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMueEIubShhLGIrMSkKcz1D
+LnhCLm0oYSxvKQpyPUgub28odCkKcT1ILm9vKHMpCmlmKHI8MHx8cTwwKXJldHVybiIlIgpwPXIqMTYr
+cQppZihwPDEyNyl7bz1DLmpuLndHKHAsNCkKaWYobz49OClyZXR1cm4gSC5PSChDLkYzLG8pCm89KEMu
+RjNbb10mMTw8KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pcmV0dXJuIEguTHcoYyYmNjU8PXAmJjkw
+Pj1wPyhwfDMyKT4+PjA6cCkKaWYodD49OTd8fHM+PTk3KXJldHVybiBDLnhCLk5qKGEsYixiKzMpLnRv
+VXBwZXJDYXNlKCkKcmV0dXJuIG51bGx9LAp6WDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbj0i
+MDEyMzQ1Njc4OUFCQ0RFRiIKaWYoYTwxMjgpe3Q9bmV3IEFycmF5KDMpCnQuZml4ZWQkbGVuZ3RoPUFy
+cmF5CnM9SC5WTSh0LHUudCkKQy5ObS5ZKHMsMCwzNykKQy5ObS5ZKHMsMSxDLnhCLlcobixhPj4+NCkp
+CkMuTm0uWShzLDIsQy54Qi5XKG4sYSYxNSkpfWVsc2V7aWYoYT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQw
+CnE9NH1lbHNle3I9MjI0CnE9M31lbHNle3I9MTkyCnE9Mn10PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQk
+bGVuZ3RoPUFycmF5CnM9SC5WTSh0LHUudCkKZm9yKHA9MDstLXEscT49MDtyPTEyOCl7bz1DLmpuLmJm
+KGEsNipxKSY2M3xyCkMuTm0uWShzLHAsMzcpCkMuTm0uWShzLHArMSxDLnhCLlcobixvPj4+NCkpCkMu
+Tm0uWShzLHArMixDLnhCLlcobixvJjE1KSkKcCs9M319cmV0dXJuIFAuSE0ocywwLG51bGwpfSwKdU86
+ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1QLlVsKGEsYixjLGQsZSkKcmV0dXJuIHQ9PW51bGw/Qy54
+Qi5OaihhLGIsYyk6dH0sClVsOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvPW51bGws
+bj0hZSxtPWIsbD1tLGs9bwp3aGlsZSghMCl7aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5K
+KCkKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQppZighKG08YykpYnJlYWsKYyQw
+Ont0PUMueEIubShhLG0pCmlmKHQ8MTI3KXtzPXQ+Pj40CmlmKHM+PTgpcmV0dXJuIEguT0goZCxzKQpz
+PShkW3NdJjE8PCh0JjE1KSkhPT0wfWVsc2Ugcz0hMQppZihzKSsrbQplbHNle2lmKHQ9PT0zNyl7cj1Q
+LnJ2KGEsbSwhMSkKaWYocj09bnVsbCl7bSs9MwpicmVhayBjJDB9aWYoIiUiPT09cil7cj0iJTI1Igpx
+PTF9ZWxzZSBxPTN9ZWxzZXtpZihuKWlmKHQ8PTkzKXtzPXQ+Pj40CmlmKHM+PTgpcmV0dXJuIEguT0go
+Qy5hayxzKQpzPShDLmFrW3NdJjE8PCh0JjE1KSkhPT0wfWVsc2Ugcz0hMQplbHNlIHM9ITEKaWYocyl7
+UC5SMyhhLG0sIkludmFsaWQgY2hhcmFjdGVyIikKcT1vCnI9cX1lbHNle2lmKCh0JjY0NTEyKT09PTU1
+Mjk2KXtzPW0rMQppZihzPGMpe3A9Qy54Qi5tKGEscykKaWYoKHAmNjQ1MTIpPT09NTYzMjApe3Q9NjU1
+MzZ8KHQmMTAyMyk8PDEwfHAmMTAyMwpxPTJ9ZWxzZSBxPTF9ZWxzZSBxPTF9ZWxzZSBxPTEKcj1QLnpY
+KHQpfX1pZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5OaihhLGwsbSkKay5hKz1ILmQo
+cikKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShxKQptKz1xCmw9bX19fWlmKGs9PW51
+bGwpcmV0dXJuIG8KaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5KKCkKaWYobDxjKWsuYSs9
+Qy54Qi5OaihhLGwsYykKbj1rLmEKcmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LAp5QjpmdW5j
+dGlvbihhKXtpZihDLnhCLm4oYSwiLiIpKXJldHVybiEwCnJldHVybiBDLnhCLk9ZKGEsIi8uIikhPT0t
+MX0sCnhlOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuCmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9
+SC5WTShbXSx1LnMpCmZvcihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ap
+e289c1twXQppZihKLlJNKG8sIi4uIikpe249dC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJu
+IEguT0godCwtMSkKdC5wb3AoKQppZih0Lmxlbmd0aD09PTApQy5ObS5pKHQsIiIpfXE9ITB9ZWxzZSBp
+ZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLmkodCxvKQpxPSExfX1pZihxKUMuTm0uaSh0LCIiKQpyZXR1
+cm4gQy5ObS5IKHQsIi8iKX0sCndGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvCmlmKCFQLnlC
+KGEpKXJldHVybiFiP1AuQzEoYSk6YQp0PUguVk0oW10sdS5zKQpmb3Iocz1hLnNwbGl0KCIvIikscj1z
+Lmxlbmd0aCxxPSExLHA9MDtwPHI7KytwKXtvPXNbcF0KaWYoIi4uIj09PW8paWYodC5sZW5ndGghPT0w
+JiZDLk5tLmdyWih0KSE9PSIuLiIpe2lmKDA+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsLTEpCnQucG9w
+KCkKcT0hMH1lbHNle0MuTm0uaSh0LCIuLiIpCnE9ITF9ZWxzZSBpZigiLiI9PT1vKXE9ITAKZWxzZXtD
+Lk5tLmkodCxvKQpxPSExfX1zPXQubGVuZ3RoCmlmKHMhPT0wKWlmKHM9PT0xKXtpZigwPj1zKXJldHVy
+biBILk9IKHQsMCkKcz10WzBdLmxlbmd0aD09PTB9ZWxzZSBzPSExCmVsc2Ugcz0hMAppZihzKXJldHVy
+biIuLyIKaWYocXx8Qy5ObS5ncloodCk9PT0iLi4iKUMuTm0uaSh0LCIiKQppZighYil7aWYoMD49dC5s
+ZW5ndGgpcmV0dXJuIEguT0godCwwKQpDLk5tLlkodCwwLFAuQzEodFswXSkpfXJldHVybiBDLk5tLkgo
+dCwiLyIpfSwKQzE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS5sZW5ndGgKaWYocT49MiYmUC5FdChK
+LlF6KGEsMCkpKWZvcih0PTE7dDxxOysrdCl7cz1DLnhCLlcoYSx0KQppZihzPT09NTgpcmV0dXJuIEMu
+eEIuTmooYSwwLHQpKyIlM0EiK0MueEIuRyhhLHQrMSkKaWYoczw9MTI3KXtyPXM+Pj40CmlmKHI+PTgp
+cmV0dXJuIEguT0goQy5tSyxyKQpyPShDLm1LW3JdJjE8PChzJjE1KSk9PT0wfWVsc2Ugcj0hMAppZihy
+KWJyZWFrfXJldHVybiBhfSwKbW46ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9YS5nRmooKSxwPXEubGVu
+Z3RoCmlmKHA+MCYmSi5IbShxWzBdKT09PTImJkouYTYocVswXSwxKT09PTU4KXtpZigwPj1wKXJldHVy
+biBILk9IKHEsMCkKUC5yZyhKLmE2KHFbMF0sMCksITEpClAuSE4ocSwhMSwxKQp0PSEwfWVsc2V7UC5I
+TihxLCExLDApCnQ9ITF9cz1hLmd0VCgpJiYhdD8iXFwiOiIiCmlmKGEuZ2NqKCkpe3I9YS5nSmYoYSkK
+aWYoci5sZW5ndGghPT0wKXM9cysiXFwiK3IrIlxcIn1zPVAudmcocyxxLCJcXCIpCnA9dCYmcD09PTE/
+cysiXFwiOnMKcmV0dXJuIHAuY2hhckNvZGVBdCgwKT09MD9wOnB9LApJaDpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscgpmb3IodD0wLHM9MDtzPDI7KytzKXtyPUMueEIuVyhhLGIrcykKaWYoNDg8PXImJnI8PTU3
+KXQ9dCoxNityLTQ4CmVsc2V7cnw9MzIKaWYoOTc8PXImJnI8PTEwMil0PXQqMTYrci04NwplbHNlIHRo
+cm93IEguYihQLnhZKCJJbnZhbGlkIFVSTCBlbmNvZGluZyIpKX19cmV0dXJuIHR9LAprdTpmdW5jdGlv
+bihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHA9Si5yWShhKSxvPWIKd2hpbGUoITApe2lmKCEobzxjKSl7
+dD0hMApicmVha31zPXAuVyhhLG8pCmlmKHM8PTEyNylpZihzIT09Mzcpcj1lJiZzPT09NDMKZWxzZSBy
+PSEwCmVsc2Ugcj0hMAppZihyKXt0PSExCmJyZWFrfSsrb31pZih0KXtpZihDLnhNIT09ZClyPSExCmVs
+c2Ugcj0hMAppZihyKXJldHVybiBwLk5qKGEsYixjKQplbHNlIHE9bmV3IEgucWoocC5OaihhLGIsYykp
+fWVsc2V7cT1ILlZNKFtdLHUudCkKZm9yKG89YjtvPGM7KytvKXtzPXAuVyhhLG8pCmlmKHM+MTI3KXRo
+cm93IEguYihQLnhZKCJJbGxlZ2FsIHBlcmNlbnQgZW5jb2RpbmcgaW4gVVJJIikpCmlmKHM9PT0zNyl7
+aWYobyszPmEubGVuZ3RoKXRocm93IEguYihQLnhZKCJUcnVuY2F0ZWQgVVJJIikpCkMuTm0uaShxLFAu
+SWgoYSxvKzEpKQpvKz0yfWVsc2UgaWYoZSYmcz09PTQzKUMuTm0uaShxLDMyKQplbHNlIEMuTm0uaShx
+LHMpfX11LkwuYihxKQpyZXR1cm4gbmV3IFAuR1koITEpLldKKHEpfSwKRXQ6ZnVuY3Rpb24oYSl7dmFy
+IHQ9YXwzMgpyZXR1cm4gOTc8PXQmJnQ8PTEyMn0sCktEOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIs
+cSxwLG8sbixtLGw9IkludmFsaWQgTUlNRSB0eXBlIixrPUguVk0oW2ItMV0sdS50KQpmb3IodD1hLmxl
+bmd0aCxzPWIscj0tMSxxPW51bGw7czx0Oysrcyl7cT1DLnhCLlcoYSxzKQppZihxPT09NDR8fHE9PT01
+OSlicmVhawppZihxPT09NDcpe2lmKHI8MCl7cj1zCmNvbnRpbnVlfXRocm93IEguYihQLnJyKGwsYSxz
+KSl9fWlmKHI8MCYmcz5iKXRocm93IEguYihQLnJyKGwsYSxzKSkKZm9yKDtxIT09NDQ7KXtDLk5tLmko
+ayxzKTsrK3MKZm9yKHA9LTE7czx0Oysrcyl7cT1DLnhCLlcoYSxzKQppZihxPT09NjEpe2lmKHA8MClw
+PXN9ZWxzZSBpZihxPT09NTl8fHE9PT00NClicmVha31pZihwPj0wKUMuTm0uaShrLHApCmVsc2V7bz1D
+Lk5tLmdyWihrKQppZihxIT09NDR8fHMhPT1vKzd8fCFDLnhCLlFpKGEsImJhc2U2NCIsbysxKSl0aHJv
+dyBILmIoUC5ycigiRXhwZWN0aW5nICc9JyIsYSxzKSkKYnJlYWt9fUMuTm0uaShrLHMpCm49cysxCmlm
+KChrLmxlbmd0aCYxKT09PTEpYT1DLmg5LnlyKGEsbix0KQplbHNle209UC5VbChhLG4sdCxDLlZDLCEw
+KQppZihtIT1udWxsKWE9Qy54Qi5pNyhhLG4sdCxtKX1yZXR1cm4gbmV3IFAuUEUoYSxrLGMpfSwKdXg6
 ZnVuY3Rpb24oKXt2YXIgdD0iMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVm
 Z2hpamtsbW5vcHFyc3R1dnd4eXotLl9+ISQmJygpKissOz0iLHM9Ii4iLHI9IjoiLHE9Ii8iLHA9Ij8i
-LG89IiMiLG49dS5nYyxtPVAuak4oMjIsbmV3IFAuZmEoKSxuKSxsPW5ldyBQLmY5KG0pLGs9bmV3IFAu
-ZmIoKSxqPW5ldyBQLmZjKCksaT1uLmIobC4kMigwLDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxzLDE0
-KQprLiQzKGksciwzNCkKay4kMyhpLHEsMykKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5i
-KGwuJDIoMTQsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHMsMTUpCmsuJDMoaSxyLDM0KQprLiQzKGks
-cSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE1LDIyNSkpCmsuJDMo
-aSx0LDEpCmsuJDMoaSwiJSIsMjI1KQprLiQzKGksciwzNCkKay4kMyhpLHEsOSkKay4kMyhpLHAsMTcy
-KQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMSwyMjUpKQprLiQzKGksdCwxKQprLiQzKGksciwzNCkK
-ay4kMyhpLHEsMTApCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDIsMjM1KSkK
-ay4kMyhpLHQsMTM5KQprLiQzKGkscSwxMzEpCmsuJDMoaSxzLDE0NikKay4kMyhpLHAsMTcyKQprLiQz
-KGksbywyMDUpCmk9bi5iKGwuJDIoMywyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEsNjgpCmsuJDMo
-aSxzLDE4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig0LDIyOSkpCmsuJDMo
-aSx0LDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHIsMTAyKQprLiQzKGksIkAiLDY4KQprLiQzKGks
-IlsiLDIzMikKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4k
-Mig1LDIyOSkpCmsuJDMoaSx0LDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHIsMTAyKQprLiQzKGks
-IkAiLDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQy
-KDYsMjMxKSkKai4kMyhpLCIxOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4KQprLiQzKGks
-cCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig3LDIzMSkpCmouJDMoaSwiMDkiLDcpCmsuJDMo
-aSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmsuJDMobi5i
-KGwuJDIoOCw4KSksIl0iLDUpCmk9bi5iKGwuJDIoOSwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMs
-MTYpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTYs
-MjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE3KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikK
-ay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE3LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscSw5KQpr
-LiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigxMCwyMzUpKQprLiQzKGksdCwxMSkK
-ay4kMyhpLHMsMTgpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5i
-KGwuJDIoMTgsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE5KQprLiQzKGkscSwyMzQpCmsuJDMo
-aSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE5LDIzNSkpCmsuJDMoaSx0LDExKQprLiQz
-KGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDExLDIzNSkpCmsu
-JDMoaSx0LDExKQprLiQzKGkscSwxMCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwu
-JDIoMTIsMjM2KSkKay4kMyhpLHQsMTIpCmsuJDMoaSxwLDEyKQprLiQzKGksbywyMDUpCmk9bi5iKGwu
-JDIoMTMsMjM3KSkKay4kMyhpLHQsMTMpCmsuJDMoaSxwLDEzKQpqLiQzKG4uYihsLiQyKDIwLDI0NSkp
-LCJheiIsMjEpCmw9bi5iKGwuJDIoMjEsMjQ1KSkKai4kMyhsLCJheiIsMjEpCmouJDMobCwiMDkiLDIx
-KQprLiQzKGwsIistLiIsMjEpCnJldHVybiBtfSwKaUM6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxz
-LHIscSxwLG89JC5qaCgpCmZvcih0PUouYTAoYSkscz1iO3M8YzsrK3Mpe2lmKGQ8MHx8ZD49by5sZW5n
-dGgpcmV0dXJuIEguaShvLGQpCnI9b1tkXQpxPXQudChhLHMpXjk2CmlmKHE+OTUpcT0zMQppZihxPj1y
-Lmxlbmd0aClyZXR1cm4gSC5pKHIscSkKcD1yW3FdCmQ9cCYzMQpDLmIubChlLHA+Pj41LHMpfXJldHVy
-biBkfSwKZWI6ZnVuY3Rpb24gZWIoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCno6ZnVuY3Rpb24geigp
-e30sCmI3OmZ1bmN0aW9uIGI3KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApUOmZ1bmN0aW9uIFQoKXt9
-LApiODpmdW5jdGlvbiBiOChhKXt0aGlzLmE9YX0sCmRYOmZ1bmN0aW9uIGRYKCl7fSwKZFk6ZnVuY3Rp
-b24gZFkoKXt9LApyOmZ1bmN0aW9uIHIoKXt9LApidzpmdW5jdGlvbiBidyhhKXt0aGlzLmE9YX0sCmJk
-OmZ1bmN0aW9uIGJkKCl7fSwKYTE6ZnVuY3Rpb24gYTEoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpf
-LmI9YgpfLmM9YwpfLmQ9ZH0sCmFVOmZ1bmN0aW9uIGFVKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8u
-ZT1hCl8uZj1iCl8uYT1jCl8uYj1kCl8uYz1lCl8uZD1mfSwKY0c6ZnVuY3Rpb24gY0coYSxiLGMsZCxl
-KXt2YXIgXz10aGlzCl8uZj1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKY1U6ZnVuY3Rpb24gY1Uo
-YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmRiOmZ1bmN0aW9uIGRi
-KGEpe3RoaXMuYT1hfSwKZDk6ZnVuY3Rpb24gZDkoYSl7dGhpcy5hPWF9LApiaDpmdW5jdGlvbiBiaChh
-KXt0aGlzLmE9YX0sCmN6OmZ1bmN0aW9uIGN6KGEpe3RoaXMuYT1hfSwKY1c6ZnVuY3Rpb24gY1coKXt9
-LApiWDpmdW5jdGlvbiBiWCgpe30sCmNCOmZ1bmN0aW9uIGNCKGEpe3RoaXMuYT1hfSwKZUE6ZnVuY3Rp
-b24gZUEoYSl7dGhpcy5hPWF9LAplXzpmdW5jdGlvbiBlXyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIK
-dGhpcy5jPWN9LAphYjpmdW5jdGlvbiBhYigpe30sCmY6ZnVuY3Rpb24gZigpe30sCmo6ZnVuY3Rpb24g
-aigpe30sClI6ZnVuY3Rpb24gUigpe30sCm06ZnVuY3Rpb24gbSgpe30sCnk6ZnVuY3Rpb24geSgpe30s
-CnA6ZnVuY3Rpb24gcCgpe30sClU6ZnVuY3Rpb24gVSgpe30sCnQ6ZnVuY3Rpb24gdCgpe30sCk06ZnVu
-Y3Rpb24gTSgpe30sCmFnOmZ1bmN0aW9uIGFnKCl7fSwKYzpmdW5jdGlvbiBjKCl7fSwKSDpmdW5jdGlv
-biBIKGEpe3RoaXMuYT1hfSwKYTY6ZnVuY3Rpb24gYTYoKXt9LAplcTpmdW5jdGlvbiBlcShhKXt0aGlz
-LmE9YX0sCmVuOmZ1bmN0aW9uIGVuKGEpe3RoaXMuYT1hfSwKZW86ZnVuY3Rpb24gZW8oYSl7dGhpcy5h
-PWF9LAplcDpmdW5jdGlvbiBlcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKY2s6ZnVuY3Rpb24gY2so
-YSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9
-ZgpfLnI9ZwpfLlE9Xy56PV8ueT1udWxsfSwKZjE6ZnVuY3Rpb24gZjEoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Yn0sCmYyOmZ1bmN0aW9uIGYyKCl7fSwKZW06ZnVuY3Rpb24gZW0oYSxiLGMpe3RoaXMuYT1hCnRo
-aXMuYj1iCnRoaXMuYz1jfSwKZmE6ZnVuY3Rpb24gZmEoKXt9LApmOTpmdW5jdGlvbiBmOShhKXt0aGlz
-LmE9YX0sCmZiOmZ1bmN0aW9uIGZiKCl7fSwKZmM6ZnVuY3Rpb24gZmMoKXt9LApkejpmdW5jdGlvbiBk
-eihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUK
-Xy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApkbTpmdW5jdGlvbiBkbShhLGIsYyxkLGUsZixnKXt2
-YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9
-Xy55PW51bGx9LAplVjpmdW5jdGlvbiBlVigpe30sCmVYOmZ1bmN0aW9uIGVYKGEsYil7dGhpcy5hPWEK
-dGhpcy5iPWJ9LAplWTpmdW5jdGlvbiBlWShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZVc6ZnVuY3Rp
-b24gZVcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmNBOmZ1bmN0aW9uIGNBKCl7fSwKZFQ6ZnVuY3Rp
-b24gZFQoYSl7dGhpcy5hPWF9LApiSzpmdW5jdGlvbiBiSygpe30sCmtUOmZ1bmN0aW9uKGEsYixjLGQp
-e3ZhciB0LHMscgpILmhnKGIpCnUuai5iKGQpCmlmKEguZEsoYikpe3Q9W2NdCkMuYi5JKHQsZCkKZD10
-fXM9dS56CnI9UC5oMihKLmpwKGQsUC5seSgpLHMpLCEwLHMpCnUuWi5iKGEpCnJldHVybiBQLmhpKEgu
-alMoYSxyLG51bGwpKX0sCmhqOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0cnl7aWYoT2JqZWN0LmlzRXh0
-ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmpl
-Y3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHQpe0guUSh0KX1y
-ZXR1cm4hMX0sCml2OmZ1bmN0aW9uKGEsYil7aWYoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0
-eS5jYWxsKGEsYikpcmV0dXJuIGFbYl0KcmV0dXJuIG51bGx9LApoaTpmdW5jdGlvbihhKXtpZihhPT1u
-dWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8SC5mZChhKSlyZXR1cm4g
-YQppZihhIGluc3RhbmNlb2YgUC5ZKXJldHVybiBhLmEKaWYoSC5pTShhKSlyZXR1cm4gYQppZih1Lmku
-YyhhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5iNylyZXR1cm4gSC5hVChhKQppZih1LlouYyhh
-KSlyZXR1cm4gUC5pdShhLCIkZGFydF9qc0Z1bmN0aW9uIixuZXcgUC5mNygpKQpyZXR1cm4gUC5pdShh
-LCJfJGRhcnRfanNPYmplY3QiLG5ldyBQLmY4KCQuaEMoKSkpfSwKaXU6ZnVuY3Rpb24oYSxiLGMpe3Zh
-ciB0PVAuaXYoYSxiKQppZih0PT1udWxsKXt0PWMuJDEoYSkKUC5oaihhLGIsdCl9cmV0dXJuIHR9LApo
-aDpmdW5jdGlvbihhKXt2YXIgdCxzCmlmKGE9PW51bGx8fHR5cGVvZiBhPT0ic3RyaW5nInx8dHlwZW9m
-IGE9PSJudW1iZXIifHx0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5j
-ZW9mIE9iamVjdCYmSC5pTShhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBPYmplY3QmJnUu
-aS5jKGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIERhdGUpe3Q9SC54KGEuZ2V0VGltZSgp
-KQppZihNYXRoLmFicyh0KTw9ODY0ZTEzKXM9ITEKZWxzZSBzPSEwCmlmKHMpSC5hayhQLmI0KCJEYXRl
-VGltZSBpcyBvdXRzaWRlIHZhbGlkIHJhbmdlOiAiK3QpKQpyZXR1cm4gbmV3IFAuYjcodCwhMSl9ZWxz
-ZSBpZihhLmNvbnN0cnVjdG9yPT09JC5oQygpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5pRihhKX0s
-CmlGOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmhrKGEsJC5mVigp
-LG5ldyBQLmZnKCkpCmlmKGEgaW5zdGFuY2VvZiBBcnJheSlyZXR1cm4gUC5oayhhLCQuaEIoKSxuZXcg
-UC5maCgpKQpyZXR1cm4gUC5oayhhLCQuaEIoKSxuZXcgUC5maSgpKX0sCmhrOmZ1bmN0aW9uKGEsYixj
-KXt2YXIgdD1QLml2KGEsYikKaWYodD09bnVsbHx8IShhIGluc3RhbmNlb2YgT2JqZWN0KSl7dD1jLiQx
-KGEpClAuaGooYSxiLHQpfXJldHVybiB0fSwKZjc6ZnVuY3Rpb24gZjcoKXt9LApmODpmdW5jdGlvbiBm
-OChhKXt0aGlzLmE9YX0sCmZnOmZ1bmN0aW9uIGZnKCl7fSwKZmg6ZnVuY3Rpb24gZmgoKXt9LApmaTpm
-dW5jdGlvbiBmaSgpe30sClk6ZnVuY3Rpb24gWShhKXt0aGlzLmE9YX0sCmJiOmZ1bmN0aW9uIGJiKGEp
-e3RoaXMuYT1hfSwKYU86ZnVuY3Rpb24gYU8oYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKYzU6ZnVu
-Y3Rpb24gYzUoKXt9LApiZzpmdW5jdGlvbiBiZygpe30sCmN2OmZ1bmN0aW9uIGN2KGEpe3RoaXMuYT1h
-fSwKZTpmdW5jdGlvbiBlKCl7fSwKYWg6ZnVuY3Rpb24gYWgoKXt9fSxXPXsKakY6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0PWRvY3VtZW50LmJvZHkscz0odCYmQy5wKS5LKHQsYSxiLGMpCnMudG9TdHJpbmcKdD11
-LmFjCnQ9bmV3IEguYVkobmV3IFcuTyhzKSx0LmgoInoobC5FKSIpLmIobmV3IFcuZFooKSksdC5oKCJh
-WTxsLkU+IikpCnJldHVybiB1LmguYih0LmdZKHQpKX0sCmJEOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0i
-ZWxlbWVudCB0YWcgdW5hdmFpbGFibGUiCnRyeXt0PUouRShhKQppZih0eXBlb2YgdC5nYm0oYSk9PSJz
-dHJpbmciKXI9dC5nYm0oYSl9Y2F0Y2gocyl7SC5RKHMpfXJldHVybiByfSwKZTI6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0LHMscixxPW5ldyBQLlMoJC53LHUuYW8pLHA9bmV3IFAuYzAocSx1LkUpLG89bmV3IFhN
-TEh0dHBSZXF1ZXN0KCkKQy5PLmNsKG8sYj09bnVsbD8iR0VUIjpiLGEsITApCmMuQSgwLG5ldyBXLmUz
-KG8pKQp0PXUuYW4Kcz10LmIobmV3IFcuZTQobyxwKSkKdS5NLmIobnVsbCkKcj11LnAKVy5hQyhvLCJs
-b2FkIixzLCExLHIpClcuYUMobywiZXJyb3IiLHQuYihwLmdjNSgpKSwhMSxyKQpvLnNlbmQoKQpyZXR1
-cm4gcX0sCmVQOmZ1bmN0aW9uKGEsYil7YT01MzY4NzA5MTEmYStiCmE9NTM2ODcwOTExJmErKCg1MjQy
-ODcmYSk8PDEwKQpyZXR1cm4gYV5hPj4+Nn0sCmliOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PVcuZVAo
-Vy5lUChXLmVQKFcuZVAoMCxhKSxiKSxjKSxkKSxzPTUzNjg3MDkxMSZ0KygoNjcxMDg4NjMmdCk8PDMp
-CnNePXM+Pj4xMQpyZXR1cm4gNTM2ODcwOTExJnMrKCgxNjM4MyZzKTw8MTUpfSwKYUM6ZnVuY3Rpb24o
-YSxiLGMsZCxlKXt2YXIgdD1XLmxlKG5ldyBXLmV6KGMpLHUuQSkKaWYodCE9bnVsbCYmITApSi5qbChh
-LGIsdCwhMSkKcmV0dXJuIG5ldyBXLmRxKGEsYix0LCExLGUuaCgiZHE8MD4iKSl9LAppYTpmdW5jdGlv
-bihhKXt2YXIgdD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJhIikscz1uZXcgVy5keSh0LHdpbmRvdy5s
-b2NhdGlvbikKcz1uZXcgVy5iXyhzKQpzLmJEKGEpCnJldHVybiBzfSwKa2w6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dS5oLmIoYSkKSC5vKGIpCkgubyhjKQp1Lk8uYihkKQpyZXR1cm4hMH0sCmttOmZ1bmN0aW9uKGEs
-YixjLGQpe3ZhciB0LHMscgp1LmguYihhKQpILm8oYikKSC5vKGMpCnQ9dS5PLmIoZCkuYQpzPXQuYQpz
-LmhyZWY9YwpyPXMuaG9zdG5hbWUKdD10LmIKaWYoIShyPT10Lmhvc3RuYW1lJiZzLnBvcnQ9PXQucG9y
-dCYmcy5wcm90b2NvbD09dC5wcm90b2NvbCkpaWYocj09PSIiKWlmKHMucG9ydD09PSIiKXt0PXMucHJv
-dG9jb2wKdD10PT09IjoifHx0PT09IiJ9ZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITAKcmV0dXJu
-IHR9LAppZTpmdW5jdGlvbigpe3ZhciB0PXUuTixzPVAuaFQoQy56LHQpLHI9dS5kRy5iKG5ldyBXLmVa
-KCkpLHE9SC5uKFsiVEVNUExBVEUiXSx1LnMpCnQ9bmV3IFcuZEIocyxQLmJNKHQpLFAuYk0odCksUC5i
-TSh0KSxudWxsKQp0LmJFKG51bGwsbmV3IEguYTQoQy56LHIsdS5kdikscSxudWxsKQpyZXR1cm4gdH0s
-CmlzOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoInBvc3RNZXNzYWdl
-IiBpbiBhKXt0PVcua2soYSkKcmV0dXJuIHR9ZWxzZSByZXR1cm4gdS5hUy5iKGEpfSwKa2s6ZnVuY3Rp
-b24oYSl7aWYoYT09PXdpbmRvdylyZXR1cm4gdS5jaS5iKGEpCmVsc2UgcmV0dXJuIG5ldyBXLmRsKCl9
-LApsZTpmdW5jdGlvbihhLGIpe3ZhciB0PSQudwppZih0PT09Qy5kKXJldHVybiBhCnJldHVybiB0LmMy
-KGEsYil9LApoOmZ1bmN0aW9uIGgoKXt9LApiMzpmdW5jdGlvbiBiMygpe30sCmN1OmZ1bmN0aW9uIGN1
-KCl7fSwKYjU6ZnVuY3Rpb24gYjUoKXt9LAphRzpmdW5jdGlvbiBhRygpe30sCmFIOmZ1bmN0aW9uIGFI
-KCl7fSwKYWE6ZnVuY3Rpb24gYWEoKXt9LApiQTpmdW5jdGlvbiBiQSgpe30sCmRVOmZ1bmN0aW9uIGRV
-KCl7fSwKYUw6ZnVuY3Rpb24gYUwoKXt9LApkVjpmdW5jdGlvbiBkVigpe30sCmJCOmZ1bmN0aW9uIGJC
-KCl7fSwKZFc6ZnVuY3Rpb24gZFcoKXt9LAphcTpmdW5jdGlvbiBhcShhLGIpe3RoaXMuYT1hCnRoaXMu
-JHRpPWJ9LAp1OmZ1bmN0aW9uIHUoKXt9LApkWjpmdW5jdGlvbiBkWigpe30sCmQ6ZnVuY3Rpb24gZCgp
-e30sCnE6ZnVuY3Rpb24gcSgpe30sCmI5OmZ1bmN0aW9uIGI5KCl7fSwKY0Y6ZnVuY3Rpb24gY0YoKXt9
-LAplMTpmdW5jdGlvbiBlMSgpe30sCmJGOmZ1bmN0aW9uIGJGKCl7fSwKYTM6ZnVuY3Rpb24gYTMoKXt9
-LAplMzpmdW5jdGlvbiBlMyhhKXt0aGlzLmE9YX0sCmU0OmZ1bmN0aW9uIGU0KGEsYil7dGhpcy5hPWEK
-dGhpcy5iPWJ9LApiRzpmdW5jdGlvbiBiRygpe30sCmJIOmZ1bmN0aW9uIGJIKCl7fSwKYk86ZnVuY3Rp
-b24gYk8oKXt9LApLOmZ1bmN0aW9uIEsoKXt9LApPOmZ1bmN0aW9uIE8oYSl7dGhpcy5hPWF9LAprOmZ1
-bmN0aW9uIGsoKXt9LApiVDpmdW5jdGlvbiBiVCgpe30sCmJlOmZ1bmN0aW9uIGJlKCl7fSwKYTU6ZnVu
-Y3Rpb24gYTUoKXt9LApkMTpmdW5jdGlvbiBkMSgpe30sCmJaOmZ1bmN0aW9uIGJaKCl7fSwKZDY6ZnVu
-Y3Rpb24gZDYoKXt9LApkNzpmdW5jdGlvbiBkNygpe30sCmJqOmZ1bmN0aW9uIGJqKCl7fSwKYTc6ZnVu
-Y3Rpb24gYTcoKXt9LAphQTpmdW5jdGlvbiBhQSgpe30sCmFpOmZ1bmN0aW9uIGFpKCl7fSwKYm06ZnVu
-Y3Rpb24gYm0oKXt9LApjMzpmdW5jdGlvbiBjMygpe30sCmM4OmZ1bmN0aW9uIGM4KCl7fSwKZGk6ZnVu
-Y3Rpb24gZGkoKXt9LAphcDpmdW5jdGlvbiBhcChhKXt0aGlzLmE9YX0sCmFCOmZ1bmN0aW9uIGFCKGEp
-e3RoaXMuYT1hfSwKZXc6ZnVuY3Rpb24gZXcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmV4OmZ1bmN0
-aW9uIGV4KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApkbjpmdW5jdGlvbiBkbihhKXt0aGlzLmE9YX0s
-CmhfOmZ1bmN0aW9uIGhfKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmM0OmZ1bmN0aW9uIGM0KGEs
-YixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCmJuOmZ1bmN0aW9uIGJu
-KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCmRxOmZ1bmN0aW9u
-IGRxKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmI9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwK
-ZXo6ZnVuY3Rpb24gZXooYSl7dGhpcy5hPWF9LApiXzpmdW5jdGlvbiBiXyhhKXt0aGlzLmE9YX0sCmFj
-OmZ1bmN0aW9uIGFjKCl7fSwKYlU6ZnVuY3Rpb24gYlUoYSl7dGhpcy5hPWF9LAplZDpmdW5jdGlvbiBl
-ZChhKXt0aGlzLmE9YX0sCmVjOmZ1bmN0aW9uIGVjKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlz
-LmM9Y30sCmNmOmZ1bmN0aW9uIGNmKCl7fSwKZVQ6ZnVuY3Rpb24gZVQoKXt9LAplVTpmdW5jdGlvbiBl
-VSgpe30sCmRCOmZ1bmN0aW9uIGRCKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmU9YQpfLmE9YgpfLmI9
-YwpfLmM9ZApfLmQ9ZX0sCmVaOmZ1bmN0aW9uIGVaKCl7fSwKZEE6ZnVuY3Rpb24gZEEoKXt9LAphTjpm
-dW5jdGlvbiBhTihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9LTEKXy5kPW51bGwKXy4k
-dGk9Y30sCmRsOmZ1bmN0aW9uIGRsKCl7fSwKRzpmdW5jdGlvbiBHKCl7fSwKZHk6ZnVuY3Rpb24gZHko
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmNtOmZ1bmN0aW9uIGNtKGEpe3RoaXMuYT1hfSwKZjU6ZnVu
-Y3Rpb24gZjUoYSl7dGhpcy5hPWF9LApkazpmdW5jdGlvbiBkaygpe30sCmR2OmZ1bmN0aW9uIGR2KCl7
-fSwKZHc6ZnVuY3Rpb24gZHcoKXt9LApkSDpmdW5jdGlvbiBkSCgpe30sCmRJOmZ1bmN0aW9uIGRJKCl7
-fX0sTD17CmZyOmZ1bmN0aW9uKGEpe3ZhciB0PVAuaTUoYSkuZ2FKKCkuaigwLCJvZmZzZXQiKQpyZXR1
-cm4gdD09bnVsbD9udWxsOkguaDQodCxudWxsKX0sCmZxOmZ1bmN0aW9uKGEpe3ZhciB0PVAuaTUoYSku
-Z2FKKCkuaigwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILmg0KHQsbnVsbCl9LAppRzpmdW5j
-dGlvbihhKXtpZigwPj1hLmxlbmd0aClyZXR1cm4gSC5pKGEsMCkKaWYoYVswXSE9PSIvIilyZXR1cm4g
-Si5kUihkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSsiLyIrSC5iKGEp
-CmVsc2UgcmV0dXJuIGF9LApsRTpmdW5jdGlvbihhKXt2YXIgdD1KLmpqKGRvY3VtZW50LnF1ZXJ5U2Vs
-ZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQsIi8iKQppZihKLmEwKGEpLkgoYSx0KSlyZXR1cm4gQy5h
-LlUoYSx0Lmxlbmd0aCkKZWxzZSByZXR1cm4gYX0sCmxIOmZ1bmN0aW9uKGEyKXt2YXIgdCxzLHIscSxw
-LG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYj0iZGlzYWJsZWQiLGE9ImxpbmUiLGEwPWRvY3VtZW50
-LGExPWEwLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0LWxpc3QgLnBhbmVsLWNvbnRlbnQiKQpKLmRRKGExLCIi
-KQp0PWEwLmNyZWF0ZUVsZW1lbnQoInAiKQpzPWExLmFwcGVuZENoaWxkKHQpCnQ9YTAuY3JlYXRlRWxl
-bWVudCgic3Ryb25nIikKcj1zLmFwcGVuZENoaWxkKHQpCnQ9Si5hXyhhMikKcT1ILngodC5qKGEyLCJl
-ZGl0Q291bnQiKSkKci5hcHBlbmRDaGlsZChhMC5jcmVhdGVUZXh0Tm9kZShKLmIyKHEpKSkKaWYocT09
-PTEpcy5hcHBlbmRDaGlsZChhMC5jcmVhdGVUZXh0Tm9kZSgiIGVkaXQgd2FzIG1hZGUgdG8gdGhpcyBm
-aWxlLiBDbGljayB0aGUgZWRpdCdzIGNoZWNrYm94IHRvIHRvZ2dsZSBpdHMgcmV2aWV3ZWQgc3RhdGUu
-IikpCmVsc2Ugcy5hcHBlbmRDaGlsZChhMC5jcmVhdGVUZXh0Tm9kZSgiIGVkaXRzIHdlcmUgbWFkZSB0
-byB0aGlzIGZpbGUuIENsaWNrIGFuIGVkaXQncyBjaGVja2JveCB0byB0b2dnbGUgaXRzIHJldmlld2Vk
-IHN0YXRlLiIpKQpmb3IodD1KLmE5KHUuUi5iKHQuaihhMiwiZWRpdHMiKSkpLHA9dS5hLG89dS5DLG49
-by5oKCJ+KDEpIiksbT11Lk0sbz1vLmQsbD11Lmgsaz11LmdCO3QucCgpOyl7aj10Lmd1KCkKaT1hMC5j
-cmVhdGVFbGVtZW50KCJwIikKaD1rLmIoYTEuYXBwZW5kQ2hpbGQoaSkpCmguY2xhc3NMaXN0LmFkZCgi
-ZWRpdCIpCmk9YTAuY3JlYXRlRWxlbWVudCgiaW5wdXQiKQpnPWwuYihoLmFwcGVuZENoaWxkKGkpKQpn
-LnNldEF0dHJpYnV0ZSgidHlwZSIsImNoZWNrYm94IikKZy5zZXRBdHRyaWJ1dGUoInRpdGxlIiwiQ2xp
-Y2sgdG8gbWFyayByZXZpZXdlZCIpCmcuc2V0QXR0cmlidXRlKGIsYikKaT1KLmFfKGopCmguYXBwZW5k
-Q2hpbGQoYTAuY3JlYXRlVGV4dE5vZGUoImxpbmUgIitILmIoaS5qKGosYSkpKyI6ICIrSC5iKGkuaihq
-LCJleHBsYW5hdGlvbiIpKSsiLiIpKQpmPWEwLmNyZWF0ZUVsZW1lbnQoImEiKQplPXAuYihoLmFwcGVu
-ZENoaWxkKGYpKQplLmNsYXNzTGlzdC5hZGQoImVkaXQtbGluayIpCmQ9SC54KGkuaihqLCJvZmZzZXQi
-KSkKZj1ILmIoZCkKZS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5hQihuZXcgVy5hcChlKSkuVigi
-b2Zmc2V0IiksZikKYz1ILngoaS5qKGosYSkpCmk9SC5iKGMpCmUuc2V0QXR0cmlidXRlKCJkYXRhLSIr
-bmV3IFcuYUIobmV3IFcuYXAoZSkpLlYoYSksaSkKZS5hcHBlbmRDaGlsZChhMC5jcmVhdGVUZXh0Tm9k
-ZSgiW3ZpZXddIikpCmk9bi5iKG5ldyBMLmZVKGQsYyxlKSkKbS5iKG51bGwpClcuYUMoZSwiY2xpY2si
-LGksITEsbyl9fSwKal86ZnVuY3Rpb24oYSl7dmFyIHQ9Ii5yZWdpb25zIixzPWRvY3VtZW50LHI9cy5x
-dWVyeVNlbGVjdG9yKHQpLHE9cy5xdWVyeVNlbGVjdG9yKCIuY29kZSIpCnM9Si5hXyhhKQpKLmhHKHIs
-SC5vKHMuaihhLCJyZWdpb25zIikpLCQuaHooKSkKSi5oRyhxLEgubyhzLmooYSwibmF2Q29udGVudCIp
-KSwkLmh6KCkpCkwubEgocy5qKGEsImVkaXRMaXN0IikpCkwubHEoKQpMLmhvKCIuY29kZSIpCkwuaG8o
-dCl9LApoeDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHI9TC5mcih3aW5kb3cubG9jYXRpb24uaHJl
-ZikscT1MLmZxKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQppZihyIT1udWxsKXt0PWRvY3VtZW50LmdldEVs
-ZW1lbnRCeUlkKCJvIitILmIocikpCmlmKHQhPW51bGwpSi5hbCh0KS5NKDAsInRhcmdldCIpfWlmKHEh
-PW51bGwpe3M9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILmIocSkpCmlmKHMhPW51bGwp
-Si5hbChzLnBhcmVudEVsZW1lbnQpLk0oMCwiaGlnaGxpZ2h0Iil9aWYoYT09d2luZG93LmxvY2F0aW9u
-LnBhdGhuYW1lKXtMLmlQKGIsYykKZC4kMCgpfWVsc2UgTC5odShhLGIsYyxkKX0sCmh3OmZ1bmN0aW9u
-KGEpe3ZhciB0PWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkscz10LmJvdHRvbSxyPXdpbmRvdy5pbm5l
-ckhlaWdodAppZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiBILmFqKHIpCmlmKHM+cilKLmhGKGEp
-CmVsc2UgaWYodC50b3A8MClKLmhGKGEpfSwKaVA6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKaWYoYSE9
-bnVsbCl7dD1kb2N1bWVudApzPXQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guYihhKSkKcj10LnF1ZXJ5U2Vs
-ZWN0b3IoIi5saW5lLSIrSC5iKGIpKQppZihzIT1udWxsKXtMLmh3KHMpCkouYWwocykuaygwLCJ0YXJn
-ZXQiKX1lbHNlIGlmKHIhPW51bGwpTC5odyhyKQppZihyIT1udWxsKUouYWwodS5oLmEoci5wYXJlbnRO
-b2RlKSkuaygwLCJoaWdobGlnaHQiKX1lbHNlIEwuaHcoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVu
-aXQtbmFtZSIpKX0sCmh1OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PXUuTgpXLmUyKEguYihhKSsiP2lu
-bGluZT10cnVlIixudWxsLFAuY08oWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29uOyBjaGFy
-c2V0PVVURi04Il0sdCx0KSkuYTQobmV3IEwuZkMoYixjLGEsZCksdS5QKS5hZChuZXcgTC5mRChhKSl9
-LApmUTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz13aW5kb3cubG9jYXRpb24scj1DLmEuQigocyYmQy5Z
-KS5nY20ocyksYSkrIj8iCmlmKGIhPW51bGwpcis9Im9mZnNldD0iK0guYihiKSsiJiIKaWYoYyE9bnVs
-bClyKz0ibGluZT0iK0guYihjKQpzPXdpbmRvdy5oaXN0b3J5CnQ9dS56CnMudG9TdHJpbmcKcy5wdXNo
-U3RhdGUobmV3IFAuZVcoW10sW10pLmFpKFAuZTkodCx0KSksIiIscil9LAppWjpmdW5jdGlvbihhLGIp
-e3ZhciB0LHMscj17fQpyLmE9YQphPUwubEUoYSkKci5hPWEKdD1kb2N1bWVudAp0LnF1ZXJ5U2VsZWN0
-b3IoIiN1bml0LW5hbWUiKS50ZXh0Q29udGVudD1hCnM9dS5oCkguZEwocyxzLCJUIiwicXVlcnlTZWxl
-Y3RvckFsbCIpCnQ9bmV3IFcuYXEodC5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBhbmVsIC5uYXYtbGlu
-ayIpLHUuUykKdC5BKHQsbmV3IEwuZlMocikpfSwKbHE6ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudCxz
-PXUuaApILmRMKHMscywiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0PW5ldyBXLmFxKHQucXVlcnlTZWxl
-Y3RvckFsbCgiLmNvZGUiKSx1LlMpCnQuQSh0LG5ldyBMLmZ4KCkpfSwKbGY6ZnVuY3Rpb24oYSl7dmFy
-IHQscz11LmguYShhLnBhcmVudE5vZGUpLnF1ZXJ5U2VsZWN0b3IoIjpzY29wZSA+IHVsIikscj1zLnN0
-eWxlLHE9IiIrQy5lLmEzKHMub2Zmc2V0SGVpZ2h0KSoyKyJweCIKci5tYXhIZWlnaHQ9cQpyPUouZFAo
-YSkKcT1yLiR0aQp0PXEuaCgifigxKSIpLmIobmV3IEwuZmoocyxhKSkKdS5NLmIobnVsbCkKVy5hQyhy
-LmEsci5iLHQsITEscS5kKX0sCmxvOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9ImhyZWYiCnUuVi5i
-KGEpCnQ9dS5oLmIoVy5pcyhhLmN1cnJlbnRUYXJnZXQpKQpzPUwuaUcodC5nZXRBdHRyaWJ1dGUocCkp
-CnI9TC5mcih0LmdldEF0dHJpYnV0ZShwKSkKcT1MLmZxKHQuZ2V0QXR0cmlidXRlKHApKQppZihyIT1u
-dWxsKUwuaHgocyxyLHEsbmV3IEwuZnMocyxyLHEpKQplbHNlIEwuaHgocyxudWxsLG51bGwsbmV3IEwu
-ZnQocykpCmEucHJldmVudERlZmF1bHQoKX0sCmxwOmZ1bmN0aW9uKGEpe3ZhciB0LHM9e30scj11Lmgu
-YShXLmlzKHUuVi5iKGEpLmN1cnJlbnRUYXJnZXQpKS5nZXRBdHRyaWJ1dGUoImhyZWYiKQpzLmE9cgpy
-PUwuaUcocikKcy5hPXIKdD11Lk4KVy5lMihyLCJQT1NUIixQLmNPKFsiQ29udGVudC1UeXBlIiwiYXBw
-bGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHQsdCkpLmE0KG5ldyBMLmZ1KCksdS5QKS5hZChu
-ZXcgTC5mdihzKSl9LApobzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPSJxdWVyeVNlbGVjdG9yQWxs
-IixvPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSksbj11LmgKby50b1N0cmluZwpILmRMKG4sbiwiVCIs
-cCkKdD11LlMKcz1uZXcgVy5hcShvLnF1ZXJ5U2VsZWN0b3JBbGwoIi5uYXYtbGluayIpLHQpCnMuQShz
-LG5ldyBMLmZsKCkpCkguZEwobixuLCJUIixwKQpyPW5ldyBXLmFxKG8ucXVlcnlTZWxlY3RvckFsbCgi
-LnJlZ2lvbiIpLHQpCnIuQShyLG5ldyBMLmZtKCkpCkguZEwobixuLCJUIixwKQpxPW5ldyBXLmFxKG8u
-cXVlcnlTZWxlY3RvckFsbCgiLnBvc3QtbGluayIpLHQpCnEuQShxLG5ldyBMLmZuKCkpfSwKajA6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaD0ibmFtZSIsZz1kb2N1bWVudCxm
-PWcuY3JlYXRlRWxlbWVudCgidWwiKSxlPWEuYXBwZW5kQ2hpbGQoZikKZm9yKGY9Si5hOSh1LlIuYihi
-KSksdD11Lmgscz11Lk07Zi5wKCk7KXtyPWYuZ3UoKQpxPWcuY3JlYXRlRWxlbWVudCgibGkiKQpwPXQu
-YihlLmFwcGVuZENoaWxkKHEpKQpxPUouYV8ocikKbz1KLkUocCkKaWYoSi5jcyhxLmoociwidHlwZSIp
-LCJkaXJlY3RvcnkiKSl7by5nQyhwKS5rKDAsImRpciIpCm89Zy5jcmVhdGVFbGVtZW50KCJzcGFuIikK
-bj10LmIocC5hcHBlbmRDaGlsZChvKSkKbz1KLkUobikKby5nQyhuKS5rKDAsImFycm93IikKby5zYWYo
-biwiJiN4MjVCQzsiKQpvPWcuY3JlYXRlRWxlbWVudCgic3BhbiIpCkouZFEodC5iKHAuYXBwZW5kQ2hp
-bGQobykpLCImI3gxRjRDMTsiKQpwLmFwcGVuZENoaWxkKGcuY3JlYXRlVGV4dE5vZGUoSC5vKHEuaihy
-LGgpKSkpCkwuajAocCxxLmoociwic3VidHJlZSIpKQpMLmxmKG4pfWVsc2V7by5zYWYocCwiJiN4MUY0
-QzQ7IikKbz1nLmNyZWF0ZUVsZW1lbnQoImEiKQptPXQuYihwLmFwcGVuZENoaWxkKG8pKQpvPUouRSht
-KQpvLmdDKG0pLmsoMCwibmF2LWxpbmsiKQpsPUgubyhxLmoociwicGF0aCIpKQptLnNldEF0dHJpYnV0
-ZSgiZGF0YS0iK25ldyBXLmFCKG5ldyBXLmFwKG0pKS5WKGgpLGwpCm0uc2V0QXR0cmlidXRlKCJocmVm
-IixILm8ocS5qKHIsImhyZWYiKSkpCm0uYXBwZW5kQ2hpbGQoZy5jcmVhdGVUZXh0Tm9kZShILm8ocS5q
-KHIsaCkpKSkKbz1vLmdhRyhtKQpsPW8uJHRpCmwuaCgifigxKSIpLmIoTC5mUCgpKQpzLmIobnVsbCkK
-Vy5hQyhvLmEsby5iLEwuZlAoKSwhMSxsLmQpCms9SC54KHEuaihyLCJlZGl0Q291bnQiKSkKaWYodHlw
-ZW9mIGshPT0ibnVtYmVyIilyZXR1cm4gay5hTSgpCmlmKGs+MCl7cT1nLmNyZWF0ZUVsZW1lbnQoInNw
-YW4iKQpqPXQuYihwLmFwcGVuZENoaWxkKHEpKQpKLmFsKGopLmsoMCwiZWRpdC1jb3VudCIpCmk9az09
-PTE/ImVkaXQiOiJlZGl0cyIKai5zZXRBdHRyaWJ1dGUoInRpdGxlIiwiIitrKyIgIitpKQpqLmFwcGVu
-ZENoaWxkKGcuY3JlYXRlVGV4dE5vZGUoQy5jLmkoaykpKX19fX0sCmxBOmZ1bmN0aW9uKCl7dmFyIHQ9
-Ii9fcHJldmlldy9uYXZpZ2F0aW9uVHJlZS5qc29uIixzPXUuTgpXLmUyKHQsbnVsbCxQLmNPKFsiQ29u
-dGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHMscykpLmE0KG5ldyBM
-LmZFKCksdS5QKS5hZChuZXcgTC5mRih0KSl9LApmSTpmdW5jdGlvbihhLGIpe3ZhciB0CndpbmRvdwp0
-PUguYihhKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3Io
-dCkKd2luZG93CnQ9SC5iKGIpCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29u
-c29sZS5lcnJvcih0KX0sCmxJOmZ1bmN0aW9uKGEwKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
-aCxnLGYsZSxkPSJsaW5rIixjPSJocmVmIixiPWRvY3VtZW50LGE9Yi5xdWVyeVNlbGVjdG9yKCIuZWRp
-dC1wYW5lbCAucGFuZWwtY29udGVudCIpCkouZFEoYSwiIikKdD1iLmNyZWF0ZUVsZW1lbnQoInAiKQpK
-LmFsKHQpLmsoMCwicmVnaW9uLWxvY2F0aW9uIikKcz1KLmFfKGEwKQp0LmFwcGVuZENoaWxkKGIuY3Jl
-YXRlVGV4dE5vZGUoSC5iKHMuaihhMCwicGF0aCIpKSsiICIpKQpyPWIuY3JlYXRlRWxlbWVudCgic3Bh
-biIpCnE9dS5oCnA9cS5iKHQuYXBwZW5kQ2hpbGQocikpCnAuYXBwZW5kQ2hpbGQoYi5jcmVhdGVUZXh0
-Tm9kZSgibGluZSAiK0guYihzLmooYTAsImxpbmUiKSkpKQpKLmFsKHApLmsoMCwibm93cmFwIikKYS5h
-cHBlbmRDaGlsZCh0KQpyPWIuY3JlYXRlRWxlbWVudCgicCIpCm89YS5hcHBlbmRDaGlsZChyKQpvLmFw
-cGVuZENoaWxkKGIuY3JlYXRlVGV4dE5vZGUoSC5vKHMuaihhMCwiZXhwbGFuYXRpb24iKSkpKQpuPUou
-YXQocy5qKGEwLCJkZXRhaWxzIikpCmlmKG49PT0wKW8uYXBwZW5kQ2hpbGQoYi5jcmVhdGVUZXh0Tm9k
-ZSgiLiIpKQplbHNle3I9bj09PTE/IiBmb3IgIitILmIobikrIiByZWFzb246IjoiIGZvciAiK0guYihu
-KSsiIHJlYXNvbnM6IgpvLmFwcGVuZENoaWxkKGIuY3JlYXRlVGV4dE5vZGUocikpCnI9Yi5jcmVhdGVF
-bGVtZW50KCJvbCIpCm09YS5hcHBlbmRDaGlsZChyKQpmb3Iocj1KLmE5KHUuUi5iKHMuaihhMCwiZGV0
-YWlscyIpKSksbD11LmE7ci5wKCk7KXtrPXIuZ3UoKQpqPWIuY3JlYXRlRWxlbWVudCgibGkiKQppPW0u
-YXBwZW5kQ2hpbGQoaikKaj1KLmFfKGspCmkuYXBwZW5kQ2hpbGQoYi5jcmVhdGVUZXh0Tm9kZShILm8o
-ai5qKGssImRlc2NyaXB0aW9uIikpKSkKaWYoai5qKGssZCkhPW51bGwpe2kuYXBwZW5kQ2hpbGQoYi5j
-cmVhdGVUZXh0Tm9kZSgiICgiKSkKaD1iLmNyZWF0ZUVsZW1lbnQoImEiKQpnPWwuYihpLmFwcGVuZENo
-aWxkKGgpKQpnLmFwcGVuZENoaWxkKGIuY3JlYXRlVGV4dE5vZGUoSC5vKEouZlcoai5qKGssZCksInRl
-eHQiKSkpKQpnLnNldEF0dHJpYnV0ZShjLEgubyhKLmZXKGouaihrLGQpLGMpKSkKZy5jbGFzc0xpc3Qu
-YWRkKCJuYXYtbGluayIpCmkuYXBwZW5kQ2hpbGQoYi5jcmVhdGVUZXh0Tm9kZSgiKSIpKX19fWlmKHMu
-aihhMCwiZWRpdHMiKSE9bnVsbClmb3Iocz1KLmE5KHUuUi5iKHMuaihhMCwiZWRpdHMiKSkpO3MucCgp
-Oyl7Zj1zLmd1KCkKcj1iLmNyZWF0ZUVsZW1lbnQoInAiKQplPXEuYihhLmFwcGVuZENoaWxkKHIpKQpy
-PWIuY3JlYXRlRWxlbWVudCgiYSIpCmc9cS5iKGUuYXBwZW5kQ2hpbGQocikpCnI9Si5hXyhmKQpnLmFw
-cGVuZENoaWxkKGIuY3JlYXRlVGV4dE5vZGUoSC5vKHIuaihmLCJ0ZXh0IikpKSkKZy5zZXRBdHRyaWJ1
-dGUoYyxILm8oci5qKGYsYykpKQpKLmFsKGcpLmsoMCwicG9zdC1saW5rIil9fSwKaU46ZnVuY3Rpb24o
-YSl7dmFyIHQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHM9YS5nZXRBdHRyaWJ1dGUoImRhdGEtIitu
-ZXcgVy5hQihuZXcgVy5hcChhKSkuVigib2Zmc2V0IikpLHI9dS5OClcuZTIoSC5iKHQpKyI/cmVnaW9u
-PXJlZ2lvbiZvZmZzZXQ9IitILmIocyksbnVsbCxQLmNPKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRp
-b24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHIscikpLmE0KG5ldyBMLmZHKCksdS5QKS5hZChuZXcgTC5m
-SCh0KSl9LAppVTpmdW5jdGlvbigpe3ZhciB0LHM9ZG9jdW1lbnQscj1zLnF1ZXJ5U2VsZWN0b3IoIi5u
-YXYtaW5uZXIiKSxxPXdpbmRvdy5pbm5lckhlaWdodCxwPXIuc3R5bGUsbz1ILmIocSkrInB4IgpwLmhl
-aWdodD1vCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuY3UoKQp0PXEvMi02CnA9cy5xdWVy
-eVNlbGVjdG9yKCIuZWRpdC1wYW5lbCIpLnN0eWxlCm89SC5iKHQpKyJweCIKcC5oZWlnaHQ9bwpzPXMu
-cXVlcnlTZWxlY3RvcigiLmVkaXQtbGlzdCIpLnN0eWxlCnA9SC5iKHQpKyJweCIKcy5oZWlnaHQ9cH0s
-CmlPOmZ1bmN0aW9uKCl7Qy5OLmFjKGRvY3VtZW50LCJET01Db250ZW50TG9hZGVkIixuZXcgTC5mSygp
-KQpDLm8uYWMod2luZG93LCJwb3BzdGF0ZSIsbmV3IEwuZkwoKSkKQy5vLmFjKHdpbmRvdywicmVzaXpl
-IixuZXcgTC5mTShuZXcgTC5jRChDLnQpKSkKQy5vLmFjKHdpbmRvdywic2Nyb2xsIixuZXcgTC5mTihu
-ZXcgTC5jRChDLnQpKSl9LApmVTpmdW5jdGlvbiBmVShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
-cy5jPWN9LApmVDpmdW5jdGlvbiBmVChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKZkM6ZnVuY3Rpb24g
-ZkMoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmZEOmZ1bmN0aW9u
-IGZEKGEpe3RoaXMuYT1hfSwKZlM6ZnVuY3Rpb24gZlMoYSl7dGhpcy5hPWF9LApmeDpmdW5jdGlvbiBm
-eCgpe30sCmZqOmZ1bmN0aW9uIGZqKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApmczpmdW5jdGlvbiBm
-cyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApmdDpmdW5jdGlvbiBmdChhKXt0aGlz
-LmE9YX0sCmZ1OmZ1bmN0aW9uIGZ1KCl7fSwKZnY6ZnVuY3Rpb24gZnYoYSl7dGhpcy5hPWF9LApmbDpm
-dW5jdGlvbiBmbCgpe30sCmZtOmZ1bmN0aW9uIGZtKCl7fSwKZms6ZnVuY3Rpb24gZmsoYSl7dGhpcy5h
-PWF9LApmbjpmdW5jdGlvbiBmbigpe30sCmZFOmZ1bmN0aW9uIGZFKCl7fSwKZkY6ZnVuY3Rpb24gZkYo
-YSl7dGhpcy5hPWF9LApmRzpmdW5jdGlvbiBmRygpe30sCmZIOmZ1bmN0aW9uIGZIKGEpe3RoaXMuYT1h
-fSwKZks6ZnVuY3Rpb24gZksoKXt9LApmSjpmdW5jdGlvbiBmSihhLGIsYyl7dGhpcy5hPWEKdGhpcy5i
-PWIKdGhpcy5jPWN9LApmTDpmdW5jdGlvbiBmTCgpe30sCmZNOmZ1bmN0aW9uIGZNKGEpe3RoaXMuYT1h
-fSwKZk46ZnVuY3Rpb24gZk4oYSl7dGhpcy5hPWF9LAplMDpmdW5jdGlvbiBlMCgpe30sCmNEOmZ1bmN0
-aW9uIGNEKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKY1k6ZnVuY3Rpb24gY1koKXt9fQp2YXIgdz1b
-QyxILEosUCxXLExdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIg
-JD17fQpILmgwLnByb3RvdHlwZT17fQpKLkkucHJvdG90eXBlPXsKRzpmdW5jdGlvbihhLGIpe3JldHVy
-biBhPT09Yn0sCmdxOmZ1bmN0aW9uKGEpe3JldHVybiBILmJWKGEpfSwKaTpmdW5jdGlvbihhKXtyZXR1
-cm4iSW5zdGFuY2Ugb2YgJyIrSC5iKEguZWYoYSkpKyInIn0sCmFoOmZ1bmN0aW9uKGEsYil7dS5vLmIo
-YikKdGhyb3cgSC5hKFAuaFUoYSxiLmdiZygpLGIuZ2JqKCksYi5nYmgoKSkpfX0KSi5jSC5wcm90b3R5
-cGU9ewppOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LApncTpmdW5jdGlvbihhKXtyZXR1cm4g
-YT81MTkwMTg6MjE4MTU5fSwKJGl6OjF9CkouYkoucHJvdG90eXBlPXsKRzpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBudWxsPT1ifSwKaTpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9LApncTpmdW5jdGlvbihhKXty
-ZXR1cm4gMH0sCmFoOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYnYoYSx1Lm8uYihiKSl9LAokaXA6
-MX0KSi5heS5wcm90b3R5cGU9ewpncTpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCmk6ZnVuY3Rpb24oYSl7
-cmV0dXJuIFN0cmluZyhhKX0sCiRpaFE6MX0KSi5jWi5wcm90b3R5cGU9e30KSi5iay5wcm90b3R5cGU9
-e30KSi5hZC5wcm90b3R5cGU9ewppOmZ1bmN0aW9uKGEpe3ZhciB0PWFbJC5mVigpXQppZih0PT1udWxs
-KXJldHVybiB0aGlzLmJ5KGEpCnJldHVybiJKYXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAiK0guYihKLmIy
-KHQpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJue2Z1bmM6MSxvcHQ6WywsLCwsLCwsLCwsLCwsLCxdfX0s
-CiRpYWI6MX0KSi5GLnByb3RvdHlwZT17Cms6ZnVuY3Rpb24oYSxiKXtILlooYSkuZC5iKGIpCmlmKCEh
-YS5maXhlZCRsZW5ndGgpSC5hayhQLk4oImFkZCIpKQphLnB1c2goYil9LApJOmZ1bmN0aW9uKGEsYil7
-dmFyIHQKSC5aKGEpLmgoImo8MT4iKS5iKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC5hayhQLk4oImFk
-ZEFsbCIpKQpmb3IodD1KLmE5KGIpO3QucCgpOylhLnB1c2godC5ndSgpKX0sCmFGOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdD1ILlooYSkKcmV0dXJuIG5ldyBILmE0KGEsdC5FKGMpLmgoIjEoMikiKS5iKGIpLHQu
-aCgiQDwxPiIpLkUoYykuaCgiYTQ8MSwyPiIpKX0sClQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPW5ldyBB
-cnJheShhLmxlbmd0aCkKcy5maXhlZCRsZW5ndGg9QXJyYXkKZm9yKHQ9MDt0PGEubGVuZ3RoOysrdCl0
-aGlzLmwocyx0LEguYihhW3RdKSkKcmV0dXJuIHMuam9pbihiKX0sCmNjOmZ1bmN0aW9uKGEsYixjLGQp
-e3ZhciB0LHMscgpkLmIoYikKSC5aKGEpLkUoZCkuaCgiMSgxLDIpIikuYihjKQp0PWEubGVuZ3RoCmZv
-cihzPWIscj0wO3I8dDsrK3Ipe3M9Yy4kMihzLGFbcl0pCmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmEo
-UC5hdihhKSl9cmV0dXJuIHN9LApPOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1
-cm4gSC5pKGEsYikKcmV0dXJuIGFbYl19LApidTpmdW5jdGlvbihhLGIsYyl7aWYoYjwwfHxiPmEubGVu
-Z3RoKXRocm93IEguYShQLkwoYiwwLGEubGVuZ3RoLCJzdGFydCIsbnVsbCkpCmlmKGM8Ynx8Yz5hLmxl
-bmd0aCl0aHJvdyBILmEoUC5MKGMsYixhLmxlbmd0aCwiZW5kIixudWxsKSkKaWYoYj09PWMpcmV0dXJu
-IEgubihbXSxILlooYSkpCnJldHVybiBILm4oYS5zbGljZShiLGMpLEguWihhKSl9LApnYWc6ZnVuY3Rp
-b24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD4wKXJldHVybiBhW3QtMV0KdGhyb3cgSC5hKEguaFAoKSl9
-LApiODpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC5aKGEpLmgoInooMSkiKS5iKGIpCnQ9YS5sZW5ndGgK
-Zm9yKHM9MDtzPHQ7KytzKXtpZihILmRLKGIuJDEoYVtzXSkpKXJldHVybiEwCmlmKGEubGVuZ3RoIT09
-dCl0aHJvdyBILmEoUC5hdihhKSl9cmV0dXJuITF9LAp3OmZ1bmN0aW9uKGEsYil7dmFyIHQKZm9yKHQ9
-MDt0PGEubGVuZ3RoOysrdClpZihKLmNzKGFbdF0sYikpcmV0dXJuITAKcmV0dXJuITF9LAppOmZ1bmN0
-aW9uKGEpe3JldHVybiBQLmU2KGEsIlsiLCJdIil9LApnRjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEou
-YUYoYSxhLmxlbmd0aCxILlooYSkuaCgiYUY8MT4iKSl9LApncTpmdW5jdGlvbihhKXtyZXR1cm4gSC5i
-VihhKX0sCmdtOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnNtOmZ1bmN0aW9uKGEsYil7aWYo
-ISFhLmZpeGVkJGxlbmd0aClILmFrKFAuTigic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5hKFAu
-TChiLDAsbnVsbCwibmV3TGVuZ3RoIixudWxsKSkKYS5sZW5ndGg9Yn0sCmo6ZnVuY3Rpb24oYSxiKXtI
-LngoYikKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmEoSC5iMShhLGIpKQpyZXR1cm4gYVtiXX0s
-Cmw6ZnVuY3Rpb24oYSxiLGMpe0guWihhKS5kLmIoYykKaWYoISFhLmltbXV0YWJsZSRsaXN0KUguYWso
-UC5OKCJpbmRleGVkIHNldCIpKQppZihiPj1hLmxlbmd0aHx8ITEpdGhyb3cgSC5hKEguYjEoYSxiKSkK
-YVtiXT1jfSwKJGlqOjEsCiRpbToxfQpKLmU3LnByb3RvdHlwZT17fQpKLmFGLnByb3RvdHlwZT17Cmd1
-OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCnA6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj1zLmEs
-cT1yLmxlbmd0aAppZihzLmIhPT1xKXRocm93IEguYShILmNyKHIpKQp0PXMuYwppZih0Pj1xKXtzLnNh
-WChudWxsKQpyZXR1cm4hMX1zLnNhWChyW3RdKTsrK3MuYwpyZXR1cm4hMH0sCnNhWDpmdW5jdGlvbihh
-KXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlSOjF9CkouYmEucHJvdG90eXBlPXsKYm86ZnVuY3Rp
-b24oYSl7dmFyIHQKaWYoYT49LTIxNDc0ODM2NDgmJmE8PTIxNDc0ODM2NDcpcmV0dXJuIGF8MAppZihp
-c0Zpbml0ZShhKSl7dD1hPDA/TWF0aC5jZWlsKGEpOk1hdGguZmxvb3IoYSkKcmV0dXJuIHQrMH10aHJv
-dyBILmEoUC5OKCIiK2ErIi50b0ludCgpIikpfSwKYTM6ZnVuY3Rpb24oYSl7aWYoYT4wKXtpZihhIT09
-MS8wKXJldHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1hdGgucm91bmQo
-MC1hKQp0aHJvdyBILmEoUC5OKCIiK2ErIi5yb3VuZCgpIikpfSwKYTU6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzLHIscQppZihiPDJ8fGI+MzYpdGhyb3cgSC5hKFAuTChiLDIsMzYsInJhZGl4IixudWxsKSkKdD1h
-LnRvU3RyaW5nKGIpCmlmKEMuYS52KHQsdC5sZW5ndGgtMSkhPT00MSlyZXR1cm4gdApzPS9eKFtcZGEt
-el0rKSg/OlwuKFtcZGEtel0rKSk/XChlXCsoXGQrKVwpJC8uZXhlYyh0KQppZihzPT1udWxsKUguYWso
-UC5OKCJVbmV4cGVjdGVkIHRvU3RyaW5nIHJlc3VsdDogIit0KSkKcj1zLmxlbmd0aAppZigxPj1yKXJl
-dHVybiBILmkocywxKQp0PXNbMV0KaWYoMz49cilyZXR1cm4gSC5pKHMsMykKcT0rc1szXQpyPXNbMl0K
-aWYociE9bnVsbCl7dCs9cgpxLT1yLmxlbmd0aH1yZXR1cm4gdCtDLmEuYU4oIjAiLHEpfSwKaTpmdW5j
-dGlvbihhKXtpZihhPT09MCYmMS9hPDApcmV0dXJuIi0wLjAiCmVsc2UgcmV0dXJuIiIrYX0sCmdxOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YXwwCmlmKGE9PT1wKXJldHVybiA1MzY4NzA5MTEmcAp0PU1h
-dGguYWJzKGEpCnM9TWF0aC5sb2codCkvMC42OTMxNDcxODA1NTk5NDUzfDAKcj1NYXRoLnBvdygyLHMp
-CnE9dDwxP3QvcjpyL3QKcmV0dXJuIDUzNjg3MDkxMSYoKHEqOTAwNzE5OTI1NDc0MDk5MnwwKSsocSoz
-NTQyMjQzMTgxMTc2NTIxfDApKSo1OTkxOTcrcyoxMjU5fSwKQjpmdW5jdGlvbihhLGIpe2lmKHR5cGVv
-ZiBiIT0ibnVtYmVyIil0aHJvdyBILmEoSC5hcyhiKSkKcmV0dXJuIGErYn0sCmFrOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQ9YSViCmlmKHQ9PT0wKXJldHVybiAwCmlmKHQ+MClyZXR1cm4gdAppZihiPDApcmV0dXJu
-IHQtYgplbHNlIHJldHVybiB0K2J9LAphYjpmdW5jdGlvbihhLGIpe3JldHVybihhfDApPT09YT9hL2J8
-MDp0aGlzLmJZKGEsYil9LApiWTpmdW5jdGlvbihhLGIpe3ZhciB0PWEvYgppZih0Pj0tMjE0NzQ4MzY0
-OCYmdDw9MjE0NzQ4MzY0NylyZXR1cm4gdHwwCmlmKHQ+MCl7aWYodCE9PTEvMClyZXR1cm4gTWF0aC5m
-bG9vcih0KX1lbHNlIGlmKHQ+LTEvMClyZXR1cm4gTWF0aC5jZWlsKHQpCnRocm93IEguYShQLk4oIlJl
-c3VsdCBvZiB0cnVuY2F0aW5nIGRpdmlzaW9uIGlzICIrSC5iKHQpKyI6ICIrSC5iKGEpKyIgfi8gIiti
-KSl9LApaOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT4wKXQ9dGhpcy5iMyhhLGIpCmVsc2V7dD1iPjMx
-PzMxOmIKdD1hPj50Pj4+MH1yZXR1cm4gdH0sCmJYOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEgu
-YShILmFzKGIpKQpyZXR1cm4gdGhpcy5iMyhhLGIpfSwKYjM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj4z
-MT8wOmE+Pj5ifSwKUjpmdW5jdGlvbihhLGIpe3JldHVybihhfGIpPj4+MH0sCiRpVDoxLAokaVU6MX0K
-Si5iSS5wcm90b3R5cGU9eyRpZjoxfQpKLmNJLnByb3RvdHlwZT17fQpKLmF4LnByb3RvdHlwZT17CnY6
-ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5hKEguYjEoYSxiKSkKaWYoYj49YS5sZW5ndGgpSC5h
-ayhILmIxKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LAp0OmZ1bmN0aW9uKGEsYil7aWYoYj49
-YS5sZW5ndGgpdGhyb3cgSC5hKEguYjEoYSxiKSkKcmV0dXJuIGEuY2hhckNvZGVBdChiKX0sCkI6ZnVu
-Y3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyIpdGhyb3cgSC5hKFAuZlgoYixudWxsLG51bGwp
-KQpyZXR1cm4gYStifSwKYTA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwpjPVAuYVYoYixjLGEubGVu
-Z3RoKQp0PWEuc3Vic3RyaW5nKDAsYikKcz1hLnN1YnN0cmluZyhjKQpyZXR1cm4gdCtkK3N9LApTOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdAppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5hKFAuTChjLDAsYS5s
-ZW5ndGgsbnVsbCxudWxsKSkKdD1jK2IubGVuZ3RoCmlmKHQ+YS5sZW5ndGgpcmV0dXJuITEKcmV0dXJu
-IGI9PT1hLnN1YnN0cmluZyhjLHQpfSwKSDpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlMoYSxiLDAp
-fSwKbjpmdW5jdGlvbihhLGIsYyl7aWYoIUguZEooYikpSC5hayhILmFzKGIpKQppZihjPT1udWxsKWM9
-YS5sZW5ndGgKaWYodHlwZW9mIGIhPT0ibnVtYmVyIilyZXR1cm4gYi5EKCkKaWYoYjwwKXRocm93IEgu
-YShQLmVnKGIsbnVsbCkpCmlmKGI+Yyl0aHJvdyBILmEoUC5lZyhiLG51bGwpKQppZihjPmEubGVuZ3Ro
-KXRocm93IEguYShQLmVnKGMsbnVsbCkpCnJldHVybiBhLnN1YnN0cmluZyhiLGMpfSwKVTpmdW5jdGlv
-bihhLGIpe3JldHVybiB0aGlzLm4oYSxiLG51bGwpfSwKY3I6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudG9M
-b3dlckNhc2UoKX0sCmNzOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEudHJpbSgpLHA9cS5sZW5ndGgK
-aWYocD09PTApcmV0dXJuIHEKaWYodGhpcy50KHEsMCk9PT0xMzMpe3Q9Si5qSyhxLDEpCmlmKHQ9PT1w
-KXJldHVybiIifWVsc2UgdD0wCnM9cC0xCnI9dGhpcy52KHEscyk9PT0xMzM/Si5qTChxLHMpOnAKaWYo
-dD09PTAmJnI9PT1wKXJldHVybiBxCnJldHVybiBxLnN1YnN0cmluZyh0LHIpfSwKYU46ZnVuY3Rpb24o
-YSxiKXt2YXIgdCxzCmlmKDA+PWIpcmV0dXJuIiIKaWYoYj09PTF8fGEubGVuZ3RoPT09MClyZXR1cm4g
-YQppZihiIT09Yj4+PjApdGhyb3cgSC5hKEMuSykKZm9yKHQ9YSxzPSIiOyEwOyl7aWYoKGImMSk9PT0x
-KXM9dCtzCmI9Yj4+PjEKaWYoYj09PTApYnJlYWsKdCs9dH1yZXR1cm4gc30sCmFlOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdAppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5hKFAuTChjLDAsYS5sZW5ndGgsbnVs
-bCxudWxsKSkKdD1hLmluZGV4T2YoYixjKQpyZXR1cm4gdH0sCmJmOmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IHRoaXMuYWUoYSxiLDApfSwKaTpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmdxOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTAscj0wO3I8dDsrK3Ipe3M9NTM2ODcwOTExJnMrYS5jaGFy
-Q29kZUF0KHIpCnM9NTM2ODcwOTExJnMrKCg1MjQyODcmcyk8PDEwKQpzXj1zPj42fXM9NTM2ODcwOTEx
-JnMrKCg2NzEwODg2MyZzKTw8MykKc149cz4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8
-PDE1KX0sCmdtOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCmo6ZnVuY3Rpb24oYSxiKXtILngo
-YikKaWYoYj49YS5sZW5ndGh8fCExKXRocm93IEguYShILmIxKGEsYikpCnJldHVybiBhW2JdfSwKJGlj
-WDoxLAokaWM6MX0KSC5jeS5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxl
-bmd0aH0sCmo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy5hLnYodGhpcy5hLEgueChiKSl9fQpILmJDLnBy
-b3RvdHlwZT17fQpILmFlLnByb3RvdHlwZT17CmdGOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMKcmV0dXJu
-IG5ldyBILmFRKHQsdC5nbSh0KSxILnYodCkuaCgiYVE8YWUuRT4iKSl9LAphajpmdW5jdGlvbihhLGIp
-e3JldHVybiB0aGlzLmJ4KDAsSC52KHRoaXMpLmgoInooYWUuRSkiKS5iKGIpKX19CkguYVEucHJvdG90
-eXBlPXsKZ3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKcDpmdW5jdGlvbigpe3ZhciB0LHM9dGhp
-cyxyPXMuYSxxPUouYV8ocikscD1xLmdtKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5hKFAuYXYocikpCnQ9
-cy5jCmlmKHQ+PXApe3Muc2FRKG51bGwpCnJldHVybiExfXMuc2FRKHEuTyhyLHQpKTsrK3MuYwpyZXR1
-cm4hMH0sCnNhUTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlSOjF9CkguYTQu
-cHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIEouYXQodGhpcy5hKX0sCk86ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gdGhpcy5iLiQxKEouam0odGhpcy5hLGIpKX19CkguYVkucHJvdG90eXBlPXsKZ0Y6
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmNfKEouYTkodGhpcy5hKSx0aGlzLmIsdGhpcy4kdGkuaCgi
-Y188MT4iKSl9fQpILmNfLnByb3RvdHlwZT17CnA6ZnVuY3Rpb24oKXt2YXIgdCxzCmZvcih0PXRoaXMu
-YSxzPXRoaXMuYjt0LnAoKTspaWYoSC5kSyhzLiQxKHQuZ3UoKSkpKXJldHVybiEwCnJldHVybiExfSwK
-Z3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLmd1KCl9fQpILlYucHJvdG90eXBlPXt9CkguYVgucHJv
-dG90eXBlPXsKbDpmdW5jdGlvbihhLGIsYyl7SC52KHRoaXMpLmgoImFYLkUiKS5iKGMpCnRocm93IEgu
-YShQLk4oIkNhbm5vdCBtb2RpZnkgYW4gdW5tb2RpZmlhYmxlIGxpc3QiKSl9fQpILmJsLnByb3RvdHlw
-ZT17fQpILmJpLnByb3RvdHlwZT17CmdxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuX2hhc2hDb2RlCmlm
-KHQhPW51bGwpcmV0dXJuIHQKdD01MzY4NzA5MTEmNjY0NTk3KkouYnYodGhpcy5hKQp0aGlzLl9oYXNo
-Q29kZT10CnJldHVybiB0fSwKaTpmdW5jdGlvbihhKXtyZXR1cm4nU3ltYm9sKCInK0guYih0aGlzLmEp
-KyciKSd9LApHOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5j
-ZW9mIEguYmkmJnRoaXMuYT09Yi5hfSwKJGlhNjoxfQpILmJ6LnByb3RvdHlwZT17fQpILmJ5LnByb3Rv
-dHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuaDModGhpcyl9LApsOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgdD1ILnYodGhpcykKdC5kLmIoYikKdC5jaFsxXS5iKGMpCnJldHVybiBILmpDKCl9LAokaXk6MX0K
-SC5hSi5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKYV86ZnVuY3Rpb24o
-YSl7aWYoIl9fcHJvdG9fXyI9PT1hKXJldHVybiExCnJldHVybiB0aGlzLmIuaGFzT3duUHJvcGVydHko
-YSl9LApqOmZ1bmN0aW9uKGEsYil7aWYoIXRoaXMuYV8oYikpcmV0dXJuIG51bGwKcmV0dXJuIHRoaXMu
-YVkoYil9LAphWTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5iW0gubyhhKV19LApBOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyLHEscD1ILnYodGhpcykKcC5oKCJ+KDEsMikiKS5iKGIpCnQ9dGhpcy5jCmZvcihz
-PXQubGVuZ3RoLHA9cC5jaFsxXSxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxwLmIodGhpcy5hWShx
-KSkpfX19CkguY0oucHJvdG90eXBlPXsKZ2JnOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hCnJldHVybiB0
-fSwKZ2JqOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzCmlmKHAuYz09PTEpcmV0dXJuIEMudwp0
-PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5mCmlmKHM9PT0wKXJldHVybiBDLncKcj1bXQpmb3Io
-cT0wO3E8czsrK3Epe2lmKHE+PXQubGVuZ3RoKXJldHVybiBILmkodCxxKQpyLnB1c2godFtxXSl9ci5m
-aXhlZCRsZW5ndGg9QXJyYXkKci5pbW11dGFibGUkbGlzdD1BcnJheQpyZXR1cm4gcn0sCmdiaDpmdW5j
-dGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuQQp0PWwu
-ZQpzPXQubGVuZ3RoCnI9bC5kCnE9ci5sZW5ndGgtcy1sLmYKaWYocz09PTApcmV0dXJuIEMuQQpwPW5l
-dyBILmFuKHUuQikKZm9yKG89MDtvPHM7KytvKXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5pKHQsbykK
-bj10W29dCm09cStvCmlmKG08MHx8bT49ci5sZW5ndGgpcmV0dXJuIEguaShyLG0pCnAubCgwLG5ldyBI
-LmJpKG4pLHJbbV0pfXJldHVybiBuZXcgSC5ieihwLHUuRCl9LAokaWhPOjF9CkguZWUucHJvdG90eXBl
-PXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdApILm8oYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5iKGEp
-CkMuYi5rKHRoaXMuYixhKQpDLmIuayh0aGlzLmMsYik7Kyt0LmF9LAokUzoxOH0KSC5lai5wcm90b3R5
-cGU9ewpMOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9bmV3IFJlZ0V4cChyLmEpLmV4ZWMoYSkK
-aWYocT09bnVsbClyZXR1cm4gbnVsbAp0PU9iamVjdC5jcmVhdGUobnVsbCkKcz1yLmIKaWYocyE9PS0x
-KXQuYXJndW1lbnRzPXFbcysxXQpzPXIuYwppZihzIT09LTEpdC5hcmd1bWVudHNFeHByPXFbcysxXQpz
-PXIuZAppZihzIT09LTEpdC5leHByPXFbcysxXQpzPXIuZQppZihzIT09LTEpdC5tZXRob2Q9cVtzKzFd
-CnM9ci5mCmlmKHMhPT0tMSl0LnJlY2VpdmVyPXFbcysxXQpyZXR1cm4gdH19CkguY1YucHJvdG90eXBl
-PXsKaTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9k
-RXJyb3I6ICIrSC5iKHRoaXMuYSkKcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZv
-dW5kOiAnIit0KyInIG9uIG51bGwifX0KSC5jTC5wcm90b3R5cGU9ewppOmZ1bmN0aW9uKGEpe3ZhciB0
-LHM9dGhpcyxyPSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIscT1zLmIKaWYo
-cT09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5iKHMuYSkKdD1zLmMKaWYodD09bnVs
-bClyZXR1cm4gcitxKyInICgiK0guYihzLmEpKyIpIgpyZXR1cm4gcitxKyInIG9uICciK3QrIicgKCIr
-SC5iKHMuYSkrIikifX0KSC5kYS5wcm90b3R5cGU9ewppOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpy
-ZXR1cm4gdC5sZW5ndGg9PT0wPyJFcnJvciI6IkVycm9yOiAiK3R9fQpILmZSLnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe2lmKHUuYlUuYyhhKSlpZihhLiR0aHJvd25Kc0Vycm9yPT1udWxsKWEuJHRocm93
-bkpzRXJyb3I9dGhpcy5hCnJldHVybiBhfSwKJFM6NH0KSC5jZy5wcm90b3R5cGU9ewppOmZ1bmN0aW9u
-KGEpe3ZhciB0LHM9dGhpcy5iCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10aGlzLmEKdD1zIT09bnVsbCYm
-dHlwZW9mIHM9PT0ib2JqZWN0Ij9zLnN0YWNrOm51bGwKcmV0dXJuIHRoaXMuYj10PT1udWxsPyIiOnR9
-LAokaWFnOjF9CkguYUkucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmNvbnN0cnVj
-dG9yLHM9dD09bnVsbD9udWxsOnQubmFtZQpyZXR1cm4iQ2xvc3VyZSAnIitILmlZKHM9PW51bGw/InVu
-a25vd24iOnMpKyInIn0sCiRpYWI6MSwKZ2N0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LAokQzoiJDEi
-LAokUjoxLAokRDpudWxsfQpILmQ4LnByb3RvdHlwZT17fQpILmQzLnByb3RvdHlwZT17Cmk6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy4kc3RhdGljX25hbWUKaWYodD09bnVsbClyZXR1cm4iQ2xvc3VyZSBvZiB1
-bmtub3duIHN0YXRpYyBtZXRob2QiCnJldHVybiJDbG9zdXJlICciK0guaVkodCkrIicifX0KSC5iNi5w
-cm90b3R5cGU9ewpHOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlm
-KHQ9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguYjYpKXJldHVybiExCnJldHVybiB0LmE9
-PT1iLmEmJnQuYj09PWIuYiYmdC5jPT09Yi5jfSwKZ3E6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmMK
-aWYocz09bnVsbCl0PUguYlYodGhpcy5hKQplbHNlIHQ9dHlwZW9mIHMhPT0ib2JqZWN0Ij9KLmJ2KHMp
-OkguYlYocykKcmV0dXJuKHReSC5iVih0aGlzLmIpKT4+PjB9LAppOmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYwppZih0PT1udWxsKXQ9dGhpcy5hCnJldHVybiJDbG9zdXJlICciK0guYih0aGlzLmQpKyInIG9m
-ICIrKCJJbnN0YW5jZSBvZiAnIitILmIoSC5lZih0KSkrIiciKX19CkguZDAucHJvdG90eXBlPXsKaTpm
-dW5jdGlvbihhKXtyZXR1cm4iUnVudGltZUVycm9yOiAiK0guYih0aGlzLmEpfX0KSC5kZy5wcm90b3R5
-cGU9ewppOmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AuYU0odGhpcy5hKX19
-CkguYW4ucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCmdKOmZ1bmN0aW9u
-KCl7cmV0dXJuIG5ldyBILmFQKHRoaXMsSC52KHRoaXMpLmgoImFQPDE+IikpfSwKYV86ZnVuY3Rpb24o
+LG89IiMiLG49dS5nYyxtPVAuZEgoMjIsbmV3IFAucTMoKSwhMCxuKSxsPW5ldyBQLnlJKG0pLGs9bmV3
+IFAuYzYoKSxqPW5ldyBQLnFkKCksaT1uLmIobC4kMigwLDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxz
+LDE0KQprLiQzKGksciwzNCkKay4kMyhpLHEsMykKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9
+bi5iKGwuJDIoMTQsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHMsMTUpCmsuJDMoaSxyLDM0KQprLiQz
+KGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE1LDIyNSkpCmsu
+JDMoaSx0LDEpCmsuJDMoaSwiJSIsMjI1KQprLiQzKGksciwzNCkKay4kMyhpLHEsOSkKay4kMyhpLHAs
+MTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMSwyMjUpKQprLiQzKGksdCwxKQprLiQzKGksciwz
+NCkKay4kMyhpLHEsMTApCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDIsMjM1
+KSkKay4kMyhpLHQsMTM5KQprLiQzKGkscSwxMzEpCmsuJDMoaSxzLDE0NikKay4kMyhpLHAsMTcyKQpr
+LiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMywyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHEsNjgpCmsu
+JDMoaSxzLDE4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig0LDIyOSkpCmsu
+JDMoaSx0LDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHIsMTAyKQprLiQzKGksIkAiLDY4KQprLiQz
+KGksIlsiLDIzMikKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIo
+bC4kMig1LDIyOSkpCmsuJDMoaSx0LDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHIsMTAyKQprLiQz
+KGksIkAiLDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihs
+LiQyKDYsMjMxKSkKai4kMyhpLCIxOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4KQprLiQz
+KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig3LDIzMSkpCmouJDMoaSwiMDkiLDcpCmsu
+JDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmsuJDMo
+bi5iKGwuJDIoOCw4KSksIl0iLDUpCmk9bi5iKGwuJDIoOSwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhp
+LHMsMTYpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIo
+MTYsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE3KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3
+MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE3LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscSw5
+KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigxMCwyMzUpKQprLiQzKGksdCwx
+MSkKay4kMyhpLHMsMTgpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9
+bi5iKGwuJDIoMTgsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE5KQprLiQzKGkscSwyMzQpCmsu
+JDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE5LDIzNSkpCmsuJDMoaSx0LDExKQpr
+LiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDExLDIzNSkp
+CmsuJDMoaSx0LDExKQprLiQzKGkscSwxMCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5i
+KGwuJDIoMTIsMjM2KSkKay4kMyhpLHQsMTIpCmsuJDMoaSxwLDEyKQprLiQzKGksbywyMDUpCmk9bi5i
+KGwuJDIoMTMsMjM3KSkKay4kMyhpLHQsMTMpCmsuJDMoaSxwLDEzKQpqLiQzKG4uYihsLiQyKDIwLDI0
+NSkpLCJheiIsMjEpCmw9bi5iKGwuJDIoMjEsMjQ1KSkKai4kMyhsLCJheiIsMjEpCmouJDMobCwiMDki
+LDIxKQprLiQzKGwsIistLiIsMjEpCnJldHVybiBtfSwKVUI6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIg
+dCxzLHIscSxwLG89JC52WigpCmZvcih0PUouclkoYSkscz1iO3M8YzsrK3Mpe2lmKGQ8MHx8ZD49by5s
+ZW5ndGgpcmV0dXJuIEguT0gobyxkKQpyPW9bZF0KcT10LlcoYSxzKV45NgppZihxPjk1KXE9MzEKaWYo
+cT49ci5sZW5ndGgpcmV0dXJuIEguT0gocixxKQpwPXJbcV0KZD1wJjMxCkMuTm0uWShlLHA+Pj41LHMp
+fXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0
+aW9uIGEyKCl7fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0
+aW9uIENQKCl7fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0s
+Cm46ZnVuY3Rpb24gbigpe30sCnU6ZnVuY3Rpb24gdShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8u
+Yj1iCl8uYz1jCl8uZD1kfSwKYko6ZnVuY3Rpb24gYkooYSxiLGMsZCxlLGYpe3ZhciBfPXRoaXMKXy5l
+PWEKXy5mPWIKXy5hPWMKXy5iPWQKXy5jPWUKXy5kPWZ9LAplWTpmdW5jdGlvbiBlWShhLGIsYyxkLGUp
+e3ZhciBfPXRoaXMKXy5mPWEKXy5hPWIKXy5iPWMKXy5jPWQKXy5kPWV9LAptcDpmdW5jdGlvbiBtcChh
+LGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKdWI6ZnVuY3Rpb24gdWIo
+YSl7dGhpcy5hPWF9LApkczpmdW5jdGlvbiBkcyhhKXt0aGlzLmE9YX0sCmxqOmZ1bmN0aW9uIGxqKGEp
+e3RoaXMuYT1hfSwKVVY6ZnVuY3Rpb24gVVYoYSl7dGhpcy5hPWF9LAprNTpmdW5jdGlvbiBrNSgpe30s
+CktZOmZ1bmN0aW9uIEtZKCl7fSwKYzpmdW5jdGlvbiBjKGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24g
+Q0QoYSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBhRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
+cy5jPWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCktOOmZ1bmN0aW9uIEtOKCl7fSwKY1g6ZnVuY3Rpb24g
+Y1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpNOmZ1bmN0aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24g
+WjAoKXt9LApjODpmdW5jdGlvbiBjOCgpe30sCkZLOmZ1bmN0aW9uIEZLKCl7fSwKazpmdW5jdGlvbiBr
+KCl7fSwKT2Q6ZnVuY3Rpb24gT2QoKXt9LAppYjpmdW5jdGlvbiBpYigpe30sCnh1OmZ1bmN0aW9uIHh1
+KCl7fSwKR3o6ZnVuY3Rpb24gR3ooKXt9LApxVTpmdW5jdGlvbiBxVSgpe30sClJuOmZ1bmN0aW9uIFJu
+KGEpe3RoaXMuYT1hfSwKR0Q6ZnVuY3Rpb24gR0QoKXt9LApuMTpmdW5jdGlvbiBuMShhKXt0aGlzLmE9
+YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMoYSl7dGhpcy5hPWF9
+LAp0cDpmdW5jdGlvbiB0cChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVuY3Rpb24gRG4oYSxi
+LGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zgpf
+LnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVsbH0sCmUxOmZ1bmN0aW9uIGUxKGEsYil7dGhpcy5hPWEKdGhp
+cy5iPWJ9LApOWTpmdW5jdGlvbiBOWShhKXt0aGlzLmE9YX0sClJaOmZ1bmN0aW9uIFJaKCl7fSwKUEU6
+ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rpb24g
+cTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6
+ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApx
+ZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
+ZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24gaUoo
+KXt9LApsUjpmdW5jdGlvbiBsUihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKamc6ZnVuY3Rpb24gamco
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LApBczpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKaEY6ZnVu
+Y3Rpb24gaEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKSC54ZChiKQp1LmouYihk
+KQppZihILm9UKGIpKXt0PVtjXQpDLk5tLkZWKHQsZCkKZD10fXM9dS56CnI9UC5DSChKLk0xKGQsUC53
+MCgpLHMpLCEwLHMpCnUuWi5iKGEpCnJldHVybiBQLndZKEguRWsoYSxyLG51bGwpKX0sCkRtOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdAp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90
+b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2
+YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHQpe0guUnUodCl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihh
+LGIpe2lmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2Jd
+CnJldHVybiBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmci
+fHx0eXBlb2YgYT09Im51bWJlciJ8fEgubChhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNCly
+ZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEKaWYodS5rLmMoYSkpcmV0dXJuIGEKaWYoYSBpbnN0
+YW5jZW9mIFAuaVApcmV0dXJuIEgubzIoYSkKaWYodS5aLmMoYSkpcmV0dXJuIFAuaEUoYSwiJGRhcnRf
+anNGdW5jdGlvbiIsbmV3IFAuUEMoKSkKcmV0dXJuIFAuaEUoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcg
+UC5ZbSgkLmtJKCkpKX0sCmhFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVs
+bCl7dD1jLiQxKGEpClAuRG0oYSxiLHQpfXJldHVybiB0fSwKTDc6ZnVuY3Rpb24oYSl7dmFyIHQscwpp
+ZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9
+PSJib29sZWFuIilyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0
+dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZ1LmsuYyhhKSlyZXR1cm4gYQplbHNlIGlm
+KGEgaW5zdGFuY2VvZiBEYXRlKXt0PUguU2MoYS5nZXRUaW1lKCkpCmlmKE1hdGguYWJzKHQpPD04NjRl
+MTMpcz0hMQplbHNlIHM9ITAKaWYocylILnZoKFAueFkoIkRhdGVUaW1lIGlzIG91dHNpZGUgdmFsaWQg
+cmFuZ2U6ICIrdCkpCnJldHVybiBuZXcgUC5pUCh0LCExKX1lbHNlIGlmKGEuY29uc3RydWN0b3I9PT0k
+LmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVuY3Rpb24oYSl7aWYodHlw
+ZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLncoKSxuZXcgUC5OeigpKQppZihhIGluc3Rh
+bmNlb2YgQXJyYXkpcmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAuUVMoKSkKcmV0dXJuIFAuaVEoYSwk
+LlI4KCksbmV3IFAubnAoKSl9LAppUTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5PbShhLGIpCmlmKHQ9
+PW51bGx8fCEoYSBpbnN0YW5jZW9mIE9iamVjdCkpe3Q9Yy4kMShhKQpQLkRtKGEsYix0KX1yZXR1cm4g
+dH0sClBDOmZ1bmN0aW9uIFBDKCl7fSwKWW06ZnVuY3Rpb24gWW0oYSl7dGhpcy5hPWF9LApOejpmdW5j
+dGlvbiBOeigpe30sClFTOmZ1bmN0aW9uIFFTKCl7fSwKbnA6ZnVuY3Rpb24gbnAoKXt9LApFNDpmdW5j
+dGlvbiBFNChhKXt0aGlzLmE9YX0sCnI3OmZ1bmN0aW9uIHI3KGEpe3RoaXMuYT1hfSwKVHo6ZnVuY3Rp
+b24gVHooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY286ZnVuY3Rpb24gY28oKXt9LApuZDpmdW5j
+dGlvbiBuZCgpe30sCktlOmZ1bmN0aW9uIEtlKGEpe3RoaXMuYT1hfSwKZDU6ZnVuY3Rpb24gZDUoKXt9
+LApuNjpmdW5jdGlvbiBuNigpe319LFc9ewpVOTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9ZG9jdW1lbnQu
+Ym9keSxzPSh0JiZDLlJZKS5yNih0LGEsYixjKQpzLnRvU3RyaW5nCnQ9dS5hYwp0PW5ldyBILlU1KG5l
+dyBXLmU3KHMpLHQuQygiYTIobEQuRSkiKS5iKG5ldyBXLkN2KCkpLHQuQygiVTU8bEQuRT4iKSkKcmV0
+dXJuIHUuaC5iKHQuZ3I4KHQpKX0sCnJTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0iZWxlbWVudCB0YWcg
+dW5hdmFpbGFibGUiCnRyeXt0PUouUkUoYSkKaWYodHlwZW9mIHQuZ25zKGEpPT0ic3RyaW5nIilyPXQu
+Z25zKGEpfWNhdGNoKHMpe0guUnUocyl9cmV0dXJuIHJ9LApxRDpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
+cyxyLHE9bmV3IFAudnMoJC5YMyx1LmFvKSxwPW5ldyBQLlpmKHEsdS5FKSxvPW5ldyBYTUxIdHRwUmVx
+dWVzdCgpCkMuRHQuZW8obyxiPT1udWxsPyJHRVQiOmIsYSwhMCkKYy5LKDAsbmV3IFcuYlUobykpCnQ9
+dS5hbgpzPXQuYihuZXcgVy5oSChvLHApKQp1Lk0uYihudWxsKQpyPXUucApXLkpFKG8sImxvYWQiLHMs
+ITEscikKVy5KRShvLCJlcnJvciIsdC5iKHAuZ1lKKCkpLCExLHIpCm8uc2VuZCgpCnJldHVybiBxfSwK
+QzA6ZnVuY3Rpb24oYSxiKXthPTUzNjg3MDkxMSZhK2IKYT01MzY4NzA5MTEmYSsoKDUyNDI4NyZhKTw8
+MTApCnJldHVybiBhXmE+Pj42fSwKckU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9Vy5DMChXLkMwKFcu
+QzAoVy5DMCgwLGEpLGIpLGMpLGQpLHM9NTM2ODcwOTExJnQrKCg2NzEwODg2MyZ0KTw8MykKc149cz4+
+PjExCnJldHVybiA1MzY4NzA5MTEmcysoKDE2MzgzJnMpPDwxNSl9LApKRTpmdW5jdGlvbihhLGIsYyxk
+LGUpe3ZhciB0PVcuYUYobmV3IFcudk4oYyksdS5CKQppZih0IT1udWxsJiYhMClKLmRaKGEsYix0LCEx
+KQpyZXR1cm4gbmV3IFcueEMoYSxiLHQsITEsZS5DKCJ4QzwwPiIpKX0sClR3OmZ1bmN0aW9uKGEpe3Zh
+ciB0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSxzPW5ldyBXLm1rKHQsd2luZG93LmxvY2F0aW9u
+KQpzPW5ldyBXLkpRKHMpCnMuQ1koYSkKcmV0dXJuIHN9LAp5VzpmdW5jdGlvbihhLGIsYyxkKXt1Lmgu
+YihhKQpILnkoYikKSC55KGMpCnUuTy5iKGQpCnJldHVybiEwfSwKUVc6ZnVuY3Rpb24oYSxiLGMsZCl7
+dmFyIHQscyxyCnUuaC5iKGEpCkgueShiKQpILnkoYykKdD11Lk8uYihkKS5hCnM9dC5hCnMuaHJlZj1j
+CnI9cy5ob3N0bmFtZQp0PXQuYgppZighKHI9PXQuaG9zdG5hbWUmJnMucG9ydD09dC5wb3J0JiZzLnBy
+b3RvY29sPT10LnByb3RvY29sKSlpZihyPT09IiIpaWYocy5wb3J0PT09IiIpe3Q9cy5wcm90b2NvbAp0
+PXQ9PT0iOiJ8fHQ9PT0iIn1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMApyZXR1cm4gdH0sCkJs
+OmZ1bmN0aW9uKCl7dmFyIHQ9dS5OLHM9UC50TShDLlF4LHQpLHI9dS5kRy5iKG5ldyBXLklBKCkpLHE9
+SC5WTShbIlRFTVBMQVRFIl0sdS5zKQp0PW5ldyBXLmN0KHMsUC5Mcyh0KSxQLkxzKHQpLFAuTHModCks
+bnVsbCkKdC5DWShudWxsLG5ldyBILkE4KEMuUXgscix1LmR2KSxxLG51bGwpCnJldHVybiB0fSwKcWM6
+ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZigicG9zdE1lc3NhZ2UiIGlu
+IGEpe3Q9Vy5QMShhKQpyZXR1cm4gdH1lbHNlIHJldHVybiB1LmFTLmIoYSl9LApQMTpmdW5jdGlvbihh
+KXtpZihhPT09d2luZG93KXJldHVybiB1LmNpLmIoYSkKZWxzZSByZXR1cm4gbmV3IFcuZFcoKX0sCmFG
+OmZ1bmN0aW9uKGEsYil7dmFyIHQ9JC5YMwppZih0PT09Qy5OVSlyZXR1cm4gYQpyZXR1cm4gdC5QeShh
+LGIpfSwKcUU6ZnVuY3Rpb24gcUUoKXt9LApHaDpmdW5jdGlvbiBHaCgpe30sCmZZOmZ1bmN0aW9uIGZZ
+KCl7fSwKbkI6ZnVuY3Rpb24gbkIoKXt9LApBejpmdW5jdGlvbiBBeigpe30sClFQOmZ1bmN0aW9uIFFQ
+KCl7fSwKbng6ZnVuY3Rpb24gbngoKXt9LApvSjpmdW5jdGlvbiBvSigpe30sCmlkOmZ1bmN0aW9uIGlk
+KCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9LApOaDpmdW5jdGlvbiBOaCgpe30sCklCOmZ1bmN0aW9uIElC
+KCl7fSwKbjc6ZnVuY3Rpb24gbjcoKXt9LAp3ejpmdW5jdGlvbiB3eihhLGIpe3RoaXMuYT1hCnRoaXMu
+JHRpPWJ9LApjdjpmdW5jdGlvbiBjdigpe30sCkN2OmZ1bmN0aW9uIEN2KCl7fSwKZWE6ZnVuY3Rpb24g
+ZWEoKXt9LApEMDpmdW5jdGlvbiBEMCgpe30sClQ1OmZ1bmN0aW9uIFQ1KCl7fSwKaDQ6ZnVuY3Rpb24g
+aDQoKXt9LApicjpmdW5jdGlvbiBicigpe30sClZiOmZ1bmN0aW9uIFZiKCl7fSwKTzc6ZnVuY3Rpb24g
+TzcoKXt9LApiVTpmdW5jdGlvbiBiVShhKXt0aGlzLmE9YX0sCmhIOmZ1bmN0aW9uIGhIKGEsYil7dGhp
+cy5hPWEKdGhpcy5iPWJ9LAp3YTpmdW5jdGlvbiB3YSgpe30sClNnOmZ1bmN0aW9uIFNnKCl7fSwKdTg6
+ZnVuY3Rpb24gdTgoKXt9LApBajpmdW5jdGlvbiBBaigpe30sCmU3OmZ1bmN0aW9uIGU3KGEpe3RoaXMu
+YT1hfSwKdUg6ZnVuY3Rpb24gdUgoKXt9LApCSDpmdW5jdGlvbiBCSCgpe30sCmV3OmZ1bmN0aW9uIGV3
+KCl7fSwKbHA6ZnVuY3Rpb24gbHAoKXt9LApUYjpmdW5jdGlvbiBUYigpe30sCkl2OmZ1bmN0aW9uIEl2
+KCl7fSwKQlQ6ZnVuY3Rpb24gQlQoKXt9LAp5WTpmdW5jdGlvbiB5WSgpe30sCnc2OmZ1bmN0aW9uIHc2
+KCl7fSwKSzU6ZnVuY3Rpb24gSzUoKXt9LApDbTpmdW5jdGlvbiBDbSgpe30sCkNROmZ1bmN0aW9uIENR
+KCl7fSwKdzQ6ZnVuY3Rpb24gdzQoKXt9LApyaDpmdW5jdGlvbiByaCgpe30sCkQ5OmZ1bmN0aW9uIEQ5
+KCl7fSwKaTc6ZnVuY3Rpb24gaTcoYSl7dGhpcy5hPWF9LApTeTpmdW5jdGlvbiBTeShhKXt0aGlzLmE9
+YX0sCktTOmZ1bmN0aW9uIEtTKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBMzpmdW5jdGlvbiBBMyhh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSTQ6ZnVuY3Rpb24gSTQoYSl7dGhpcy5hPWF9LApGazpmdW5j
+dGlvbiBGayhhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApSTzpmdW5jdGlvbiBSTyhhLGIsYyxkKXt2
+YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LApDcTpmdW5jdGlvbiBDcShhLGIsYyxk
+KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LAp4QzpmdW5jdGlvbiB4QyhhLGIs
+YyxkLGUpe3ZhciBfPXRoaXMKXy5iPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZOOmZ1bmN0
+aW9uIHZOKGEpe3RoaXMuYT1hfSwKSlE6ZnVuY3Rpb24gSlEoYSl7dGhpcy5hPWF9LApHbTpmdW5jdGlv
+biBHbSgpe30sCnZEOmZ1bmN0aW9uIHZEKGEpe3RoaXMuYT1hfSwKVXY6ZnVuY3Rpb24gVXYoYSl7dGhp
+cy5hPWF9LApFZzpmdW5jdGlvbiBFZyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApt
+NjpmdW5jdGlvbiBtNigpe30sCkVvOmZ1bmN0aW9uIEVvKCl7fSwKV2s6ZnVuY3Rpb24gV2soKXt9LApj
+dDpmdW5jdGlvbiBjdChhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5lPWEKXy5hPWIKXy5iPWMKXy5jPWQK
+Xy5kPWV9LApJQTpmdW5jdGlvbiBJQSgpe30sCk93OmZ1bmN0aW9uIE93KCl7fSwKVzk6ZnVuY3Rpb24g
+VzkoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPS0xCl8uZD1udWxsCl8uJHRpPWN9LApk
+VzpmdW5jdGlvbiBkVygpe30sCmtGOmZ1bmN0aW9uIGtGKCl7fSwKbWs6ZnVuY3Rpb24gbWsoYSxiKXt0
+aGlzLmE9YQp0aGlzLmI9Yn0sCktvOmZ1bmN0aW9uIEtvKGEpe3RoaXMuYT1hfSwKZm06ZnVuY3Rpb24g
+Zm0oYSl7dGhpcy5hPWF9LApMZTpmdW5jdGlvbiBMZSgpe30sCks3OmZ1bmN0aW9uIEs3KCl7fSwKckI6
+ZnVuY3Rpb24gckIoKXt9LApYVzpmdW5jdGlvbiBYVygpe30sCm9hOmZ1bmN0aW9uIG9hKCl7fX0sVD17
+R1Y6ZnVuY3Rpb24gR1YoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQsIkRPTUNv
+bnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBMLkwoKSl9
+LApHNjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwib2Zmc2V0IikKcmV0dXJuIHQ9
+PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LAphSzpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgp
+LnEoMCwibGluZSIpCnJldHVybiB0PT1udWxsP251bGw6SC5IcCh0LG51bGwpfSwKaE86ZnVuY3Rpb24o
+YSl7aWYoMD49YS5sZW5ndGgpcmV0dXJuIEguT0goYSwwKQppZihhWzBdIT09Ii8iKXJldHVybiBKLlQw
+KGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQpKyIvIitILmQoYSkKZWxz
+ZSByZXR1cm4gYX0sCkVuOmZ1bmN0aW9uKGEpe3ZhciB0PUouYmIoZG9jdW1lbnQucXVlcnlTZWxlY3Rv
+cigiLnJvb3QiKS50ZXh0Q29udGVudCwiLyIpCmlmKEMueEIubihhLHQpKXJldHVybiBDLnhCLkcoYSx0
+Lmxlbmd0aCkKZWxzZSByZXR1cm4gYX0sClNyOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0s
+bCxrLGosaSxoLGcsZixlLGQ9ZG9jdW1lbnQsYz1kLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0LWxpc3QgLnBh
+bmVsLWNvbnRlbnQiKQpKLmw1KGMsIiIpCnQ9ZC5jcmVhdGVFbGVtZW50KCJwIikKcz1jLmFwcGVuZENo
+aWxkKHQpCnQ9Si5VNihhKQpyPUguU2ModC5xKGEsImVkaXRDb3VudCIpKQppZihyPT09MClzLmFwcGVu
+ZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoSC5kKHIpKyIgcHJvcG9zZWQgZWRpdHMiKSkKZWxzZSBzLmFw
+cGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoSC5kKHIpKyIgcHJvcG9zZWQgIitMLkx4KHIsImVkaXQi
+KSsiOiIpKQpxPWQuY3JlYXRlRWxlbWVudCgidWwiKQpwPXUuaApvPXAuYihjLmFwcGVuZENoaWxkKHEp
+KQpmb3IodD1KLklUKHUuUi5iKHQucShhLCJlZGl0cyIpKSkscT11LmEsbj11LkMsbT1uLkMoIn4oMSki
+KSxsPXUuTSxuPW4uZDt0LkYoKTspe2s9dC5nbCgpCmo9ZC5jcmVhdGVFbGVtZW50KCJsaSIpCmk9cC5i
+KG8uYXBwZW5kQ2hpbGQoaikpCkouZFIoaSkuaSgwLCJlZGl0IikKaj1kLmNyZWF0ZUVsZW1lbnQoImEi
+KQpoPXEuYihpLmFwcGVuZENoaWxkKGopKQpoLmNsYXNzTGlzdC5hZGQoImVkaXQtbGluayIpCmo9Si5V
+NihrKQpnPUguU2Moai5xKGssIm9mZnNldCIpKQpmPUguZChnKQpoLnNldEF0dHJpYnV0ZSgiZGF0YS0i
+K25ldyBXLlN5KG5ldyBXLmk3KGgpKS5PKCJvZmZzZXQiKSxmKQplPUguU2Moai5xKGssImxpbmUiKSkK
+Zj1ILmQoZSkKaC5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhoKSkuTygibGlu
+ZSIpLGYpCmguYXBwZW5kQ2hpbGQoZC5jcmVhdGVUZXh0Tm9kZSgibGluZSAiK0guZChlKSkpCmY9bS5i
+KG5ldyBMLmVTKGcsZSxoKSkKbC5iKG51bGwpClcuSkUoaCwiY2xpY2siLGYsITEsbikKaS5hcHBlbmRD
+aGlsZChkLmNyZWF0ZVRleHROb2RlKCI6ICIrSC5kKGoucShrLCJleHBsYW5hdGlvbiIpKSkpfX0sCkJF
+OmZ1bmN0aW9uKGEpe3ZhciB0PSIucmVnaW9ucyIscz1kb2N1bWVudCxyPXMucXVlcnlTZWxlY3Rvcih0
+KSxxPXMucXVlcnlTZWxlY3RvcigiLmNvZGUiKQpzPUouVTYoYSkKSi50SChyLEgueShzLnEoYSwicmVn
+aW9ucyIpKSwkLktHKCkpCkoudEgocSxILnkocy5xKGEsIm5hdkNvbnRlbnQiKSksJC5LRygpKQpMLlNy
+KHMucShhLCJlZGl0TGlzdCIpKQpMLnZVKCkKTC55WCgiLmNvZGUiKQpMLnlYKHQpfSwKYWY6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHQscyxyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHE9TC5hSyh3aW5k
+b3cubG9jYXRpb24uaHJlZikKaWYociE9bnVsbCl7dD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIr
+SC5kKHIpKQppZih0IT1udWxsKUouZFIodCkuUigwLCJ0YXJnZXQiKX1pZihxIT1udWxsKXtzPWRvY3Vt
+ZW50LnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5kKHEpKQppZihzIT1udWxsKUouZFIocy5wYXJlbnRF
+bGVtZW50KS5SKDAsImhpZ2hsaWdodCIpfWlmKGE9PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSl7TC5m
+RyhiLGMpCmQuJDAoKX1lbHNlIEwuRzcoYSxiLGMsZCl9LApxTzpmdW5jdGlvbihhKXt2YXIgdD1hLmdl
+dEJvdW5kaW5nQ2xpZW50UmVjdCgpLHM9dC5ib3R0b20scj13aW5kb3cuaW5uZXJIZWlnaHQKaWYodHlw
+ZW9mIHIhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShyKQppZihzPnIpSi5kaChhKQplbHNlIGlmKHQudG9w
+PDApSi5kaChhKX0sCmZHOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmlmKGEhPW51bGwpe3Q9ZG9jdW1l
+bnQKcz10LmdldEVsZW1lbnRCeUlkKCJvIitILmQoYSkpCnI9dC5xdWVyeVNlbGVjdG9yKCIubGluZS0i
+K0guZChiKSkKaWYocyE9bnVsbCl7TC5xTyhzKQpKLmRSKHMpLmkoMCwidGFyZ2V0Iil9ZWxzZSBpZihy
+IT1udWxsKUwucU8oci5wYXJlbnRFbGVtZW50KQppZihyIT1udWxsKUouZFIodS5oLmEoci5wYXJlbnRO
+b2RlKSkuaSgwLCJoaWdobGlnaHQiKX1lbHNlIEwucU8oZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVu
+aXQtbmFtZSIpKX0sCkc3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PUouemwoYSwiPyIpP2ErIiZpbmxp
+bmU9dHJ1ZSI6YSsiP2lubGluZT10cnVlIixzPXUuTgpXLnFEKHQsbnVsbCxQLkVGKFsiQ29udGVudC1U
+eXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHMscykpLlc3KG5ldyBMLnl1KGIs
+YyxhLGQpLHUuUCkuT0EobmV3IEwuekQoYSkpfSwKRnI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9d2lu
+ZG93LmxvY2F0aW9uLHI9Qy54Qi5oKChzJiZDLkV4KS5nRHIocyksYSkrIj8iCmlmKGIhPW51bGwpcis9
+Im9mZnNldD0iK0guZChiKSsiJiIKaWYoYyE9bnVsbClyKz0ibGluZT0iK0guZChjKQpzPXdpbmRvdy5o
+aXN0b3J5CnQ9dS56CnMudG9TdHJpbmcKcy5wdXNoU3RhdGUobmV3IFAuQmYoW10sW10pLlB2KFAuRmwo
+dCx0KSksIiIscil9LApCWDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj17fQpyLmE9YQphPUwuRW4oYSkK
+ci5hPWEKdD1kb2N1bWVudAp0LnF1ZXJ5U2VsZWN0b3IoIiN1bml0LW5hbWUiKS50ZXh0Q29udGVudD1h
+CnM9dS5oCkguRGgocyxzLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNl
+bGVjdG9yQWxsKCIubmF2LXBhbmVsIC5uYXYtbGluayIpLHUuUykKdC5LKHQsbmV3IEwuVlMocikpfSwK
+dlU6ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudCxzPXUuaApILkRoKHMscywiVCIsInF1ZXJ5U2VsZWN0
+b3JBbGwiKQp0PW5ldyBXLnd6KHQucXVlcnlTZWxlY3RvckFsbCgiLmNvZGUiKSx1LlMpCnQuSyh0LG5l
+dyBMLkdIKCkpfSwKa3o6ZnVuY3Rpb24oYSl7dmFyIHQscz11LmguYShhLnBhcmVudE5vZGUpLnF1ZXJ5
+U2VsZWN0b3IoIjpzY29wZSA+IHVsIikscj1zLnN0eWxlLHE9IiIrQy5DRC56UShzLm9mZnNldEhlaWdo
+dCkqMisicHgiCnIubWF4SGVpZ2h0PXEKcj1KLnFGKGEpCnE9ci4kdGkKdD1xLkMoIn4oMSkiKS5iKG5l
+dyBMLld4KHMsYSkpCnUuTS5iKG51bGwpClcuSkUoci5hLHIuYix0LCExLHEuZCl9LAp0MjpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscSxwPSJocmVmIgp1LlYuYihhKQp0PXUuaC5iKFcucWMoYS5jdXJyZW50VGFy
+Z2V0KSkKcz1MLmhPKHQuZ2V0QXR0cmlidXRlKHApKQpyPUwuRzYodC5nZXRBdHRyaWJ1dGUocCkpCnE9
+TC5hSyh0LmdldEF0dHJpYnV0ZShwKSkKaWYociE9bnVsbClMLmFmKHMscixxLG5ldyBMLm5UKHMscixx
+KSkKZWxzZSBMLmFmKHMsbnVsbCxudWxsLG5ldyBMLkJaKHMpKQphLnByZXZlbnREZWZhdWx0KCl9LAp1
+bTpmdW5jdGlvbihhKXt2YXIgdCxzPXt9LHI9dS5oLmEoVy5xYyh1LlYuYihhKS5jdXJyZW50VGFyZ2V0
+KSkuZ2V0QXR0cmlidXRlKCJocmVmIikKcy5hPXIKcj1MLmhPKHIpCnMuYT1yCnQ9dS5OClcucUQociwi
+UE9TVCIsUC5FRihbIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgi
+XSx0LHQpKS5XNyhuZXcgTC5GUSgpLHUuUCkuT0EobmV3IEwudFkocykpfSwKeVg6ZnVuY3Rpb24oYSl7
+dmFyIHQscyxyLHEscD0icXVlcnlTZWxlY3RvckFsbCIsbz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGEp
+LG49dS5oCm8udG9TdHJpbmcKSC5EaChuLG4sIlQiLHApCnQ9dS5TCnM9bmV3IFcud3ooby5xdWVyeVNl
+bGVjdG9yQWxsKCIubmF2LWxpbmsiKSx0KQpzLksocyxuZXcgTC5BTygpKQpILkRoKG4sbiwiVCIscCkK
+cj1uZXcgVy53eihvLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSx0KQpyLksocixuZXcgTC5Ibygp
+KQpILkRoKG4sbiwiVCIscCkKcT1uZXcgVy53eihvLnF1ZXJ5U2VsZWN0b3JBbGwoIi5wb3N0LWxpbmsi
+KSx0KQpxLksocSxuZXcgTC5JQygpKX0sCnRYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4s
+bSxsLGssaj0ibmFtZSIsaT1kb2N1bWVudCxoPWkuY3JlYXRlRWxlbWVudCgidWwiKSxnPXUuaCxmPWcu
+YihhLmFwcGVuZENoaWxkKGgpKQpmb3IoaD1KLklUKHUuUi5iKGIpKSx0PXUuTTtoLkYoKTspe3M9aC5n
+bCgpCnI9aS5jcmVhdGVFbGVtZW50KCJsaSIpCnE9Zy5iKGYuYXBwZW5kQ2hpbGQocikpCnI9Si5VNihz
+KQpwPUouUkUocSkKaWYoSi5STShyLnEocywidHlwZSIpLCJkaXJlY3RvcnkiKSl7cC5nRChxKS5pKDAs
+ImRpciIpCnA9aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKbz1nLmIocS5hcHBlbmRDaGlsZChwKSkKcD1K
+LlJFKG8pCnAuZ0QobykuaSgwLCJhcnJvdyIpCnAuc2hmKG8sIiYjeDI1QkM7IikKcD1pLmNyZWF0ZUVs
+ZW1lbnQoInNwYW4iKQpKLmw1KGcuYihxLmFwcGVuZENoaWxkKHApKSwiJiN4MUY0QzE7IikKcS5hcHBl
+bmRDaGlsZChpLmNyZWF0ZVRleHROb2RlKEgueShyLnEocyxqKSkpKQpMLnRYKHEsci5xKHMsInN1YnRy
+ZWUiKSkKTC5reihvKX1lbHNle3Auc2hmKHEsIiYjeDFGNEM0OyIpCnA9aS5jcmVhdGVFbGVtZW50KCJh
+IikKbj1nLmIocS5hcHBlbmRDaGlsZChwKSkKcD1KLlJFKG4pCnAuZ0QobikuaSgwLCJuYXYtbGluayIp
+Cm09SC55KHIucShzLCJwYXRoIikpCm4uc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcu
+aTcobikpLk8oaiksbSkKbi5zZXRBdHRyaWJ1dGUoImhyZWYiLEgueShyLnEocywiaHJlZiIpKSkKbi5h
+cHBlbmRDaGlsZChpLmNyZWF0ZVRleHROb2RlKEgueShyLnEocyxqKSkpKQpwPXAuZ1ZsKG4pCm09cC4k
+dGkKbS5DKCJ+KDEpIikuYihMLlhOKCkpCnQuYihudWxsKQpXLkpFKHAuYSxwLmIsTC5YTigpLCExLG0u
+ZCkKbD1ILlNjKHIucShzLCJlZGl0Q291bnQiKSkKaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4g
+bC5vcygpCmlmKGw+MCl7cj1pLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQprPWcuYihxLmFwcGVuZENoaWxk
+KHIpKQpKLmRSKGspLmkoMCwiZWRpdC1jb3VudCIpCnI9IiIrbCsiICIKaWYobD09PTEpcD0iZWRpdCIK
+ZWxzZSBwPSJlZGl0cyIKay5zZXRBdHRyaWJ1dGUoInRpdGxlIixyK3ApCmsuYXBwZW5kQ2hpbGQoaS5j
+cmVhdGVUZXh0Tm9kZShDLmpuLncobCkpKX19fX0sCkdlOmZ1bmN0aW9uKCl7dmFyIHQ9Ii9fcHJldmll
+dy9uYXZpZ2F0aW9uVHJlZS5qc29uIixzPXUuTgpXLnFEKHQsbnVsbCxQLkVGKFsiQ29udGVudC1UeXBl
+IiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHMscykpLlc3KG5ldyBMLlRXKCksdS5Q
+KS5PQShuZXcgTC54cih0KSl9LApxSjpmdW5jdGlvbihhLGIpe3ZhciB0CndpbmRvdwppZih0eXBlb2Yg
+Y29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IoYSkKd2luZG93CnQ9SC5kKGIp
+CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS5lcnJvcih0KX0sCkFG
+OmZ1bmN0aW9uKGE0KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhPW51
+bGwsYTA9ImxpbmsiLGExPSJocmVmIixhMj1kb2N1bWVudCxhMz1hMi5xdWVyeVNlbGVjdG9yKCIuZWRp
+dC1wYW5lbCAucGFuZWwtY29udGVudCIpCkoubDUoYTMsIiIpCnQ9Si5VNihhNCkKcz1ILnkodC5xKGE0
+LCJwYXRoIikpCnI9JC5uVSgpCnE9ci50TShzKQpwPUgueSh0LnEoYTQsImV4cGxhbmF0aW9uIikpCm89
+ci5IUChzLEouVDAoYTIucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpCm49SC5TYyh0
+LnEoYTQsImxpbmUiKSkKcj1hMi5jcmVhdGVFbGVtZW50KCJwIikKbT11LmgKbS5iKGEzLmFwcGVuZENo
+aWxkKHIpKS5hcHBlbmRDaGlsZChhMi5jcmVhdGVUZXh0Tm9kZShILmQocCkrIiBhdCAiK0guZChvKSsi
+OiIrSC5kKG4pKyIuIikpCmlmKEguU2MoSi5IbSh0LnEoYTQsImRldGFpbHMiKSkpIT09MCl7cj1hMi5j
+cmVhdGVFbGVtZW50KCJwIikKci50ZXh0Q29udGVudD0iRWRpdCByYXRpb25hbGU6IgphMy5hcHBlbmRD
+aGlsZChyKQpyPWEyLmNyZWF0ZUVsZW1lbnQoInVsIikKbD1tLmIoYTMuYXBwZW5kQ2hpbGQocikpCmZv
+cihyPUouSVQodS5SLmIodC5xKGE0LCJkZXRhaWxzIikpKSxrPXUuYTtyLkYoKTspe2o9ci5nbCgpCmk9
+YTIuY3JlYXRlRWxlbWVudCgibGkiKQpoPWwuYXBwZW5kQ2hpbGQoaSkKaT1KLlU2KGopCmguYXBwZW5k
+Q2hpbGQoYTIuY3JlYXRlVGV4dE5vZGUoSC55KGkucShqLCJkZXNjcmlwdGlvbiIpKSkpCmlmKGkucShq
+LGEwKSE9bnVsbCl7Zz1ILlNjKEoudzIoaS5xKGosYTApLCJsaW5lIikpCmguYXBwZW5kQ2hpbGQoYTIu
+Y3JlYXRlVGV4dE5vZGUoIiAoIikpCmY9YTIuY3JlYXRlRWxlbWVudCgiYSIpCmU9ay5iKGguYXBwZW5k
+Q2hpbGQoZikpCmUuYXBwZW5kQ2hpbGQoYTIuY3JlYXRlVGV4dE5vZGUoSC5kKEoudzIoaS5xKGosYTAp
+LCJ0ZXh0IikpKyI6IitILmQoZykpKQpkPUgueShKLncyKGkucShqLGEwKSxhMSkpCmk9JC5uVSgpCmUu
+c2V0QXR0cmlidXRlKGExLGkubzUoaS5xNygwLHEsZCxhLGEsYSxhLGEsYSkpKQplLmNsYXNzTGlzdC5h
+ZGQoIm5hdi1saW5rIikKaC5hcHBlbmRDaGlsZChhMi5jcmVhdGVUZXh0Tm9kZSgiKSIpKX19fWlmKHQu
+cShhNCwiZWRpdHMiKSE9bnVsbClmb3IodD1KLklUKHUuUi5iKHQucShhNCwiZWRpdHMiKSkpO3QuRigp
+Oyl7Yz10LmdsKCkKcj1hMi5jcmVhdGVFbGVtZW50KCJwIikKYj1tLmIoYTMuYXBwZW5kQ2hpbGQocikp
+CnI9YTIuY3JlYXRlRWxlbWVudCgiYSIpCmU9bS5iKGIuYXBwZW5kQ2hpbGQocikpCnI9Si5VNihjKQpl
+LmFwcGVuZENoaWxkKGEyLmNyZWF0ZVRleHROb2RlKEgueShyLnEoYywidGV4dCIpKSkpCmUuc2V0QXR0
+cmlidXRlKGExLEgueShyLnEoYyxhMSkpKQpKLmRSKGUpLmkoMCwicG9zdC1saW5rIil9fSwKTVY6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHM9YS5nZXRBdHRyaWJ1dGUoImRh
+dGEtIituZXcgVy5TeShuZXcgVy5pNyhhKSkuTygib2Zmc2V0IikpLHI9dS5OClcucUQoSC5kKHQpKyI/
+cmVnaW9uPXJlZ2lvbiZvZmZzZXQ9IitILmQocyksbnVsbCxQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBw
+bGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHIscikpLlc3KG5ldyBMLlF2KCksdS5QKS5PQShu
+ZXcgTC5uNCh0KSl9LApMeDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PT0xKXQ9YgplbHNlIHQ9Yisi
+cyIKcmV0dXJuIHR9LAplOmZ1bmN0aW9uIGUoKXt9LApWVzpmdW5jdGlvbiBWVyhhLGIsYyl7dGhpcy5h
+PWEKdGhpcy5iPWIKdGhpcy5jPWN9LApMOmZ1bmN0aW9uIEwoKXt9LAplUzpmdW5jdGlvbiBlUyhhLGIs
+Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApGaDpmdW5jdGlvbiBGaChhLGIpe3RoaXMuYT1h
+CnRoaXMuYj1ifSwKeXU6ZnVuY3Rpb24geXUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
+LmM9YwpfLmQ9ZH0sCnpEOmZ1bmN0aW9uIHpEKGEpe3RoaXMuYT1hfSwKVlM6ZnVuY3Rpb24gVlMoYSl7
+dGhpcy5hPWF9LApHSDpmdW5jdGlvbiBHSCgpe30sCld4OmZ1bmN0aW9uIFd4KGEsYil7dGhpcy5hPWEK
+dGhpcy5iPWJ9LApuVDpmdW5jdGlvbiBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApCWjpmdW5jdGlvbiBCWihhKXt0aGlzLmE9YX0sCkZROmZ1bmN0aW9uIEZRKCl7fSwKdFk6ZnVuY3Rp
+b24gdFkoYSl7dGhpcy5hPWF9LApBTzpmdW5jdGlvbiBBTygpe30sCkhvOmZ1bmN0aW9uIEhvKCl7fSwK
+eHo6ZnVuY3Rpb24geHooYSl7dGhpcy5hPWF9LApJQzpmdW5jdGlvbiBJQygpe30sClRXOmZ1bmN0aW9u
+IFRXKCl7fSwKeHI6ZnVuY3Rpb24geHIoYSl7dGhpcy5hPWF9LApRdjpmdW5jdGlvbiBRdigpe30sCm40
+OmZ1bmN0aW9uIG40KGEpe3RoaXMuYT1hfSwKWEE6ZnVuY3Rpb24gWEEoKXt9LApJVjpmdW5jdGlvbiBJ
+VihhLGIsYyxkKXt2YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sTT17CllGOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4KZm9yKHQ9Yi5sZW5ndGgscz0xO3M8dDsrK3Mpe2lmKGJb
+c109PW51bGx8fGJbcy0xXSE9bnVsbCljb250aW51ZQpmb3IoO3Q+PTE7dD1yKXtyPXQtMQppZihiW3Jd
+IT1udWxsKWJyZWFrfXE9bmV3IFAuUm4oIiIpCnA9YSsiKCIKcS5hPXAKbz1ILnFDKGIsMCx0LEgudDYo
+YikuZCkKbj1vLiR0aQpuPXArbmV3IEguQTgobyxuLkMoInFVKGFMLkUpIikuYihuZXcgTS5ObygpKSxu
+LkMoIkE4PGFMLkUscVU+IikpLkgoMCwiLCAiKQpxLmE9bgpxLmE9bisoIik6IHBhcnQgIisocy0xKSsi
+IHdhcyBudWxsLCBidXQgcGFydCAiK3MrIiB3YXMgbm90LiIpCnRocm93IEguYihQLnhZKHEudygwKSkp
+fX0sCmxJOmZ1bmN0aW9uIGxJKGEpe3RoaXMuYT1hfSwKTWk6ZnVuY3Rpb24gTWkoKXt9LApxNzpmdW5j
+dGlvbiBxNygpe30sCk5vOmZ1bmN0aW9uIE5vKCl7fX0sQj17THU6ZnVuY3Rpb24gTHUoKXt9LApPUzpm
+dW5jdGlvbihhKXt2YXIgdAppZighKGE+PTY1JiZhPD05MCkpdD1hPj05NyYmYTw9MTIyCmVsc2UgdD0h
+MApyZXR1cm4gdH0sCll1OmZ1bmN0aW9uKGEsYil7dmFyIHQ9YS5sZW5ndGgscz1iKzIKaWYodDxzKXJl
+dHVybiExCmlmKCFCLk9TKEMueEIubShhLGIpKSlyZXR1cm4hMQppZihDLnhCLm0oYSxiKzEpIT09NTgp
+cmV0dXJuITEKaWYodD09PXMpcmV0dXJuITAKcmV0dXJuIEMueEIubShhLHMpPT09NDd9fSxYPXsKQ0w6
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89Yi54WihhKQpiLmhLKGEpCmlmKG8hPW51bGwpYT1K
+LktWKGEsby5sZW5ndGgpCnQ9dS5zCnM9SC5WTShbXSx0KQpyPUguVk0oW10sdCkKdD1hLmxlbmd0aApp
+Zih0IT09MCYmYi5yNChDLnhCLlcoYSwwKSkpe2lmKDA+PXQpcmV0dXJuIEguT0goYSwwKQpDLk5tLmko
+cixhWzBdKQpxPTF9ZWxzZXtDLk5tLmkociwiIikKcT0wfWZvcihwPXE7cDx0OysrcClpZihiLnI0KEMu
+eEIuVyhhLHApKSl7Qy5ObS5pKHMsQy54Qi5OaihhLHEscCkpCkMuTm0uaShyLGFbcF0pCnE9cCsxfWlm
+KHE8dCl7Qy5ObS5pKHMsQy54Qi5HKGEscSkpCkMuTm0uaShyLCIiKX1yZXR1cm4gbmV3IFguV0QoYixv
+LHMscil9LApXRDpmdW5jdGlvbiBXRChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1j
+Cl8uZT1kfSwKcVI6ZnVuY3Rpb24gcVIoYSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFguZHYoYSl9LApkdjpmdW5jdGlvbiBkdihhKXt0aGlzLmE9YX19LE89ewpSaDpmdW5jdGlvbigp
+e3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1udWxsCmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIily
+ZXR1cm4gJC5FYigpCnQ9UC51bygpCmlmKCFDLnhCLlRjKHQuZ0lpKHQpLCIvIikpcmV0dXJuICQuRWIo
+KQpzPVAuUGkoaSwwLDApCnI9UC56UihpLDAsMCkKcT1QLk9lKGksMCwwLCExKQpwPVAubGUoaSwwLDAs
+aSkKbz1QLnRHKGksMCwwKQpuPVAud0IoaSxzKQptPXM9PT0iZmlsZSIKaWYocT09bnVsbCl0PXIubGVu
+Z3RoIT09MHx8biE9bnVsbHx8bQplbHNlIHQ9ITEKaWYodClxPSIiCnQ9cT09bnVsbApsPSF0Cms9UC5r
+YSgiYS9iIiwwLDMsaSxzLGwpCmo9cy5sZW5ndGg9PT0wCmlmKGomJnQmJiFDLnhCLm4oaywiLyIpKWs9
+UC53RihrLCFqfHxsKQplbHNlIGs9UC54ZShrKQppZihuZXcgUC5EbihzLHIsdCYmQy54Qi5uKGssIi8v
+Iik/IiI6cSxuLGsscCxvKS50NCgpPT09ImFcXGIiKXJldHVybiAkLktrKCkKcmV0dXJuICQuYkQoKX0s
+CnpMOmZ1bmN0aW9uIHpMKCl7fX0sRT17T0Y6ZnVuY3Rpb24gT0YoYSxiLGMpe3RoaXMuZD1hCnRoaXMu
+ZT1iCnRoaXMuZj1jfX0sRj17cnU6ZnVuY3Rpb24gcnUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpf
+LmU9YgpfLmY9YwpfLnI9ZH19LEQ9ewpSWDpmdW5jdGlvbigpe3ZhciB0LHMscj1QLnVvKCkKaWYoSi5S
+TShyLCQuSTYpKXJldHVybiAkLkZmCiQuSTY9cgppZigkLkhrKCk9PSQuRWIoKSlyZXR1cm4gJC5GZj1y
+LlpJKCIuIikudygwKQplbHNle3Q9ci50NCgpCnM9dC5sZW5ndGgtMQpyZXR1cm4gJC5GZj1zPT09MD90
+OkMueEIuTmoodCwwLHMpfX19CnZhciB3PVtDLEgsSixQLFcsVCxMLE0sQixYLE8sRSxGLERdCmh1bmtI
+ZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILmVvLnByb3RvdHlw
+ZT17fQpKLnZCLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1ifSwKZ2lPOmZ1
+bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2Yg
+JyIrSC5kKEguTShhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYihiKQp0aHJvdyBILmIoUC5s
+cihhLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIFN0cmluZyhhKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gYT81MTkwMTg6MjE4MTU5
+fSwKJGlhMjoxfQpKLllFLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGw9PWJ9
+LAp3OmZ1bmN0aW9uKGEpe3JldHVybiJudWxsIn0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCmU3
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuU2ooYSx1Lm8uYihiKSl9LAokaWM4OjF9CkouTUYucHJv
+dG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3Ry
+aW5nKGEpfSwKJGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpKLmM1LnBy
+b3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLncoKV0KaWYodD09bnVsbClyZXR1cm4gdGhp
+cy50KGEpCnJldHVybiJKYXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAiK0guZChKLmoodCkpfSwKJFM6ZnVu
+Y3Rpb24oKXtyZXR1cm57ZnVuYzoxLG9wdDpbLCwsLCwsLCwsLCwsLCwsLF19fSwKJGlFSDoxfQpKLmpk
+LnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSxiKXtILnQ2KGEpLmQuYihiKQppZighIWEuZml4ZWQkbGVu
+Z3RoKUgudmgoUC5MNCgiYWRkIikpCmEucHVzaChiKX0sClc0OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYo
+ISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoInJlbW92ZUF0IikpCnQ9YS5sZW5ndGgKaWYoYj49dCl0
+aHJvdyBILmIoUC54KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0LHMscgpILnQ2KGEpLkMoImNYPDE+IikuYihjKQppZighIWEuZml4ZWQkbGVuZ3Ro
+KUgudmgoUC5MNCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5kZXgiKQpzPWMu
+bGVuZ3RoCnRoaXMuc0EoYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEsYikKdGhpcy52
+ZyhhLGIscixjKX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJy
+ZW1vdmVMYXN0IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkKcmV0dXJuIGEu
+cG9wKCl9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiY1g8MT4iKS5iKGIpCmlmKCEh
+YS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0LkYoKTspYS5w
+dXNoKHQuZ2woKSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoIn4oMSkiKS5iKGIp
+CnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKXtiLiQxKGFbc10pCmlmKGEubGVuZ3RoIT09dCl0aHJv
+dyBILmIoUC5hNChhKSl9fSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgudDYoYSkKcmV0dXJuIG5l
+dyBILkE4KGEsdC5LcShjKS5DKCIxKDIpIikuYihiKSx0LkMoIkA8MT4iKS5LcShjKS5DKCJBODwxLDI+
+IikpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciB0LHM9bmV3IEFycmF5KGEubGVuZ3RoKQpzLmZpeGVkJGxl
+bmd0aD1BcnJheQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMuWShzLHQsSC5kKGFbdF0pKQpyZXR1
+cm4gcy5qb2luKGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmQuYihiKQpILnQ2KGEp
+LktxKGQpLkMoIjEoMSwyKSIpLmIoYykKdD1hLmxlbmd0aApmb3Iocz1iLHI9MDtyPHQ7KytyKXtzPWMu
+JDIocyxhW3JdKQppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiBzfSwKRTpm
+dW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVti
+XX0sCmFNOmZ1bmN0aW9uKGEsYixjKXtpZihiPDB8fGI+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYiww
+LGEubGVuZ3RoLCJzdGFydCIsbnVsbCkpCmlmKGM8Ynx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShj
+LGIsYS5sZW5ndGgsImVuZCIsbnVsbCkpCmlmKGI9PT1jKXJldHVybiBILlZNKFtdLEgudDYoYSkpCnJl
+dHVybiBILlZNKGEuc2xpY2UoYixjKSxILnQ2KGEpKX0sCmdyWjpmdW5jdGlvbihhKXt2YXIgdD1hLmxl
+bmd0aAppZih0PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5XcCgpKX0sCllXOmZ1bmN0aW9uKGEs
+YixjLGQsZSl7dmFyIHQscyxyPUgudDYoYSkKci5DKCJjWDwxPiIpLmIoZCkKaWYoISFhLmltbXV0YWJs
+ZSRsaXN0KUgudmgoUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnQ9Yy1iCmlmKHQ9
+PT0wKXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08MT4iKS5iKGQpCnI9Si5VNihkKQpp
+ZihlK3Q+ci5nQShkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHM9dC0xO3M+PTA7LS1zKWFb
+YitzXT1yLnEoZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFbYitzXT1yLnEoZCxlK3MpfSwKdmc6
+ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYihiKQp0PWEubGVuZ3RoCmZvcihzPTA7czx0Oysr
+cyl7aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAu
+YTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD0wO3Q8YS5sZW5ndGg7
+Kyt0KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IFAuV0UoYSwiWyIsIl0iKX0sCmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEoubTEoYSxhLmxlbmd0
+aCxILnQ2KGEpLkMoIm0xPDE+IikpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKZ0E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKc0E6ZnVuY3Rpb24oYSxiKXtpZighIWEuZml4ZWQk
+bGVuZ3RoKUgudmgoUC5MNCgic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51
+bGwsIm5ld0xlbmd0aCIsbnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpp
+ZihiPj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTpmdW5j
+dGlvbihhLGIsYyl7SC50NihhKS5kLmIoYykKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgudmgoUC5MNCgi
+aW5kZXhlZCBzZXQiKSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2Jd
+PWN9LAokaWNYOjEsCiRpek06MX0KSi5Qby5wcm90b3R5cGU9e30KSi5tMS5wcm90b3R5cGU9ewpnbDpm
+dW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9cy5hLHE9
+ci5sZW5ndGgKaWYocy5iIT09cSl0aHJvdyBILmIoSC5sayhyKSkKdD1zLmMKaWYodD49cSl7cy5zTShu
+dWxsKQpyZXR1cm4hMX1zLnNNKHJbdF0pOysrcy5jCnJldHVybiEwfSwKc006ZnVuY3Rpb24oYSl7dGhp
+cy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KSi5xSS5wcm90b3R5cGU9ewp5dTpmdW5jdGlvbihh
+KXt2YXIgdAppZihhPj0tMjE0NzQ4MzY0OCYmYTw9MjE0NzQ4MzY0NylyZXR1cm4gYXwwCmlmKGlzRmlu
+aXRlKGEpKXt0PWE8MD9NYXRoLmNlaWwoYSk6TWF0aC5mbG9vcihhKQpyZXR1cm4gdCswfXRocm93IEgu
+YihQLkw0KCIiK2ErIi50b0ludCgpIikpfSwKelE6ZnVuY3Rpb24oYSl7aWYoYT4wKXtpZihhIT09MS8w
+KXJldHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1hdGgucm91bmQoMC1h
+KQp0aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCldaOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyLHEKaWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFkaXgiLG51bGwpKQp0PWEu
+dG9TdHJpbmcoYikKaWYoQy54Qi5tKHQsdC5sZW5ndGgtMSkhPT00MSlyZXR1cm4gdApzPS9eKFtcZGEt
+el0rKSg/OlwuKFtcZGEtel0rKSk/XChlXCsoXGQrKVwpJC8uZXhlYyh0KQppZihzPT1udWxsKUgudmgo
+UC5MNCgiVW5leHBlY3RlZCB0b1N0cmluZyByZXN1bHQ6ICIrdCkpCnI9cy5sZW5ndGgKaWYoMT49cily
+ZXR1cm4gSC5PSChzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBILk9IKHMsMykKcT0rc1szXQpyPXNb
+Ml0KaWYociE9bnVsbCl7dCs9cgpxLT1yLmxlbmd0aH1yZXR1cm4gdCtDLnhCLkl4KCIwIixxKX0sCnc6
+ZnVuY3Rpb24oYSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9LApn
+aU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1hfDAKaWYoYT09PXApcmV0dXJuIDUzNjg3MDkxMSZw
+CnQ9TWF0aC5hYnMoYSkKcz1NYXRoLmxvZyh0KS8wLjY5MzE0NzE4MDU1OTk0NTN8MApyPU1hdGgucG93
+KDIscykKcT10PDE/dC9yOnIvdApyZXR1cm4gNTM2ODcwOTExJigocSo5MDA3MTk5MjU0NzQwOTkyfDAp
+KyhxKjM1NDIyNDMxODExNzY1MjF8MCkpKjU5OTE5NytzKjEyNTl9LApoOmZ1bmN0aW9uKGEsYil7aWYo
+dHlwZW9mIGIhPSJudW1iZXIiKXRocm93IEguYihILnRMKGIpKQpyZXR1cm4gYStifSwKelk6ZnVuY3Rp
+b24oYSxiKXt2YXIgdD1hJWIKaWYodD09PTApcmV0dXJuIDAKaWYodD4wKXJldHVybiB0CmlmKGI8MCly
+ZXR1cm4gdC1iCmVsc2UgcmV0dXJuIHQrYn0sCndHOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT4wKXQ9
+dGhpcy5wMyhhLGIpCmVsc2V7dD1iPjMxPzMxOmIKdD1hPj50Pj4+MH1yZXR1cm4gdH0sCmJmOmZ1bmN0
+aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILnRMKGIpKQpyZXR1cm4gdGhpcy5wMyhhLGIpfSwKcDM6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj4zMT8wOmE+Pj5ifSwKQWc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4o
+YXxiKT4+PjB9LAokaUNQOjEsCiRpRks6MX0KSi51ci5wcm90b3R5cGU9eyRpS046MX0KSi5WQS5wcm90
+b3R5cGU9e30KSi5Eci5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihI
+LkhZKGEsYikpCmlmKGI+PWEubGVuZ3RoKUgudmgoSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFyQ29kZUF0
+KGIpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEguYihILkhZKGEsYikpCnJl
+dHVybiBhLmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC51bihiLGEs
+MCl9LApoOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRocm93IEguYihQLkwzKGIs
+bnVsbCxudWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5sZW5ndGgscz1h
+Lmxlbmd0aAppZih0PnMpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLkcoYSxzLXQpfSwKaTc6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHQscwpjPVAuakIoYixjLGEubGVuZ3RoKQp0PWEuc3Vic3RyaW5nKDAsYikK
+cz1hLnN1YnN0cmluZyhjKQpyZXR1cm4gdCtkK3N9LApRaTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYo
+IUgub2soYykpSC52aChILnRMKGMpKQppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBjLkooKQpp
+ZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9
+YytiLmxlbmd0aAppZih0PmEubGVuZ3RoKXJldHVybiExCnJldHVybiBiPT09YS5zdWJzdHJpbmcoYyx0
+KX0sCm46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIs
+Yyl7aWYoIUgub2soYikpSC52aChILnRMKGIpKQppZihjPT1udWxsKWM9YS5sZW5ndGgKaWYodHlwZW9m
+IGIhPT0ibnVtYmVyIilyZXR1cm4gYi5KKCkKaWYoYjwwKXRocm93IEguYihQLngoYixudWxsKSkKaWYo
+Yj5jKXRocm93IEguYihQLngoYixudWxsKSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC54KGMsbnVs
+bCkpCnJldHVybiBhLnN1YnN0cmluZyhiLGMpfSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLk5q
+KGEsYixudWxsKX0sCmhjOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93ZXJDYXNlKCl9LApiUzpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscT1hLnRyaW0oKSxwPXEubGVuZ3RoCmlmKHA9PT0wKXJldHVybiBxCmlm
+KHRoaXMuVyhxLDApPT09MTMzKXt0PUoubW0ocSwxKQppZih0PT09cClyZXR1cm4iIn1lbHNlIHQ9MApz
+PXAtMQpyPXRoaXMubShxLHMpPT09MTMzP0ouYzEocSxzKTpwCmlmKHQ9PT0wJiZyPT09cClyZXR1cm4g
+cQpyZXR1cm4gcS5zdWJzdHJpbmcodCxyKX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZigwPj1i
+KXJldHVybiIiCmlmKGI9PT0xfHxhLmxlbmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4wKXRocm93
+IEguYihDLkVxKQpmb3IodD1hLHM9IiI7ITA7KXtpZigoYiYxKT09PTEpcz10K3MKYj1iPj4+MQppZihi
+PT09MClicmVhawp0Kz10fXJldHVybiBzfSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKGM8MHx8
+Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1hLmluZGV4
+T2YoYixjKQpyZXR1cm4gdH0sCk9ZOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxiLDApfSwK
+UGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2UgaWYoYzww
+fHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQp0PWIubGVu
+Z3RoCnM9YS5sZW5ndGgKaWYoYyt0PnMpYz1zLXQKcmV0dXJuIGEubGFzdEluZGV4T2YoYixjKX0sCmNu
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0PWEubGVuZ3RoCmlmKGM+dCl0aHJvdyBILmIoUC5URShjLDAsdCxudWxsLG51bGwpKQpyZXR1
+cm4gSC5tMihhLGIsYyl9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiwwKX0sCnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0PWEubGVu
+Z3RoLHM9MCxyPTA7cjx0Oysrcil7cz01MzY4NzA5MTEmcythLmNoYXJDb2RlQXQocikKcz01MzY4NzA5
+MTEmcysoKDUyNDI4NyZzKTw8MTApCnNePXM+PjZ9cz01MzY4NzA5MTEmcysoKDY3MTA4ODYzJnMpPDwz
+KQpzXj1zPj4xMQpyZXR1cm4gNTM2ODcwOTExJnMrKCgxNjM4MyZzKTw8MTUpfSwKZ0E6ZnVuY3Rpb24o
+YSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj49YS5sZW5ndGh8
+fCExKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKJGl2WDoxLAokaXFVOjF9CkgucWou
+cHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIEMueEIubSh0aGlzLmEsSC5TYyhiKSl9fQpILmJRLnByb3RvdHlwZT17fQpILmFM
+LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzCnJldHVybiBuZXcgSC5hNyh0LHQu
+Z0EodCksSC5MaCh0KS5DKCJhNzxhTC5FPiIpKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT10
+aGlzLHA9cS5nQShxKQppZihiLmxlbmd0aCE9PTApe2lmKHA9PT0wKXJldHVybiIiCnQ9SC5kKHEuRSgw
+LDApKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSkKZm9yKHM9dCxyPTE7cjxwOysrcil7
+cz1zK2IrSC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0dXJu
+IHMuY2hhckNvZGVBdCgwKT09MD9zOnN9ZWxzZXtmb3Iocj0wLHM9IiI7cjxwOysrcil7cys9SC5kKHEu
+RSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0dXJuIHMuY2hhckNvZGVB
+dCgwKT09MD9zOnN9fSwKZXY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5HRygwLEguTGgodGhpcyku
+QygiYTIoYUwuRSkiKS5iKGIpKX19CkgubkgucHJvdG90eXBlPXsKZ1VEOmZ1bmN0aW9uKCl7dmFyIHQ9
+Si5IbSh0aGlzLmEpLHM9dGhpcy5jCmlmKHM9PW51bGx8fHM+dClyZXR1cm4gdApyZXR1cm4gc30sCmdB
+czpmdW5jdGlvbigpe3ZhciB0PUouSG0odGhpcy5hKSxzPXRoaXMuYgppZihzPnQpcmV0dXJuIHQKcmV0
+dXJuIHN9LApnQTpmdW5jdGlvbihhKXt2YXIgdCxzPUouSG0odGhpcy5hKSxyPXRoaXMuYgppZihyPj1z
+KXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9PW51bGx8fHQ+PXMpcmV0dXJuIHMtcgppZih0eXBlb2YgdCE9
+PSJudW1iZXIiKXJldHVybiB0LkhOKCkKcmV0dXJuIHQtcn0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+PXRoaXMscj1zLmdBcygpK2IKaWYoYj49MCl7dD1zLmdVRCgpCmlmKHR5cGVvZiB0IT09Im51bWJlciIp
+cmV0dXJuIEgucFkodCkKdD1yPj10fWVsc2UgdD0hMAppZih0KXRocm93IEguYihQLkNmKGIscywiaW5k
+ZXgiLG51bGwsbnVsbCkpCnJldHVybiBKLkdBKHMuYSxyKX19CkguYTcucHJvdG90eXBlPXsKZ2w6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMuYSxxPUou
+VTYocikscD1xLmdBKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5iKFAuYTQocikpCnQ9cy5jCmlmKHQ+PXAp
+e3Muc0kobnVsbCkKcmV0dXJuITF9cy5zSShxLkUocix0KSk7KytzLmMKcmV0dXJuITB9LApzSTpmdW5j
+dGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjoxfQpILkE4LnByb3RvdHlwZT17CmdB
+OmZ1bmN0aW9uKGEpe3JldHVybiBKLkhtKHRoaXMuYSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRo
+aXMuYi4kMShKLkdBKHRoaXMuYSxiKSl9fQpILlU1LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IEguU08oSi5JVCh0aGlzLmEpLHRoaXMuYix0aGlzLiR0aS5DKCJTTzwxPiIpKX19Ckgu
+U08ucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0LHMKZm9yKHQ9dGhpcy5hLHM9dGhpcy5iO3Qu
+RigpOylpZihILm9UKHMuJDEodC5nbCgpKSkpcmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigp
+e3JldHVybiB0aGlzLmEuZ2woKX19CkguU1UucHJvdG90eXBlPXt9CkguUmUucHJvdG90eXBlPXsKWTpm
+dW5jdGlvbihhLGIsYyl7SC5MaCh0aGlzKS5DKCJSZS5FIikuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fu
+bm90IG1vZGlmeSBhbiB1bm1vZGlmaWFibGUgbGlzdCIpKX19CkguWEMucHJvdG90eXBlPXt9Ckgud3Yu
+cHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuX2hhc2hDb2RlCmlmKHQhPW51bGwp
+cmV0dXJuIHQKdD01MzY4NzA5MTEmNjY0NTk3KkouaGYodGhpcy5hKQp0aGlzLl9oYXNoQ29kZT10CnJl
+dHVybiB0fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4nU3ltYm9sKCInK0guZCh0aGlzLmEpKyciKSd9LApE
+TjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBILnd2
+JiZ0aGlzLmE9PWIuYX0sCiRpR0Q6MX0KSC5QRC5wcm90b3R5cGU9e30KSC5XVS5wcm90b3R5cGU9ewp3
+OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5M
+aCh0aGlzKQp0LmQuYihiKQp0LmNoWzFdLmIoYykKcmV0dXJuIEguZGMoKX0sCiRpWjA6MX0KSC5MUC5w
+cm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKeDQ6ZnVuY3Rpb24oYSl7aWYo
+dHlwZW9mIGEhPSJzdHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YSlyZXR1cm4hMQpyZXR1
+cm4gdGhpcy5iLmhhc093blByb3BlcnR5KGEpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KGIp
+KXJldHVybiBudWxsCnJldHVybiB0aGlzLnFQKGIpfSwKcVA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
+YltILnkoYSldfSwKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9SC5MaCh0aGlzKQpwLkMoIn4o
+MSwyKSIpLmIoYikKdD10aGlzLmMKZm9yKHM9dC5sZW5ndGgscD1wLmNoWzFdLHI9MDtyPHM7KytyKXtx
+PXRbcl0KYi4kMihxLHAuYih0aGlzLnFQKHEpKSl9fX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6ZnVuY3Rp
+b24oKXt2YXIgdD10aGlzLmEKcmV0dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRo
+aXMKaWYocC5jPT09MSlyZXR1cm4gQy5kbgp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5mCmlm
+KHM9PT0wKXJldHVybiBDLmRuCnI9W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0aClyZXR1
+cm4gSC5PSCh0LHEpCnIucHVzaCh0W3FdKX1yZXR1cm4gSi56QyhyKX0sCmdWbTpmdW5jdGlvbigpe3Zh
+ciB0LHMscixxLHAsbyxuLG0sbD10aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuQ00KdD1sLmUKcz10Lmxl
+bmd0aApyPWwuZApxPXIubGVuZ3RoLXMtbC5mCmlmKHM9PT0wKXJldHVybiBDLkNNCnA9bmV3IEguTjUo
+dS5lbykKZm9yKG89MDtvPHM7KytvKXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LG8pCm49dFtv
+XQptPXErbwppZihtPDB8fG0+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsbSkKcC5ZKDAsbmV3IEgud3Yo
+biksclttXSl9cmV0dXJuIG5ldyBILlBEKHAsdS5GKX0sCiRpdlE6MX0KSC5Dai5wcm90b3R5cGU9ewok
+MjpmdW5jdGlvbihhLGIpe3ZhciB0CkgueShhKQp0PXRoaXMuYQp0LmI9dC5iKyIkIitILmQoYSkKQy5O
+bS5pKHRoaXMuYixhKQpDLk5tLmkodGhpcy5jLGIpOysrdC5hfSwKJFM6MTl9CkguWnIucHJvdG90eXBl
+PXsKcVM6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMscT1uZXcgUmVnRXhwKHIuYSkuZXhlYyhhKQpp
+ZihxPT1udWxsKXJldHVybiBudWxsCnQ9T2JqZWN0LmNyZWF0ZShudWxsKQpzPXIuYgppZihzIT09LTEp
+dC5hcmd1bWVudHM9cVtzKzFdCnM9ci5jCmlmKHMhPT0tMSl0LmFyZ3VtZW50c0V4cHI9cVtzKzFdCnM9
+ci5kCmlmKHMhPT0tMSl0LmV4cHI9cVtzKzFdCnM9ci5lCmlmKHMhPT0tMSl0Lm1ldGhvZD1xW3MrMV0K
+cz1yLmYKaWYocyE9PS0xKXQucmVjZWl2ZXI9cVtzKzFdCnJldHVybiB0fX0KSC5XMC5wcm90b3R5cGU9
+ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYgppZih0PT1udWxsKXJldHVybiJOb1N1Y2hNZXRob2RF
+cnJvcjogIitILmQodGhpcy5hKQpyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91
+bmQ6ICciK3QrIicgb24gbnVsbCJ9fQpILmF6LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQs
+cz10aGlzLHI9Ik5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIixxPXMuYgppZihx
+PT1udWxsKXJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogIitILmQocy5hKQp0PXMuYwppZih0PT1udWxs
+KXJldHVybiByK3ErIicgKCIrSC5kKHMuYSkrIikiCnJldHVybiByK3ErIicgb24gJyIrdCsiJyAoIitI
+LmQocy5hKSsiKSJ9fQpILnZWLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJl
+dHVybiB0Lmxlbmd0aD09PTA/IkVycm9yIjoiRXJyb3I6ICIrdH19CkguQW0ucHJvdG90eXBlPXsKJDE6
+ZnVuY3Rpb24oYSl7aWYodS5iVS5jKGEpKWlmKGEuJHRocm93bkpzRXJyb3I9PW51bGwpYS4kdGhyb3du
+SnNFcnJvcj10aGlzLmEKcmV0dXJuIGF9LAokUzo0fQpILlhPLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24o
+YSl7dmFyIHQscz10aGlzLmIKaWYocyE9bnVsbClyZXR1cm4gcwpzPXRoaXMuYQp0PXMhPT1udWxsJiZ0
+eXBlb2Ygcz09PSJvYmplY3QiP3Muc3RhY2s6bnVsbApyZXR1cm4gdGhpcy5iPXQ9PW51bGw/IiI6dH0s
+CiRpR3o6MX0KSC5UcC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuY29uc3RydWN0
+b3Iscz10PT1udWxsP251bGw6dC5uYW1lCnJldHVybiJDbG9zdXJlICciK0guTlEocz09bnVsbD8idW5r
+bm93biI6cykrIicifSwKJGlFSDoxLApnUWw6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sCiRDOiIkMSIs
+CiRSOjEsCiREOm51bGx9CkgubGMucHJvdG90eXBlPXt9CkguengucHJvdG90eXBlPXsKdzpmdW5jdGlv
+bihhKXt2YXIgdD10aGlzLiRzdGF0aWNfbmFtZQppZih0PT1udWxsKXJldHVybiJDbG9zdXJlIG9mIHVu
+a25vd24gc3RhdGljIG1ldGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIrSC5OUSh0KSsiJyJ9fQpILnJULnBy
+b3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlm
+KHQ9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguclQpKXJldHVybiExCnJldHVybiB0LmE9
+PT1iLmEmJnQuYj09PWIuYiYmdC5jPT09Yi5jfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5j
+CmlmKHM9PW51bGwpdD1ILmVRKHRoaXMuYSkKZWxzZSB0PXR5cGVvZiBzIT09Im9iamVjdCI/Si5oZihz
+KTpILmVRKHMpCnJldHVybih0XkguZVEodGhpcy5iKSk+Pj4wfSwKdzpmdW5jdGlvbihhKXt2YXIgdD10
+aGlzLmMKaWYodD09bnVsbCl0PXRoaXMuYQpyZXR1cm4iQ2xvc3VyZSAnIitILmQodGhpcy5kKSsiJyBv
+ZiAiKygiSW5zdGFuY2Ugb2YgJyIrSC5kKEguTSh0KSkrIiciKX19CkguRXEucHJvdG90eXBlPXsKdzpm
+dW5jdGlvbihhKXtyZXR1cm4iUnVudGltZUVycm9yOiAiK0guZCh0aGlzLmEpfX0KSC5rWS5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AucCh0aGlzLmEpfX0K
+SC5ONS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKZ1Y6ZnVuY3Rpb24o
+KXtyZXR1cm4gbmV3IEguaTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+IikpfSwKeDQ6ZnVuY3Rpb24o
 YSl7dmFyIHQscwppZih0eXBlb2YgYT09InN0cmluZyIpe3Q9dGhpcy5iCmlmKHQ9PW51bGwpcmV0dXJu
-ITEKcmV0dXJuIHRoaXMuYk8odCxhKX1lbHNle3M9dGhpcy5jZihhKQpyZXR1cm4gc319LApjZjpmdW5j
-dGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5hRSh0aGlz
-LmF1KHQsSi5idihhKSYweDNmZmZmZmYpLGEpPj0wfSwKajpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixx
+ITEKcmV0dXJuIHRoaXMuWHUodCxhKX1lbHNle3M9dGhpcy5DWChhKQpyZXR1cm4gc319LApDWDpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5GaCh0aGlz
+LkJ0KHQsSi5oZihhKSYweDNmZmZmZmYpLGEpPj0wfSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixx
 LHA9dGhpcyxvPW51bGwKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PXAuYgppZih0PT1udWxsKXJldHVy
-biBvCnM9cC5hOCh0LGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5cGVvZiBiPT0i
-bnVtYmVyIiYmKGImMHgzZmZmZmZmKT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJuIG8Kcz1wLmE4
-KHEsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAuY2coYil9LApjZzpmdW5j
-dGlvbihhKXt2YXIgdCxzLHI9dGhpcy5kCmlmKHI9PW51bGwpcmV0dXJuIG51bGwKdD10aGlzLmF1KHIs
-Si5idihhKSYweDNmZmZmZmYpCnM9dGhpcy5hRSh0LGEpCmlmKHM8MClyZXR1cm4gbnVsbApyZXR1cm4g
-dFtzXS5ifSwKbDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPUgudihuKQpt
-LmQuYihiKQptLmNoWzFdLmIoYykKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PW4uYgpuLmFSKHQ9PW51
-bGw/bi5iPW4uYXYoKTp0LGIsYyl9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZm
-Zik9PT1iKXtzPW4uYwpuLmFSKHM9PW51bGw/bi5jPW4uYXYoKTpzLGIsYyl9ZWxzZXtyPW4uZAppZihy
-PT1udWxsKXI9bi5kPW4uYXYoKQpxPUouYnYoYikmMHgzZmZmZmZmCnA9bi5hdShyLHEpCmlmKHA9PW51
-bGwpbi5heChyLHEsW24uYW4oYixjKV0pCmVsc2V7bz1uLmFFKHAsYikKaWYobz49MClwW29dLmI9Ywpl
-bHNlIHAucHVzaChuLmFuKGIsYykpfX19LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMKSC52
-KHIpLmgoIn4oMSwyKSIpLmIoYikKdD1yLmUKcz1yLnIKZm9yKDt0IT1udWxsOyl7Yi4kMih0LmEsdC5i
-KQppZihzIT09ci5yKXRocm93IEguYShQLmF2KHIpKQp0PXQuY319LAphUjpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQscz10aGlzLHI9SC52KHMpCnIuZC5iKGIpCnIuY2hbMV0uYihjKQp0PXMuYTgoYSxiKQppZih0
-PT1udWxsKXMuYXgoYSxiLHMuYW4oYixjKSkKZWxzZSB0LmI9Y30sCmJHOmZ1bmN0aW9uKCl7dGhpcy5y
-PXRoaXMucisxJjY3MTA4ODYzfSwKYW46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILnYocyks
-cT1uZXcgSC5lOChyLmQuYihhKSxyLmNoWzFdLmIoYikpCmlmKHMuZT09bnVsbClzLmU9cy5mPXEKZWxz
-ZXt0PXMuZgpxLmQ9dApzLmY9dC5jPXF9KytzLmEKcy5iRygpCnJldHVybiBxfSwKYUU6ZnVuY3Rpb24o
-YSxiKXt2YXIgdCxzCmlmKGE9PW51bGwpcmV0dXJuLTEKdD1hLmxlbmd0aApmb3Iocz0wO3M8dDsrK3Mp
-aWYoSi5jcyhhW3NdLmEsYikpcmV0dXJuIHMKcmV0dXJuLTF9LAppOmZ1bmN0aW9uKGEpe3JldHVybiBQ
-LmgzKHRoaXMpfSwKYTg6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCmF1OmZ1bmN0aW9uKGEsYil7
-cmV0dXJuIGFbYl19LApheDpmdW5jdGlvbihhLGIsYyl7YVtiXT1jfSwKYlA6ZnVuY3Rpb24oYSxiKXtk
-ZWxldGUgYVtiXX0sCmJPOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYTgoYSxiKSE9bnVsbH0sCmF2
-OmZ1bmN0aW9uKCl7dmFyIHQ9Ijxub24taWRlbnRpZmllci1rZXk+IixzPU9iamVjdC5jcmVhdGUobnVs
-bCkKdGhpcy5heChzLHQscykKdGhpcy5iUChzLHQpCnJldHVybiBzfSwKJGloUzoxfQpILmU4LnByb3Rv
-dHlwZT17fQpILmFQLnByb3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYX0sCmdG
-OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPW5ldyBILmJMKHQsdC5yLHRoaXMuJHRpLmgoImJMPDE+
-IikpCnMuYz10LmUKcmV0dXJuIHN9fQpILmJMLnByb3RvdHlwZT17Cmd1OmZ1bmN0aW9uKCl7cmV0dXJu
-IHRoaXMuZH0sCnA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBI
-LmEoUC5hdihzKSkKZWxzZXtzPXQuYwppZihzPT1udWxsKXt0LnNhUyhudWxsKQpyZXR1cm4hMX1lbHNl
-e3Quc2FTKHMuYSkKdC5jPXQuYy5jCnJldHVybiEwfX19LApzYVM6ZnVuY3Rpb24oYSl7dGhpcy5kPXRo
-aXMuJHRpLmQuYihhKX0sCiRpUjoxfQpILmZ5LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLmEoYSl9LAokUzo0fQpILmZ6LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IHRoaXMuYShhLGIpfSwKJFM6MjF9CkguZkEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuYShILm8oYSkpfSwKJFM6MjV9CkguY0sucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1
-cm4iUmVnRXhwLyIrdGhpcy5hKyIvIit0aGlzLmIuZmxhZ3N9LAokaWNYOjEsCiRpaFo6MX0KSC5DLnBy
-b3RvdHlwZT17JGlDOjEsJGlXOjF9CkguYlEucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJu
-IGEubGVuZ3RofSwKJGlKOjF9CkguYVIucHJvdG90eXBlPXsKajpmdW5jdGlvbihhLGIpe0gueChiKQpI
-LmFyKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LApsOmZ1bmN0aW9uKGEsYixjKXtILmFyKGIsYSxh
-Lmxlbmd0aCkKYVtiXT1jfSwKJGlqOjEsCiRpbToxfQpILmJSLnByb3RvdHlwZT17Cmw6ZnVuY3Rpb24o
-YSxiLGMpe0guYXIoYixhLGEubGVuZ3RoKQphW2JdPWN9LAokaWo6MSwKJGltOjF9CkguY1AucHJvdG90
-eXBlPXsKajpmdW5jdGlvbihhLGIpe0gueChiKQpILmFyKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19
-fQpILmNRLnByb3RvdHlwZT17Cmo6ZnVuY3Rpb24oYSxiKXtILngoYikKSC5hcihiLGEsYS5sZW5ndGgp
-CnJldHVybiBhW2JdfX0KSC5jUi5wcm90b3R5cGU9ewpqOmZ1bmN0aW9uKGEsYil7SC54KGIpCkguYXIo
-YixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguY1MucHJvdG90eXBlPXsKajpmdW5jdGlvbihhLGIp
-e0gueChiKQpILmFyKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmNULnByb3RvdHlwZT17Cmo6
-ZnVuY3Rpb24oYSxiKXtILngoYikKSC5hcihiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5iUy5w
-cm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApqOmZ1bmN0aW9uKGEsYil7
-SC54KGIpCkguYXIoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguYVMucHJvdG90eXBlPXsKZ206
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKajpmdW5jdGlvbihhLGIpe0gueChiKQpILmFyKGIs
-YSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LAokaWFTOjEsCiRpYWg6MX0KSC5jOS5wcm90b3R5cGU9e30K
-SC5jYS5wcm90b3R5cGU9e30KSC5jYi5wcm90b3R5cGU9e30KSC5jYy5wcm90b3R5cGU9e30KSC5hZi5w
-cm90b3R5cGU9ewpoOmZ1bmN0aW9uKGEpe3JldHVybiBILmRGKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9
-LApFOmZ1bmN0aW9uKGEpe3JldHVybiBILmtBKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9fQpILmVCLnBy
-b3RvdHlwZT17fQpILmRwLnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX19Ckgu
-YzEucHJvdG90eXBlPXt9CkguY2gucHJvdG90eXBlPXt9ClAuZXQucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy5hLHM9dC5hCnQuYT1udWxsCnMuJDAoKX0sCiRTOjExfQpQLmVzLnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdGhpcy5hLmE9dS5NLmIoYSkKdD10aGlzLmIKcz10
-aGlzLmMKdC5maXJzdENoaWxkP3QucmVtb3ZlQ2hpbGQocyk6dC5hcHBlbmRDaGlsZChzKX0sCiRTOjM2
-fQpQLmV1LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjow
-LAokUzowfQpQLmV2LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAi
-LAokUjowLAokUzowfQpQLmRDLnByb3RvdHlwZT17CmJGOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRU
-aW1lb3V0IT1udWxsKXRoaXMuYj1zZWxmLnNldFRpbWVvdXQoSC5kTShuZXcgUC5mXyh0aGlzLGIpLDAp
-LGEpCmVsc2UgdGhyb3cgSC5hKFAuTigiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5kLiIpKX0sCmM0OmZ1
-bmN0aW9uKCl7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbCly
-ZXR1cm4Kc2VsZi5jbGVhclRpbWVvdXQodCkKdGhpcy5iPW51bGx9ZWxzZSB0aHJvdyBILmEoUC5OKCJD
-YW5jZWxpbmcgYSB0aW1lci4iKSl9LAokaWs2OjF9ClAuZl8ucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24o
-KXt0aGlzLmEuYj1udWxsCnRoaXMuYi4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6MX0KUC5jMi5wcm90
-b3R5cGU9ewpiYTpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpYT1uZXcgUC5iZCgpCnQ9dGhp
-cy5hCmlmKHQuYSE9PTApdGhyb3cgSC5hKFAuZDIoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQp0
-LmJLKGEsYil9LApiOTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5iYShhLG51bGwpfX0KUC5jMC5wcm90
-b3R5cGU9e30KUC5hWi5wcm90b3R5cGU9ewpjaTpmdW5jdGlvbihhKXtpZigodGhpcy5jJjE1KSE9PTYp
-cmV0dXJuITAKcmV0dXJuIHRoaXMuYi5iLmFLKHUuYWwuYih0aGlzLmQpLGEuYSx1LmNKLHUuSyl9LApj
-ZTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmUscz11Lnoscj11LksscT10aGlzLiR0aS5oKCIyLyIpLHA9
-dGhpcy5iLmIKaWYodS5ZLmModCkpcmV0dXJuIHEuYihwLmNvKHQsYS5hLGEuYixzLHIsdS5sKSkKZWxz
-ZSByZXR1cm4gcS5iKHAuYUsodS55LmIodCksYS5hLHMscikpfX0KUC5TLnByb3RvdHlwZT17CmJuOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT10aGlzLiR0aQpxLkUoYykuaCgiMS8oMikiKS5iKGEpCnQ9
-JC53CmlmKHQhPT1DLmQpe2MuaCgiQDwwLz4iKS5FKHEuZCkuaCgiMSgyKSIpLmIoYSkKaWYoYiE9bnVs
-bCliPVAuaXooYix0KX1zPW5ldyBQLlMoJC53LGMuaCgiUzwwPiIpKQpyPWI9PW51bGw/MTozCnRoaXMu
-YW8obmV3IFAuYVoocyxyLGEsYixxLmgoIkA8MT4iKS5FKGMpLmgoImFaPDEsMj4iKSkpCnJldHVybiBz
-fSwKYTQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5ibihhLG51bGwsYil9LAphZDpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIKdS5iZi5iKG51bGwpCnQ9dGhpcy4kdGkKcz0kLncKcj1uZXcgUC5TKHMsdCkKaWYo
-cyE9PUMuZClhPVAuaXooYSxzKQp0aGlzLmFvKG5ldyBQLmFaKHIsMixudWxsLGEsdC5oKCJAPDE+Iiku
-RSh0LmQpLmgoImFaPDEsMj4iKSkpCnJldHVybiByfSwKYW86ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlz
-LHI9cy5hCmlmKHI8PTEpe2EuYT11LnguYihzLmMpCnMuYz1hfWVsc2V7aWYocj09PTIpe3Q9dS5fLmIo
-cy5jKQpyPXQuYQppZihyPDQpe3QuYW8oYSkKcmV0dXJufXMuYT1yCnMuYz10LmN9UC5idChudWxsLG51
-bGwscy5iLHUuTS5iKG5ldyBQLmVDKHMsYSkpKX19LApiMjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxw
-LG89dGhpcyxuPXt9Cm4uYT1hCmlmKGE9PW51bGwpcmV0dXJuCnQ9by5hCmlmKHQ8PTEpe3M9dS54LmIo
-by5jKQpyPW8uYz1hCmlmKHMhPW51bGwpe2Zvcig7cT1yLmEscSE9bnVsbDtyPXEpO3IuYT1zfX1lbHNl
-e2lmKHQ9PT0yKXtwPXUuXy5iKG8uYykKdD1wLmEKaWYodDw0KXtwLmIyKGEpCnJldHVybn1vLmE9dApv
-LmM9cC5jfW4uYT1vLmFhKGEpClAuYnQobnVsbCxudWxsLG8uYix1Lk0uYihuZXcgUC5lSyhuLG8pKSl9
-fSwKYTk6ZnVuY3Rpb24oKXt2YXIgdD11LnguYih0aGlzLmMpCnRoaXMuYz1udWxsCnJldHVybiB0aGlz
-LmFhKHQpfSwKYWE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0PWEscz1udWxsO3QhPW51bGw7cz10
-LHQ9cil7cj10LmEKdC5hPXN9cmV0dXJuIHN9LAphVzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1z
-LiR0aQpyLmgoIjEvIikuYihhKQppZihyLmgoImJFPDE+IikuYyhhKSlpZihyLmMoYSkpUC5lRihhLHMp
-CmVsc2UgUC5pOShhLHMpCmVsc2V7dD1zLmE5KCkKci5kLmIoYSkKcy5hPTQKcy5jPWEKUC5ibyhzLHQp
-fX0sCmFwOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzCnUubC5iKGIpCnQ9cy5hOSgpCnMuYT04CnMu
-Yz1uZXcgUC5hdShhLGIpClAuYm8ocyx0KX0sCmJKOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LiR0
-aQpzLmgoIjEvIikuYihhKQppZihzLmgoImJFPDE+IikuYyhhKSl7dC5iTChhKQpyZXR1cm59dC5hPTEK
-UC5idChudWxsLG51bGwsdC5iLHUuTS5iKG5ldyBQLmVFKHQsYSkpKX0sCmJMOmZ1bmN0aW9uKGEpe3Zh
-ciB0PXRoaXMscz10LiR0aQpzLmgoImJFPDE+IikuYihhKQppZihzLmMoYSkpe2lmKGEuZ2N6KCkpe3Qu
-YT0xClAuYnQobnVsbCxudWxsLHQuYix1Lk0uYihuZXcgUC5lSih0LGEpKSl9ZWxzZSBQLmVGKGEsdCkK
-cmV0dXJufVAuaTkoYSx0KX0sCmJLOmZ1bmN0aW9uKGEsYil7dGhpcy5hPTEKUC5idChudWxsLG51bGws
-dGhpcy5iLHUuTS5iKG5ldyBQLmVEKHRoaXMsYSxiKSkpfSwKJGliRToxfQpQLmVDLnByb3RvdHlwZT17
-CiQwOmZ1bmN0aW9uKCl7UC5ibyh0aGlzLmEsdGhpcy5iKX0sCiRTOjB9ClAuZUsucHJvdG90eXBlPXsK
-JDA6ZnVuY3Rpb24oKXtQLmJvKHRoaXMuYix0aGlzLmEuYSl9LAokUzowfQpQLmVHLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQp0LmE9MAp0LmFXKGEpfSwKJFM6MTF9ClAuZUgucHJv
-dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt1LmwuYihiKQp0aGlzLmEuYXAoYSxiKX0sCiQxOmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLiQyKGEsbnVsbCl9LAokQzoiJDIiLAokRDpmdW5jdGlvbigpe3JldHVy
-bltudWxsXX0sCiRTOjM3fQpQLmVJLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLmFwKHRo
-aXMuYix0aGlzLmMpfSwKJFM6MH0KUC5lRS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0PXRo
-aXMuYSxzPXQuJHRpLmQuYih0aGlzLmIpLHI9dC5hOSgpCnQuYT00CnQuYz1zClAuYm8odCxyKX0sCiRT
-OjB9ClAuZUoucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLmVGKHRoaXMuYix0aGlzLmEpfSwKJFM6
-MH0KUC5lRC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5hcCh0aGlzLmIsdGhpcy5jKX0s
-CiRTOjB9ClAuZU4ucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbj10aGlz
-LG09bnVsbAp0cnl7cj1uLmMKbT1yLmIuYi5ibCh1LmZPLmIoci5kKSx1LnopfWNhdGNoKHEpe3Q9SC5R
-KHEpCnM9SC5jcChxKQppZihuLmQpe3I9dS5uLmIobi5hLmEuYykuYQpwPXQKcD1yPT1udWxsP3A9PW51
-bGw6cj09PXAKcj1wfWVsc2Ugcj0hMQpwPW4uYgppZihyKXAuYj11Lm4uYihuLmEuYS5jKQplbHNlIHAu
-Yj1uZXcgUC5hdSh0LHMpCnAuYT0hMApyZXR1cm59aWYodS5jLmMobSkpe2lmKG0gaW5zdGFuY2VvZiBQ
-LlMmJm0uYT49NCl7aWYobS5hPT09OCl7cj1uLmIKci5iPXUubi5iKG0uYykKci5hPSEwfXJldHVybn1v
-PW4uYS5hCnI9bi5iCnIuYj1tLmE0KG5ldyBQLmVPKG8pLHUueikKci5hPSExfX0sCiRTOjF9ClAuZU8u
-cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRTOjM4fQpQLmVNLnByb3Rv
-dHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzCnRyeXtyPW0uYgpxPXIu
-JHRpCnA9cS5kCm89cC5iKG0uYykKbS5hLmI9ci5iLmIuYUsocS5oKCIyLygxKSIpLmIoci5kKSxvLHEu
-aCgiMi8iKSxwKX1jYXRjaChuKXt0PUguUShuKQpzPUguY3AobikKcj1tLmEKci5iPW5ldyBQLmF1KHQs
-cykKci5hPSEwfX0sCiRTOjF9ClAuZUwucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGw9dGhpcwp0cnl7dD11Lm4uYihsLmEuYS5jKQpxPWwuYwppZihILmRLKHEuY2kodCkp
-JiZxLmUhPW51bGwpe3A9bC5iCnAuYj1xLmNlKHQpCnAuYT0hMX19Y2F0Y2gobyl7cz1ILlEobykKcj1I
-LmNwKG8pCnE9dS5uLmIobC5hLmEuYykKcD1xLmEKbj1zCm09bC5iCmlmKHA9PW51bGw/bj09bnVsbDpw
-PT09biltLmI9cQplbHNlIG0uYj1uZXcgUC5hdShzLHIpCm0uYT0hMH19LAokUzoxfQpQLmRoLnByb3Rv
-dHlwZT17fQpQLmJZLnByb3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9e30s
-cD1uZXcgUC5TKCQudyx1LmZKKQpxLmE9MAp0PUgudihyKQpzPXQuaCgifigxKSIpLmIobmV3IFAuZWgo
-cSxyKSkKdS5NLmIobmV3IFAuZWkocSxwKSkKVy5hQyhyLmEsci5iLHMsITEsdC5kKQpyZXR1cm4gcH19
-ClAuZWgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC52KHRoaXMuYikuZC5iKGEpOysrdGhpcy5h
-LmF9LAokUzpmdW5jdGlvbigpe3JldHVybiBILnYodGhpcy5iKS5oKCJwKDEpIil9fQpQLmVpLnByb3Rv
-dHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLmFXKHRoaXMuYS5hKX0sCiRTOjB9ClAuZDQucHJvdG90
-eXBlPXt9ClAuZDUucHJvdG90eXBlPXt9ClAuYXUucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1
-cm4gSC5iKHRoaXMuYSl9LAokaXI6MX0KUC5kRy5wcm90b3R5cGU9eyRpaTg6MX0KUC5mZi5wcm90b3R5
-cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcy5hLHI9cy5hCnM9cj09bnVsbD9zLmE9bmV3IFAu
-YmQoKTpyCnI9dGhpcy5iCmlmKHI9PW51bGwpdGhyb3cgSC5hKHMpCnQ9SC5hKHMpCnQuc3RhY2s9ci5p
-KDApCnRocm93IHR9LAokUzowfQpQLmR4LnByb3RvdHlwZT17CmNwOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
-cixxPW51bGwKdS5NLmIoYSkKdHJ5e2lmKEMuZD09PSQudyl7YS4kMCgpCnJldHVybn1QLmlBKHEscSx0
-aGlzLGEsdS5IKX1jYXRjaChyKXt0PUguUShyKQpzPUguY3AocikKUC5mZShxLHEsdGhpcyx0LHUubC5i
-KHMpKX19LApjcTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9bnVsbApjLmgoIn4oMCkiKS5iKGEp
-CmMuYihiKQp0cnl7aWYoQy5kPT09JC53KXthLiQxKGIpCnJldHVybn1QLmlCKHEscSx0aGlzLGEsYix1
-LkgsYyl9Y2F0Y2gocil7dD1ILlEocikKcz1ILmNwKHIpClAuZmUocSxxLHRoaXMsdCx1LmwuYihzKSl9
-fSwKYzE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuZVIodGhpcyxiLmgoIjAoKSIpLmIoYSksYil9
-LAphejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuZVEodGhpcyx1Lk0uYihhKSl9LApjMjpmdW5jdGlv
-bihhLGIpe3JldHVybiBuZXcgUC5lUyh0aGlzLGIuaCgifigwKSIpLmIoYSksYil9LApqOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIG51bGx9LApibDpmdW5jdGlvbihhLGIpe2IuaCgiMCgpIikuYihhKQppZigkLnc9
-PT1DLmQpcmV0dXJuIGEuJDAoKQpyZXR1cm4gUC5pQShudWxsLG51bGwsdGhpcyxhLGIpfSwKYUs6ZnVu
-Y3Rpb24oYSxiLGMsZCl7Yy5oKCJAPDA+IikuRShkKS5oKCIxKDIpIikuYihhKQpkLmIoYikKaWYoJC53
-PT09Qy5kKXJldHVybiBhLiQxKGIpCnJldHVybiBQLmlCKG51bGwsbnVsbCx0aGlzLGEsYixjLGQpfSwK
-Y286ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2QuaCgiQDwwPiIpLkUoZSkuRShmKS5oKCIxKDIsMykiKS5i
-KGEpCmUuYihiKQpmLmIoYykKaWYoJC53PT09Qy5kKXJldHVybiBhLiQyKGIsYykKcmV0dXJuIFAubDko
-bnVsbCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfX0KUC5lUi5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLmEuYmwodGhpcy5iLHRoaXMuYyl9LAokUzpmdW5jdGlvbigpe3JldHVybiB0aGlz
-LmMuaCgiMCgpIil9fQpQLmVRLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5j
-cCh0aGlzLmIpfSwKJFM6MX0KUC5lUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
-LmMKcmV0dXJuIHRoaXMuYS5jcSh0aGlzLmIsdC5iKGEpLHQpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5jLmgoIn4oMCkiKX19ClAuYzYucHJvdG90eXBlPXsKZ0Y6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cyxzPW5ldyBQLmIwKHQsdC5yLEgudih0KS5oKCJiMDwxPiIpKQpzLmM9dC5lCnJldHVybiBzfSwKZ206
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCnc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKHR5cGVv
-ZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXt0PXRoaXMuYgppZih0PT1udWxsKXJldHVybiEx
-CnJldHVybiB1LkouYih0W2JdKSE9bnVsbH1lbHNle3M9dGhpcy5iTihiKQpyZXR1cm4gc319LApiTjpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5hdCh0
-W3RoaXMuYXEoYSldLGEpPj0wfSwKazpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkgudihyKS5k
-LmIoYikKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9ci5iCnJldHVybiBy
-LmFUKHQ9PW51bGw/ci5iPVAuaDkoKTp0LGIpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYx
-MDczNzQxODIzKT09PWIpe3M9ci5jCnJldHVybiByLmFUKHM9PW51bGw/ci5jPVAuaDkoKTpzLGIpfWVs
-c2UgcmV0dXJuIHIuYkgoYil9LApiSDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT10aGlzCkgudihxKS5k
-LmIoYSkKdD1xLmQKaWYodD09bnVsbCl0PXEuZD1QLmg5KCkKcz1xLmFxKGEpCnI9dFtzXQppZihyPT1u
-dWxsKXRbc109W3EuYXcoYSldCmVsc2V7aWYocS5hdChyLGEpPj0wKXJldHVybiExCnIucHVzaChxLmF3
-KGEpKX1yZXR1cm4hMH0sCk06ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiIT09Il9fcHJvdG9fXyIpcmV0
-dXJuIHRoaXMuYlUodGhpcy5iLGIpCmVsc2V7dD10aGlzLmJUKGIpCnJldHVybiB0fX0sCmJUOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuZAppZihvPT1udWxsKXJldHVybiExCnQ9cC5hcShh
-KQpzPW9bdF0Kcj1wLmF0KHMsYSkKaWYocjwwKXJldHVybiExCnE9cy5zcGxpY2UociwxKVswXQppZigw
-PT09cy5sZW5ndGgpZGVsZXRlIG9bdF0KcC5iNShxKQpyZXR1cm4hMH0sCmFUOmZ1bmN0aW9uKGEsYil7
-SC52KHRoaXMpLmQuYihiKQppZih1LkouYihhW2JdKSE9bnVsbClyZXR1cm4hMQphW2JdPXRoaXMuYXco
-YikKcmV0dXJuITB9LApiVTpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuITEKdD11
-LkouYihhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMuYjUodCkKZGVsZXRlIGFbYl0KcmV0dXJu
-ITB9LApiMTpmdW5jdGlvbigpe3RoaXMucj0xMDczNzQxODIzJnRoaXMucisxfSwKYXc6ZnVuY3Rpb24o
-YSl7dmFyIHQscz10aGlzLHI9bmV3IFAuZHUoSC52KHMpLmQuYihhKSkKaWYocy5lPT1udWxsKXMuZT1z
-LmY9cgplbHNle3Q9cy5mCnIuYz10CnMuZj10LmI9cn0rK3MuYQpzLmIxKCkKcmV0dXJuIHJ9LApiNTpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLHM9YS5jLHI9YS5iCmlmKHM9PW51bGwpdC5lPXIKZWxzZSBzLmI9
-cgppZihyPT1udWxsKXQuZj1zCmVsc2Ugci5jPXM7LS10LmEKdC5iMSgpfSwKYXE6ZnVuY3Rpb24oYSl7
-cmV0dXJuIEouYnYoYSkmMTA3Mzc0MTgyM30sCmF0OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZihhPT1u
-dWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouY3MoYVtzXS5hLGIpKXJl
-dHVybiBzCnJldHVybi0xfX0KUC5kdS5wcm90b3R5cGU9e30KUC5iMC5wcm90b3R5cGU9ewpndTpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmR9LApwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYQppZih0LmIh
-PT1zLnIpdGhyb3cgSC5hKFAuYXYocykpCmVsc2V7cz10LmMKaWYocz09bnVsbCl7dC5zYVYobnVsbCkK
-cmV0dXJuITF9ZWxzZXt0LnNhVih0LiR0aS5kLmIocy5hKSkKdC5jPXQuYy5iCnJldHVybiEwfX19LApz
-YVY6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpUjoxfQpQLmJOLnByb3RvdHlw
-ZT17JGlqOjEsJGltOjF9ClAubC5wcm90b3R5cGU9ewpnRjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEgu
-YVEoYSx0aGlzLmdtKGEpLEguYTgoYSkuaCgiYVE8bC5FPiIpKX0sCk86ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gdGhpcy5qKGEsYil9LApBOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILmE4KGEpLmgoIn4obC5FKSIp
-LmIoYikKdD10aGlzLmdtKGEpCmZvcihzPTA7czx0Oysrcyl7Yi4kMSh0aGlzLmooYSxzKSkKaWYodCE9
-PXRoaXMuZ20oYSkpdGhyb3cgSC5hKFAuYXYoYSkpfX0sCmFGOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1I
-LmE4KGEpCnJldHVybiBuZXcgSC5hNChhLHQuRShjKS5oKCIxKGwuRSkiKS5iKGIpLHQuaCgiQDxsLkU+
-IikuRShjKS5oKCJhNDwxLDI+IikpfSwKY2I6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKSC5hOChhKS5o
-KCJsLkUiKS5iKGQpClAuYVYoYixjLHRoaXMuZ20oYSkpCmZvcih0PWI7dDxjOysrdCl0aGlzLmwoYSx0
-LGQpfSwKaTpmdW5jdGlvbihhKXtyZXR1cm4gUC5lNihhLCJbIiwiXSIpfX0KUC5iUC5wcm90b3R5cGU9
-e30KUC5lYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5hCmlmKCFzLmEp
-dGhpcy5iLmErPSIsICIKcy5hPSExCnM9dGhpcy5iCnQ9cy5hKz1ILmIoYSkKcy5hPXQrIjogIgpzLmEr
-PUguYihiKX0sCiRTOjJ9ClAuQi5wcm90b3R5cGU9ewpBOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnYo
-dGhpcykuaCgifihCLkssQi5WKSIpLmIoYikKZm9yKHQ9Si5hOSh0aGlzLmdKKCkpO3QucCgpOyl7cz10
-Lmd1KCkKYi4kMihzLHRoaXMuaigwLHMpKX19LApnbTpmdW5jdGlvbihhKXtyZXR1cm4gSi5hdCh0aGlz
-LmdKKCkpfSwKaTpmdW5jdGlvbihhKXtyZXR1cm4gUC5oMyh0aGlzKX0sCiRpeToxfQpQLmNqLnByb3Rv
-dHlwZT17Cmw6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgudih0aGlzKQp0LmQuYihiKQp0LmNoWzFdLmIo
-YykKdGhyb3cgSC5hKFAuTigiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgbWFwIikpfX0KUC5iYy5w
-cm90b3R5cGU9ewpqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5qKDAsYil9LApsOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdD1ILnYodGhpcykKdGhpcy5hLmwoMCx0LmQuYihiKSx0LmNoWzFdLmIoYykpfSwK
-QTpmdW5jdGlvbihhLGIpe3RoaXMuYS5BKDAsSC52KHRoaXMpLmgoIn4oMSwyKSIpLmIoYikpfSwKZ206
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0LmdtKHQpfSwKaTpmdW5jdGlvbihhKXtyZXR1
-cm4gSi5iMih0aGlzLmEpfSwKJGl5OjF9ClAuYXoucHJvdG90eXBlPXt9ClAuYVcucHJvdG90eXBlPXsK
-aTpmdW5jdGlvbihhKXtyZXR1cm4gUC5lNih0aGlzLCJ7IiwifSIpfX0KUC5iVy5wcm90b3R5cGU9eyRp
-ajoxLCRpTToxfQpQLmNkLnByb3RvdHlwZT17Ckk6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1KLmE5
-KEgudih0aGlzKS5oKCJqPDE+IikuYihiKSk7dC5wKCk7KXRoaXMuaygwLHQuZ3UoKSl9LAppOmZ1bmN0
-aW9uKGEpe3JldHVybiBQLmU2KHRoaXMsInsiLCJ9Iil9LApUOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1Q
-LmljKHRoaXMsdGhpcy5yLEgudih0aGlzKS5kKQppZighcy5wKCkpcmV0dXJuIiIKaWYoYj09PSIiKXt0
-PSIiCmRvIHQrPUguYihzLmQpCndoaWxlKHMucCgpKX1lbHNle3Q9SC5iKHMuZCkKZm9yKDtzLnAoKTsp
-dD10K2IrSC5iKHMuZCl9cmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaWo6MSwKJGlNOjF9
-ClAuYzcucHJvdG90eXBlPXt9ClAuY2UucHJvdG90eXBlPXt9ClAuYnEucHJvdG90eXBlPXt9ClAuZHMu
-cHJvdG90eXBlPXsKajpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5iCmlmKHM9PW51bGwpcmV0dXJu
-IHRoaXMuYy5qKDAsYikKZWxzZSBpZih0eXBlb2YgYiE9InN0cmluZyIpcmV0dXJuIG51bGwKZWxzZXt0
-PXNbYl0KcmV0dXJuIHR5cGVvZiB0PT0idW5kZWZpbmVkIj90aGlzLmJSKGIpOnR9fSwKZ206ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuYj09bnVsbD90aGlzLmMuYTp0aGlzLmExKCkubGVuZ3RofSwKZ0o6ZnVu
-Y3Rpb24oKXtpZih0aGlzLmI9PW51bGwpe3ZhciB0PXRoaXMuYwpyZXR1cm4gbmV3IEguYVAodCxILnYo
-dCkuaCgiYVA8MT4iKSl9cmV0dXJuIG5ldyBQLmR0KHRoaXMpfSwKbDpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQscyxyPXRoaXMKaWYoci5iPT1udWxsKXIuYy5sKDAsYixjKQplbHNlIGlmKHIuYV8oYikpe3Q9ci5i
-CnRbYl09YwpzPXIuYQppZihzPT1udWxsP3QhPW51bGw6cyE9PXQpc1tiXT1udWxsfWVsc2Ugci5iWigp
-LmwoMCxiLGMpfSwKYV86ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0aGlzLmMuYV8o
-YSkKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSl9LApB
-OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuY0EuYihiKQppZihwLmI9PW51bGwpcmV0
-dXJuIHAuYy5BKDAsYikKdD1wLmExKCkKZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCnE9cC5i
-W3JdCmlmKHR5cGVvZiBxPT0idW5kZWZpbmVkIil7cT1QLmY2KHAuYVtyXSkKcC5iW3JdPXF9Yi4kMihy
-LHEpCmlmKHQhPT1wLmMpdGhyb3cgSC5hKFAuYXYocCkpfX0sCmExOmZ1bmN0aW9uKCl7dmFyIHQ9dS5q
-LmIodGhpcy5jKQppZih0PT1udWxsKXQ9dGhpcy5jPUgubihPYmplY3Qua2V5cyh0aGlzLmEpLHUucykK
-cmV0dXJuIHR9LApiWjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbz10aGlzCmlmKG8uYj09bnVsbCly
-ZXR1cm4gby5jCnQ9UC5lOSh1Lk4sdS56KQpzPW8uYTEoKQpmb3Iocj0wO3E9cy5sZW5ndGgscjxxOysr
-cil7cD1zW3JdCnQubCgwLHAsby5qKDAscCkpfWlmKHE9PT0wKUMuYi5rKHMsbnVsbCkKZWxzZSBDLmIu
-c20ocywwKQpvLmE9by5iPW51bGwKcmV0dXJuIG8uYz10fSwKYlI6ZnVuY3Rpb24oYSl7dmFyIHQKaWYo
-IU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkpcmV0dXJuIG51bGwK
-dD1QLmY2KHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT10fX0KUC5kdC5wcm90b3R5cGU9ewpnbTpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ20odCl9LApPOmZ1bmN0aW9uKGEsYil7dmFy
-IHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl0PXQuZ0ooKS5PKDAsYikKZWxzZXt0PXQuYTEoKQppZihiPDB8
-fGI+PXQubGVuZ3RoKXJldHVybiBILmkodCxiKQp0PXRbYl19cmV0dXJuIHR9LApnRjpmdW5jdGlvbihh
-KXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXt0PXQuZ0ooKQp0PXQuZ0YodCl9ZWxzZXt0PXQuYTEo
-KQp0PW5ldyBKLmFGKHQsdC5sZW5ndGgsSC5aKHQpLmgoImFGPDE+IikpfXJldHVybiB0fX0KUC5jdy5w
-cm90b3R5cGU9ewpjazpmdW5jdGlvbihhLGEwLGExKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGks
-aCxnLGYsZSxkLGMsYj0iSW52YWxpZCBiYXNlNjQgZW5jb2RpbmcgbGVuZ3RoICIKYTE9UC5hVihhMCxh
-MSxhLmxlbmd0aCkKdD0kLmpkKCkKZm9yKHM9YTAscj1zLHE9bnVsbCxwPS0xLG89LTEsbj0wO3M8YTE7
-cz1tKXttPXMrMQpsPUMuYS50KGEscykKaWYobD09PTM3KXtrPW0rMgppZihrPD1hMSl7aj1ILmZ3KEMu
-YS50KGEsbSkpCmk9SC5mdyhDLmEudChhLG0rMSkpCmg9aioxNitpLShpJjI1NikKaWYoaD09PTM3KWg9
-LTEKbT1rfWVsc2UgaD0tMX1lbHNlIGg9bAppZigwPD1oJiZoPD0xMjcpe2lmKGg8MHx8aD49dC5sZW5n
-dGgpcmV0dXJuIEguaSh0LGgpCmc9dFtoXQppZihnPj0wKXtoPUMuYS52KCJBQkNERUZHSElKS0xNTk9Q
-UVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvIixnKQppZihoPT09
-bCljb250aW51ZQpsPWh9ZWxzZXtpZihnPT09LTEpe2lmKHA8MCl7Zj1xPT1udWxsP251bGw6cS5hLmxl
-bmd0aAppZihmPT1udWxsKWY9MApwPWYrKHMtcikKbz1zfSsrbgppZihsPT09NjEpY29udGludWV9bD1o
-fWlmKGchPT0tMil7aWYocT09bnVsbClxPW5ldyBQLkgoIiIpCnEuYSs9Qy5hLm4oYSxyLHMpCnEuYSs9
-SC5kXyhsKQpyPW0KY29udGludWV9fXRocm93IEguYShQLkEoIkludmFsaWQgYmFzZTY0IGRhdGEiLGEs
-cykpfWlmKHEhPW51bGwpe2Y9cS5hKz1DLmEubihhLHIsYTEpCmU9Zi5sZW5ndGgKaWYocD49MClQLmhJ
-KGEsbyxhMSxwLG4sZSkKZWxzZXtkPUMuYy5hayhlLTEsNCkrMQppZihkPT09MSl0aHJvdyBILmEoUC5B
-KGIsYSxhMSkpCmZvcig7ZDw0Oyl7Zis9Ij0iCnEuYT1mOysrZH19Zj1xLmEKcmV0dXJuIEMuYS5hMChh
-LGEwLGExLGYuY2hhckNvZGVBdCgwKT09MD9mOmYpfWM9YTEtYTAKaWYocD49MClQLmhJKGEsbyxhMSxw
-LG4sYykKZWxzZXtkPUMuYy5hayhjLDQpCmlmKGQ9PT0xKXRocm93IEguYShQLkEoYixhLGExKSkKaWYo
-ZD4xKWE9Qy5hLmEwKGEsYTEsYTEsZD09PTI/Ij09IjoiPSIpfXJldHVybiBhfX0KUC5jeC5wcm90b3R5
-cGU9e30KUC5hMi5wcm90b3R5cGU9e30KUC5hSy5wcm90b3R5cGU9e30KUC5jRS5wcm90b3R5cGU9e30K
-UC5jTS5wcm90b3R5cGU9ewphQjpmdW5jdGlvbihhLGIsYyl7dmFyIHQKdS5lcC5iKGMpCnQ9UC5sOChi
-LHRoaXMuZ2M5KCkuYSkKcmV0dXJuIHR9LApnYzk6ZnVuY3Rpb24oKXtyZXR1cm4gQy5TfX0KUC5jTi5w
-cm90b3R5cGU9e30KUC5kZC5wcm90b3R5cGU9ewpnY2E6ZnVuY3Rpb24oKXtyZXR1cm4gQy5MfX0KUC5k
-Zi5wcm90b3R5cGU9ewphQTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9UC5hVigwLG51bGwsYS5nbShhKSks
-cT1yLTAKaWYocT09PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApCnQ9bmV3IFVpbnQ4QXJyYXkocSoz
-KQpzPW5ldyBQLmY0KHQpCmlmKHMuYlEoYSwwLHIpIT09cilzLmI2KGEudigwLHItMSksMCkKcmV0dXJu
-IG5ldyBVaW50OEFycmF5KHQuc3ViYXJyYXkoMCxILmtVKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5mNC5w
-cm90b3R5cGU9ewpiNjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhpcwppZigoYiY2NDUxMik9
-PT01NjMyMClQLmtWKGEsYikKZWxzZXt0PXAuYwpzPXAuYisrCnI9Qy5jLlIoMjI0LGEuYTcoMCwxMikp
-CnE9dC5sZW5ndGgKaWYocz49cSlyZXR1cm4gSC5pKHQscykKdFtzXT1yCnI9cC5iKysKcz1DLmMuUigx
-MjgsYS5hNygwLDYpLlAoMCw2MykpCmlmKHI+PXEpcmV0dXJuIEguaSh0LHIpCnRbcl09cwpzPXAuYisr
-CnI9Qy5jLlIoMTI4LGEuUCgwLDYzKSkKaWYocz49cSlyZXR1cm4gSC5pKHQscykKdFtzXT1yCnJldHVy
-biExfX0sCmJROmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKaWYoYiE9PWMm
-JlAuaXgoYS52KDAsYy0xKSkpLS1jCmZvcih0PW0uYyxzPXQubGVuZ3RoLHI9YjtyPGM7KytyKXtxPWEu
-digwLHIpCmlmKHEuYnMoMCwxMjcpKXtwPW0uYgppZihwPj1zKWJyZWFrCm0uYj1wKzEKQy5hXy5sKHQs
-cCxxKX1lbHNlIGlmKFAuaXgocSkpe2lmKG0uYiszPj1zKWJyZWFrCm89cisxCmlmKG0uYjYocSxhLnYo
-MCxvKSkpcj1vfWVsc2UgaWYocS5icygwLDIwNDcpKXtwPW0uYgpuPXArMQppZihuPj1zKWJyZWFrCm0u
-Yj1uCm49Qy5jLlIoMTkyLHEuYTcoMCw2KSkKaWYocD49cylyZXR1cm4gSC5pKHQscCkKdFtwXT1uCm49
-bS5iKysKcD1DLmMuUigxMjgscS5QKDAsNjMpKQppZihuPj1zKXJldHVybiBILmkodCxuKQp0W25dPXB9
-ZWxzZXtwPW0uYgppZihwKzI+PXMpYnJlYWsKbS5iPXArMQpuPUMuYy5SKDIyNCxxLmE3KDAsMTIpKQpp
-ZihwPj1zKXJldHVybiBILmkodCxwKQp0W3BdPW4Kbj1tLmIrKwpwPUMuYy5SKDEyOCxxLmE3KDAsNiku
-UCgwLDYzKSkKaWYobj49cylyZXR1cm4gSC5pKHQsbikKdFtuXT1wCnA9bS5iKysKbj1DLmMuUigxMjgs
-cS5QKDAsNjMpKQppZihwPj1zKXJldHVybiBILmkodCxwKQp0W3BdPW59fXJldHVybiByfX0KUC5kZS5w
-cm90b3R5cGU9ewphQTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwKdS5MLmIoYSkKdD1Q
-LmthKCExLGEsMCxudWxsKQppZih0IT1udWxsKXJldHVybiB0CnM9UC5hVigwLG51bGwsSi5hdChhKSkK
-cj1QLmlEKGEsMCxzKQppZihyPjApe3E9UC5oNihhLDAscikKaWYocj09PXMpcmV0dXJuIHEKcD1uZXcg
-UC5IKHEpCm89cgpuPSExfWVsc2V7bz0wCnA9bnVsbApuPSEwfWlmKHA9PW51bGwpcD1uZXcgUC5IKCIi
-KQptPW5ldyBQLmYzKCExLHApCm0uYz1uCm0uYzYoYSxvLHMpCmlmKG0uZT4wKXtILmFrKFAuQSgiVW5m
-aW5pc2hlZCBVVEYtOCBvY3RldCBzZXF1ZW5jZSIsYSxzKSkKcC5hKz1ILmRfKDY1NTMzKQptLmY9bS5l
-PW0uZD0wfWw9cC5hCnJldHVybiBsLmNoYXJDb2RlQXQoMCk9PTA/bDpsfX0KUC5mMy5wcm90b3R5cGU9
-ewpjNjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGg9dGhpcyxnPSJC
-YWQgVVRGLTggZW5jb2RpbmcgMHgiCnUuTC5iKGEpCnQ9aC5kCnM9aC5lCnI9aC5mCmguZj1oLmU9aC5k
-PTAKJGxhYmVsMCQwOmZvcihxPUouYV8oYSkscD1oLmIsbz1iOyEwO289ail7JGxhYmVsMSQxOmlmKHM+
-MCl7ZG97aWYobz09PWMpYnJlYWsgJGxhYmVsMCQwCm49cS5qKGEsbykKaWYodHlwZW9mIG4hPT0ibnVt
-YmVyIilyZXR1cm4gbi5QKCkKaWYoKG4mMTkyKSE9PTEyOCl7bT1QLkEoZytDLmMuYTUobiwxNiksYSxv
-KQp0aHJvdyBILmEobSl9ZWxzZXt0PSh0PDw2fG4mNjMpPj4+MDstLXM7KytvfX13aGlsZShzPjApCm09
-ci0xCmlmKG08MHx8bT49NClyZXR1cm4gSC5pKEMudSxtKQppZih0PD1DLnVbbV0pe209UC5BKCJPdmVy
-bG9uZyBlbmNvZGluZyBvZiAweCIrQy5jLmE1KHQsMTYpLGEsby1yLTEpCnRocm93IEguYShtKX1pZih0
-PjExMTQxMTEpe209UC5BKCJDaGFyYWN0ZXIgb3V0c2lkZSB2YWxpZCBVbmljb2RlIHJhbmdlOiAweCIr
-Qy5jLmE1KHQsMTYpLGEsby1yLTEpCnRocm93IEguYShtKX1pZighaC5jfHx0IT09NjUyNzkpcC5hKz1I
-LmRfKHQpCmguYz0hMX1mb3IobT1vPGM7bTspe2w9UC5pRChhLG8sYykKaWYobD4wKXtoLmM9ITEKaz1v
-K2wKcC5hKz1QLmg2KGEsbyxrKQppZihrPT09YylicmVha31lbHNlIGs9bwpqPWsrMQpuPXEuaihhLGsp
-CmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uRCgpCmlmKG48MCl7aT1QLkEoIk5lZ2F0aXZl
-IFVURi04IGNvZGUgdW5pdDogLTB4IitDLmMuYTUoLW4sMTYpLGEsai0xKQp0aHJvdyBILmEoaSl9ZWxz
-ZXtpZigobiYyMjQpPT09MTkyKXt0PW4mMzEKcz0xCnI9MQpjb250aW51ZSAkbGFiZWwwJDB9aWYoKG4m
-MjQwKT09PTIyNCl7dD1uJjE1CnM9MgpyPTIKY29udGludWUgJGxhYmVsMCQwfWlmKChuJjI0OCk9PT0y
-NDAmJm48MjQ1KXt0PW4mNwpzPTMKcj0zCmNvbnRpbnVlICRsYWJlbDAkMH1pPVAuQShnK0MuYy5hNShu
-LDE2KSxhLGotMSkKdGhyb3cgSC5hKGkpfX1icmVhayAkbGFiZWwwJDB9aWYocz4wKXtoLmQ9dApoLmU9
-cwpoLmY9cn19fQpQLmViLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCnUuZm8u
-YihhKQp0PXRoaXMuYgpzPXRoaXMuYQp0LmErPXMuYQpyPXQuYSs9SC5iKGEuYSkKdC5hPXIrIjogIgp0
-LmErPVAuYU0oYikKcy5hPSIsICJ9LAokUzoxN30KUC56LnByb3RvdHlwZT17fQpQLmI3LnByb3RvdHlw
-ZT17Ckc6ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2Yg
-UC5iNyYmdGhpcy5hPT09Yi5hJiYhMH0sCmdxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4o
-dF5DLmMuWih0LDMwKSkmMTA3Mzc0MTgyM30sCmk6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPVAuakQo
-SC5qWih0KSkscj1QLmNDKEgualgodCkpLHE9UC5jQyhILmpUKHQpKSxwPVAuY0MoSC5qVSh0KSksbz1Q
-LmNDKEgualcodCkpLG49UC5jQyhILmpZKHQpKSxtPVAuakUoSC5qVih0KSksbD1zKyItIityKyItIitx
-KyIgIitwKyI6IitvKyI6IituKyIuIittCnJldHVybiBsfX0KUC5ULnByb3RvdHlwZT17fQpQLmI4LnBy
-b3RvdHlwZT17Ckc6ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3Rh
-bmNlb2YgUC5iOCYmdGhpcy5hPT09Yi5hfSwKZ3E6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuYy5ncSh0aGlz
-LmEpfSwKaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1uZXcgUC5kWSgpLHA9dGhpcy5hCmlmKHA8MCly
-ZXR1cm4iLSIrbmV3IFAuYjgoMC1wKS5pKDApCnQ9cS4kMShDLmMuYWIocCw2ZTcpJTYwKQpzPXEuJDEo
-Qy5jLmFiKHAsMWU2KSU2MCkKcj1uZXcgUC5kWCgpLiQxKHAlMWU2KQpyZXR1cm4iIitDLmMuYWIocCwz
-NmU4KSsiOiIrSC5iKHQpKyI6IitILmIocykrIi4iK0guYihyKX19ClAuZFgucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7aWYoYT49MWU1KXJldHVybiIiK2EKaWYoYT49MWU0KXJldHVybiIwIithCmlmKGE+
-PTEwMDApcmV0dXJuIjAwIithCmlmKGE+PTEwMClyZXR1cm4iMDAwIithCmlmKGE+PTEwKXJldHVybiIw
-MDAwIithCnJldHVybiIwMDAwMCIrYX0sCiRTOjEyfQpQLmRZLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
-KGEpe2lmKGE+PTEwKXJldHVybiIiK2EKcmV0dXJuIjAiK2F9LAokUzoxMn0KUC5yLnByb3RvdHlwZT17
-fQpQLmJ3LnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQhPW51bGwpcmV0
-dXJuIkFzc2VydGlvbiBmYWlsZWQ6ICIrUC5hTSh0KQpyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZCJ9fQpQ
-LmJkLnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9mIG51bGwuIn19ClAuYTEu
-cHJvdG90eXBlPXsKZ2FzOmZ1bmN0aW9uKCl7cmV0dXJuIkludmFsaWQgYXJndW1lbnQiKyghdGhpcy5h
-PyIocykiOiIiKX0sCmdhcjpmdW5jdGlvbigpe3JldHVybiIifSwKaTpmdW5jdGlvbihhKXt2YXIgdCxz
-LHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysiKSI6IiIKbz1wLmQKdD1vPT1udWxsPyIi
-OiI6ICIrSC5iKG8pCnM9cC5nYXMoKStuK3QKaWYoIXAuYSlyZXR1cm4gcwpyPXAuZ2FyKCkKcT1QLmFN
-KHAuYikKcmV0dXJuIHMrcisiOiAiK3F9fQpQLmFVLnByb3RvdHlwZT17CmdhczpmdW5jdGlvbigpe3Jl
-dHVybiJSYW5nZUVycm9yIn0sCmdhcjpmdW5jdGlvbigpe3ZhciB0LHMscj10aGlzLmUKaWYocj09bnVs
-bCl7cj10aGlzLmYKdD1yIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gIitILmIocik6
-IiJ9ZWxzZXtzPXRoaXMuZgppZihzPT1udWxsKXQ9IjogTm90IGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0
-byAiK0guYihyKQplbHNlIGlmKHM+cil0PSI6IE5vdCBpbiByYW5nZSAiK0guYihyKSsiLi4iK0guYihz
-KSsiLCBpbmNsdXNpdmUiCmVsc2UgdD1zPHI/IjogVmFsaWQgdmFsdWUgcmFuZ2UgaXMgZW1wdHkiOiI6
-IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILmIocil9cmV0dXJuIHR9fQpQLmNHLnByb3RvdHlwZT17Cmdh
-czpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmdhcjpmdW5jdGlvbigpe3ZhciB0LHM9SC54
-KHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5EKCkKaWYoczwwKXJldHVybiI6
-IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1cm4iOiBubyBp
-bmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAiK0guYih0
-KX0sCmdtOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLmNVLnByb3RvdHlwZT17Cmk6ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxqPW5ldyBQLkgoIiIpCmsuYT0iIgpm
-b3IodD1sLmMscz10Lmxlbmd0aCxyPTAscT0iIixwPSIiO3I8czsrK3IscD0iLCAiKXtvPXRbcl0Kai5h
-PXErcApxPWouYSs9UC5hTShvKQprLmE9IiwgIn1sLmQuQSgwLG5ldyBQLmViKGssaikpCm49UC5hTShs
-LmEpCm09ai5pKDApCnQ9Ik5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIitILmIo
-bC5iLmEpKyInXG5SZWNlaXZlcjogIituKyJcbkFyZ3VtZW50czogWyIrbSsiXSIKcmV0dXJuIHR9fQpQ
-LmRiLnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIlVuc3VwcG9ydGVkIG9wZXJhdGlvbjog
-Iit0aGlzLmF9fQpQLmQ5LnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVy
-biB0IT1udWxsPyJVbmltcGxlbWVudGVkRXJyb3I6ICIrdDoiVW5pbXBsZW1lbnRlZEVycm9yIn19ClAu
-YmgucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1cm4iQmFkIHN0YXRlOiAiK3RoaXMuYX19ClAu
-Y3oucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKaWYodD09bnVsbClyZXR1cm4i
-Q29uY3VycmVudCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbi4iCnJldHVybiJDb25jdXJyZW50
-IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uOiAiK1AuYU0odCkrIi4ifX0KUC5jVy5wcm90b3R5
-cGU9ewppOmZ1bmN0aW9uKGEpe3JldHVybiJPdXQgb2YgTWVtb3J5In0sCiRpcjoxfQpQLmJYLnByb3Rv
-dHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIlN0YWNrIE92ZXJmbG93In0sCiRpcjoxfQpQLmNCLnBy
-b3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0PT1udWxsPyJSZWFkaW5n
-IHN0YXRpYyB2YXJpYWJsZSBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9uIjoiUmVhZGluZyBzdGF0aWMg
-dmFyaWFibGUgJyIrdCsiJyBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9uIn19ClAuZUEucHJvdG90eXBl
-PXsKaTpmdW5jdGlvbihhKXtyZXR1cm4iRXhjZXB0aW9uOiAiK3RoaXMuYX19ClAuZV8ucHJvdG90eXBl
-PXsKaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaD10aGlzLmEsZz0iIiE9
-PWg/IkZvcm1hdEV4Y2VwdGlvbjogIitoOiJGb3JtYXRFeGNlcHRpb24iLGY9dGhpcy5jLGU9dGhpcy5i
-CmlmKHR5cGVvZiBlPT0ic3RyaW5nIil7aWYoZiE9bnVsbCloPWY8MHx8Zj5lLmxlbmd0aAplbHNlIGg9
-ITEKaWYoaClmPW51bGwKaWYoZj09bnVsbCl7dD1lLmxlbmd0aD43OD9DLmEubihlLDAsNzUpKyIuLi4i
-OmUKcmV0dXJuIGcrIlxuIit0fWZvcihzPTEscj0wLHE9ITEscD0wO3A8ZjsrK3Ape289Qy5hLnQoZSxw
-KQppZihvPT09MTApe2lmKHIhPT1wfHwhcSkrK3MKcj1wKzEKcT0hMX1lbHNlIGlmKG89PT0xMyl7Kytz
-CnI9cCsxCnE9ITB9fWc9cz4xP2crKCIgKGF0IGxpbmUgIitzKyIsIGNoYXJhY3RlciAiKyhmLXIrMSkr
-IilcbiIpOmcrKCIgKGF0IGNoYXJhY3RlciAiKyhmKzEpKyIpXG4iKQpuPWUubGVuZ3RoCmZvcihwPWY7
-cDxuOysrcCl7bz1DLmEudihlLHApCmlmKG89PT0xMHx8bz09PTEzKXtuPXAKYnJlYWt9fWlmKG4tcj43
-OClpZihmLXI8NzUpe209cis3NQpsPXIKaz0iIgpqPSIuLi4ifWVsc2V7aWYobi1mPDc1KXtsPW4tNzUK
-bT1uCmo9IiJ9ZWxzZXtsPWYtMzYKbT1mKzM2Cmo9Ii4uLiJ9az0iLi4uIn1lbHNle209bgpsPXIKaz0i
-IgpqPSIifWk9Qy5hLm4oZSxsLG0pCnJldHVybiBnK2sraStqKyJcbiIrQy5hLmFOKCIgIixmLWwray5s
-ZW5ndGgpKyJeXG4ifWVsc2UgcmV0dXJuIGYhPW51bGw/ZysoIiAoYXQgb2Zmc2V0ICIrSC5iKGYpKyIp
-Iik6Z319ClAuYWIucHJvdG90eXBlPXt9ClAuZi5wcm90b3R5cGU9e30KUC5qLnByb3RvdHlwZT17CmFq
-OmZ1bmN0aW9uKGEsYil7dmFyIHQ9SC52KHRoaXMpCnJldHVybiBuZXcgSC5hWSh0aGlzLHQuaCgieihq
-LkUpIikuYihiKSx0LmgoImFZPGouRT4iKSl9LApnbTpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuZ0Yo
-dGhpcykKZm9yKHQ9MDtzLnAoKTspKyt0CnJldHVybiB0fSwKZ1k6ZnVuY3Rpb24oYSl7dmFyIHQscz10
-aGlzLmdGKHRoaXMpCmlmKCFzLnAoKSl0aHJvdyBILmEoSC5oUCgpKQp0PXMuZ3UoKQppZihzLnAoKSl0
-aHJvdyBILmEoSC5qSSgpKQpyZXR1cm4gdH0sCk86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKUC5rMShi
-LCJpbmRleCIpCmZvcih0PXRoaXMuZ0YodGhpcykscz0wO3QucCgpOyl7cj10Lmd1KCkKaWYoYj09PXMp
-cmV0dXJuIHI7KytzfXRocm93IEguYShQLmU1KGIsdGhpcywiaW5kZXgiLG51bGwscykpfSwKaTpmdW5j
-dGlvbihhKXtyZXR1cm4gUC5qSCh0aGlzLCIoIiwiKSIpfX0KUC5SLnByb3RvdHlwZT17fQpQLm0ucHJv
-dG90eXBlPXskaWo6MX0KUC55LnByb3RvdHlwZT17fQpQLnAucHJvdG90eXBlPXsKZ3E6ZnVuY3Rpb24o
-YSl7cmV0dXJuIFAudC5wcm90b3R5cGUuZ3EuY2FsbCh0aGlzLHRoaXMpfSwKaTpmdW5jdGlvbihhKXty
-ZXR1cm4ibnVsbCJ9fQpQLlUucHJvdG90eXBlPXt9ClAudC5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOlAu
-dCwkaXQ6MSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzPT09Yn0sCmdxOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBILmJWKHRoaXMpfSwKaTpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5iKEgu
-ZWYodGhpcykpKyInIn0sCmFoOmZ1bmN0aW9uKGEsYil7dS5vLmIoYikKdGhyb3cgSC5hKFAuaFUodGhp
-cyxiLmdiZygpLGIuZ2JqKCksYi5nYmgoKSkpfSwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
-cy5pKHRoaXMpfX0KUC5NLnByb3RvdHlwZT17fQpQLmFnLnByb3RvdHlwZT17fQpQLmMucHJvdG90eXBl
-PXskaWNYOjF9ClAuSC5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0
-aH0sCmk6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/dDp0
-fSwKJGlrNDoxfQpQLmE2LnByb3RvdHlwZT17fQpQLmVxLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyLHEKdS5mLmIoYSkKSC5vKGIpCnQ9Si5hMChiKS5iZihiLCI9IikKaWYodD09PS0x
-KXtpZihiIT09IiIpYS5sKDAsUC5oZihiLDAsYi5sZW5ndGgsdGhpcy5hLCEwKSwiIil9ZWxzZSBpZih0
-IT09MCl7cz1DLmEubihiLDAsdCkKcj1DLmEuVShiLHQrMSkKcT10aGlzLmEKYS5sKDAsUC5oZihzLDAs
-cy5sZW5ndGgscSwhMCksUC5oZihyLDAsci5sZW5ndGgscSwhMCkpfXJldHVybiBhfSwKJFM6MzV9ClAu
-ZW4ucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmEoUC5BKCJJbGxlZ2FsIElQdjQg
-YWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokUzoxOX0KUC5lby5wcm90b3R5cGU9ewokMjpmdW5jdGlv
-bihhLGIpe3Rocm93IEguYShQLkEoIklsbGVnYWwgSVB2NiBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0s
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLiQyKGEsbnVsbCl9LAokUzoyMH0KUC5lcC5wcm90b3R5
-cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGItYT40KXRoaXMuYS4kMigiYW4gSVB2NiBwYXJ0
-IGNhbiBvbmx5IGNvbnRhaW4gYSBtYXhpbXVtIG9mIDQgaGV4IGRpZ2l0cyIsYSkKdD1QLmRPKEMuYS5u
-KHRoaXMuYixhLGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuRCgpCmlm
-KHQ8MHx8dD42NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBvZiBg
-MHgwLi4weEZGRkZgIixhKQpyZXR1cm4gdH0sCiRTOjI0fQpQLmNrLnByb3RvdHlwZT17CmdicTpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmJ9LApnYUQ6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51
-bGwpcmV0dXJuIiIKaWYoQy5hLkgodCwiWyIpKXJldHVybiBDLmEubih0LDEsdC5sZW5ndGgtMSkKcmV0
-dXJuIHR9LApnYUg6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuIFAuaWso
-dGhpcy5hKQpyZXR1cm4gdH0sCmdhSTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZgpyZXR1cm4gdD09bnVs
-bD8iIjp0fSwKZ2JiOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yCnJldHVybiB0PT1udWxsPyIiOnR9LApn
-YUo6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMKaWYocy5RPT1udWxsKXt0PXMuZgpzLnNiUyhuZXcgUC5h
-eihQLmk3KHQ9PW51bGw/IiI6dCksdS5XKSl9cmV0dXJuIHMuUX0sCmdiYzpmdW5jdGlvbigpe3JldHVy
-biB0aGlzLmMhPW51bGx9LApnYmU6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mIT1udWxsfSwKZ2JkOmZ1
-bmN0aW9uKCl7cmV0dXJuIHRoaXMuciE9bnVsbH0sCmk6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhp
-cyxwPXEueQppZihwPT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09MD9wKyI6IjoiIgpzPXEuYwpyPXM9
-PW51bGwKaWYoIXJ8fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5iCmlmKHQubGVuZ3RoIT09MClwPXAr
-dCsiQCIKaWYoIXIpcCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsiOiIrSC5iKHQpfWVsc2UgcD10CnAr
-PXEuZQp0PXEuZgppZih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxsKXA9cCsiIyIrdApw
-PXEueT1wLmNoYXJDb2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwKRzpmdW5jdGlvbihhLGIpe3ZhciB0
-LHMscj10aGlzCmlmKGI9PW51bGwpcmV0dXJuITEKaWYocj09PWIpcmV0dXJuITAKaWYodS5rLmMoYikp
-aWYoci5hPT09Yi5nYVAoKSlpZihyLmMhPW51bGw9PT1iLmdiYygpKWlmKHIuYj09Yi5nYnEoKSlpZihy
-LmdhRChyKT09Yi5nYUQoYikpaWYoci5nYUgocik9PWIuZ2FIKGIpKWlmKHIuZT09PWIuZ2JpKGIpKXt0
-PXIuZgpzPXQ9PW51bGwKaWYoIXM9PT1iLmdiZSgpKXtpZihzKXQ9IiIKaWYodD09PWIuZ2FJKCkpe3Q9
-ci5yCnM9dD09bnVsbAppZighcz09PWIuZ2JkKCkpe2lmKHMpdD0iIgp0PXQ9PT1iLmdiYigpfWVsc2Ug
-dD0hMX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2Ug
-dD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQpyZXR1cm4gdH0sCmdxOmZ1bmN0aW9uKGEp
-e3ZhciB0PXRoaXMuegpyZXR1cm4gdD09bnVsbD90aGlzLno9Qy5hLmdxKHRoaXMuaSgwKSk6dH0sCnNi
-UzpmdW5jdGlvbihhKXt0aGlzLlE9dS5mLmIoYSl9LAokaWRjOjEsCmdhUDpmdW5jdGlvbigpe3JldHVy
-biB0aGlzLmF9LApnYmk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZX19ClAuZjEucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dGhyb3cgSC5hKFAuQSgiSW52YWxpZCBwb3J0Iix0aGlzLmEsdGhpcy5iKzEp
-KX0sCiRTOjIyfQpQLmYyLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBQLmtSKEMuWCxh
-LEMuZiwhMSl9LAokUzoxM30KUC5lbS5wcm90b3R5cGU9ewpnYnA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIs
-cSxwPXRoaXMsbz1udWxsLG49cC5jCmlmKG4hPW51bGwpcmV0dXJuIG4Kbj1wLmIKaWYoMD49bi5sZW5n
-dGgpcmV0dXJuIEguaShuLDApCnQ9cC5hCm49blswXSsxCnM9Qy5hLmFlKHQsIj8iLG4pCnI9dC5sZW5n
-dGgKaWYocz49MCl7cT1QLmNsKHQscysxLHIsQy5pLCExKQpyPXN9ZWxzZSBxPW8KcmV0dXJuIHAuYz1u
-ZXcgUC5kbSgiZGF0YSIsbyxvLG8sUC5jbCh0LG4scixDLnksITEpLHEsbyl9LAppOmZ1bmN0aW9uKGEp
-e3ZhciB0LHM9dGhpcy5iCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILmkocywwKQp0PXRoaXMuYQpyZXR1
-cm4gc1swXT09PS0xPyJkYXRhOiIrdDp0fX0KUC5mYS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
-ZXR1cm4gbmV3IFVpbnQ4QXJyYXkoOTYpfSwKJFM6NDB9ClAuZjkucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
-b24oYSxiKXt2YXIgdD10aGlzLmEKaWYoYT49dC5sZW5ndGgpcmV0dXJuIEguaSh0LGEpCnQ9dFthXQpK
-LmpuKHQsMCw5NixiKQpyZXR1cm4gdH0sCiRTOjIzfQpQLmZiLnByb3RvdHlwZT17CiQzOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1iLmxlbmd0aCxzPWEubGVuZ3RoLHI9MDtyPHQ7KytyKXtx
-PUMuYS50KGIscileOTYKaWYocT49cylyZXR1cm4gSC5pKGEscSkKYVtxXT1jfX19ClAuZmMucHJvdG90
-eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmZvcih0PUMuYS50KGIsMCkscz1DLmEu
-dChiLDEpLHI9YS5sZW5ndGg7dDw9czsrK3Qpe3E9KHReOTYpPj4+MAppZihxPj1yKXJldHVybiBILmko
-YSxxKQphW3FdPWN9fX0KUC5kei5wcm90b3R5cGU9ewpnYmM6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5j
-PjB9LApnYmU6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1
-cm4gdC5EKCkKcmV0dXJuIHQ8dGhpcy5yfSwKZ2JkOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucjx0aGlz
-LmEubGVuZ3RofSwKZ2JfOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMuYS5IKHRoaXMuYSwi
-aHR0cCIpfSwKZ2IwOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTUmJkMuYS5IKHRoaXMuYSwiaHR0
-cHMiKX0sCmdhUDpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPSJmaWxlIixxPSJwYWNrYWdlIixwPXMu
-YgppZihwPD0wKXJldHVybiIiCnQ9cy54CmlmKHQhPW51bGwpcmV0dXJuIHQKaWYocy5nYl8oKSlwPXMu
-eD0iaHR0cCIKZWxzZSBpZihzLmdiMCgpKXtzLng9Imh0dHBzIgpwPSJodHRwcyJ9ZWxzZSBpZihwPT09
-NCYmQy5hLkgocy5hLHIpKXtzLng9cgpwPXJ9ZWxzZSBpZihwPT09NyYmQy5hLkgocy5hLHEpKXtzLng9
-cQpwPXF9ZWxzZXtwPUMuYS5uKHMuYSwwLHApCnMueD1wfXJldHVybiBwfSwKZ2JxOmZ1bmN0aW9uKCl7
-dmFyIHQ9dGhpcy5jLHM9dGhpcy5iKzMKcmV0dXJuIHQ+cz9DLmEubih0aGlzLmEscyx0LTEpOiIifSwK
-Z2FEOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwpyZXR1cm4gdD4wP0MuYS5uKHRoaXMuYSx0LHRoaXMu
-ZCk6IiJ9LApnYUg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMKaWYoci5jPjApe3Q9ci5kCmlmKHR5
-cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuQigpCnM9ci5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIp
-cmV0dXJuIEguYWoocykKcz10KzE8cwp0PXN9ZWxzZSB0PSExCmlmKHQpe3Q9ci5kCmlmKHR5cGVvZiB0
-IT09Im51bWJlciIpcmV0dXJuIHQuQigpCnJldHVybiBQLmRPKEMuYS5uKHIuYSx0KzEsci5lKSxudWxs
-LG51bGwpfWlmKHIuZ2JfKCkpcmV0dXJuIDgwCmlmKHIuZ2IwKCkpcmV0dXJuIDQ0MwpyZXR1cm4gMH0s
-CmdiaTpmdW5jdGlvbihhKXtyZXR1cm4gQy5hLm4odGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ2FJOmZ1
-bmN0aW9uKCl7dmFyIHQ9dGhpcy5mLHM9dGhpcy5yCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJu
-IHQuRCgpCnJldHVybiB0PHM/Qy5hLm4odGhpcy5hLHQrMSxzKToiIn0sCmdiYjpmdW5jdGlvbigpe3Zh
-ciB0PXRoaXMucixzPXRoaXMuYQpyZXR1cm4gdDxzLmxlbmd0aD9DLmEuVShzLHQrMSk6IiJ9LApnYUo6
-ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5EKCkK
-aWYodD49dGhpcy5yKXJldHVybiBDLloKcmV0dXJuIG5ldyBQLmF6KFAuaTcodGhpcy5nYUkoKSksdS5X
-KX0sCmdxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMueQpyZXR1cm4gdD09bnVsbD90aGlzLnk9Qy5hLmdx
-KHRoaXMuYSk6dH0sCkc6ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCmlmKHRoaXM9PT1i
-KXJldHVybiEwCnJldHVybiB1LmsuYyhiKSYmdGhpcy5hPT09Yi5pKDApfSwKaTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5hfSwKJGlkYzoxfQpQLmRtLnByb3RvdHlwZT17fQpXLmgucHJvdG90eXBlPXt9Clcu
-YjMucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGliMzoxfQpXLmN1
-LnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcuYjUucHJvdG90eXBl
-PXskaWI1OjF9ClcuYUcucHJvdG90eXBlPXskaWFHOjF9ClcuYUgucHJvdG90eXBlPXskaWFIOjF9Clcu
-YWEucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5iQS5wcm90b3R5
-cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmRVLnByb3RvdHlwZT17fQpXLmFM
-LnByb3RvdHlwZT17fQpXLmRWLnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhh
-KX19ClcuYkIucHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgiK0guYihh
-LmxlZnQpKyIsICIrSC5iKGEudG9wKSsiKSAiK0guYihhLndpZHRoKSsiIHggIitILmIoYS5oZWlnaHQp
-fSwKRzpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5jKGIpJiZhLmxl
-ZnQ9PT1iLmxlZnQmJmEudG9wPT09Yi50b3AmJmEud2lkdGg9PT1iLndpZHRoJiZhLmhlaWdodD09PWIu
-aGVpZ2h0fSwKZ3E6ZnVuY3Rpb24oYSl7cmV0dXJuIFcuaWIoQy5lLmdxKGEubGVmdCksQy5lLmdxKGEu
-dG9wKSxDLmUuZ3EoYS53aWR0aCksQy5lLmdxKGEuaGVpZ2h0KSl9LAokaWg1OjF9ClcuZFcucHJvdG90
-eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5hcS5wcm90b3R5cGU9ewpnbTpm
-dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCmo6ZnVuY3Rpb24oYSxiKXt2YXIgdApILngo
-YikKdD10aGlzLmEKaWYoYjwwfHxiPj10Lmxlbmd0aClyZXR1cm4gSC5pKHQsYikKcmV0dXJuIHRoaXMu
-JHRpLmQuYih0W2JdKX0sCmw6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuJHRpLmQuYihjKQp0aHJvdyBILmEo
-UC5OKCJDYW5ub3QgbW9kaWZ5IGxpc3QiKSl9fQpXLnUucHJvdG90eXBlPXsKZ2MwOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgVy5hcChhKX0sCmdDOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5kbihhKX0sCmk6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYWxOYW1lfSwKYnQ6ZnVuY3Rpb24oYSl7dmFyIHQ9ISFhLnNj
-cm9sbEludG9WaWV3SWZOZWVkZWQKaWYodClhLnNjcm9sbEludG9WaWV3SWZOZWVkZWQoKQplbHNlIGEu
-c2Nyb2xsSW50b1ZpZXcoKX0sCks6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoYz09bnVs
-bCl7aWYoZD09bnVsbCl7dD0kLmhOCmlmKHQ9PW51bGwpe3Q9SC5uKFtdLHUuUSkKcz1uZXcgVy5iVSh0
-KQpDLmIuayh0LFcuaWEobnVsbCkpCkMuYi5rKHQsVy5pZSgpKQokLmhOPXMKZD1zfWVsc2UgZD10fXQ9
-JC5oTQppZih0PT1udWxsKXt0PW5ldyBXLmNtKGQpCiQuaE09dApjPXR9ZWxzZXt0LmE9ZApjPXR9fWVs
-c2UgaWYoZCE9bnVsbCl0aHJvdyBILmEoUC5iNCgidmFsaWRhdG9yIGNhbiBvbmx5IGJlIHBhc3NlZCBp
-ZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC5hdz09bnVsbCl7dD1kb2N1bWVudApzPXQuaW1w
-bGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKQokLmF3PXMKJC5mWj1zLmNyZWF0ZVJhbmdl
-KCkKcz0kLmF3LmNyZWF0ZUVsZW1lbnQoImJhc2UiKQp1LnYuYihzKQpzLmhyZWY9dC5iYXNlVVJJCiQu
-YXcuaGVhZC5hcHBlbmRDaGlsZChzKX10PSQuYXcKaWYodC5ib2R5PT1udWxsKXtzPXQuY3JlYXRlRWxl
-bWVudCgiYm9keSIpCnQuYm9keT11LlguYihzKX10PSQuYXcKaWYodS5YLmMoYSkpcj10LmJvZHkKZWxz
-ZXtyPXQuY3JlYXRlRWxlbWVudChhLnRhZ05hbWUpCiQuYXcuYm9keS5hcHBlbmRDaGlsZChyKX1pZigi
-Y3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlJiYhQy5iLnco
-Qy5VLGEudGFnTmFtZSkpeyQuZlouc2VsZWN0Tm9kZUNvbnRlbnRzKHIpCnE9JC5mWi5jcmVhdGVDb250
-ZXh0dWFsRnJhZ21lbnQoYil9ZWxzZXtyLmlubmVySFRNTD1iCnE9JC5hdy5jcmVhdGVEb2N1bWVudEZy
-YWdtZW50KCkKZm9yKDt0PXIuZmlyc3RDaGlsZCx0IT1udWxsOylxLmFwcGVuZENoaWxkKHQpfXQ9JC5h
-dy5ib2R5CmlmKHI9PW51bGw/dCE9bnVsbDpyIT09dClKLmhFKHIpCmMuYU8ocSkKZG9jdW1lbnQuYWRv
-cHROb2RlKHEpCnJldHVybiBxfSwKYzg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLksoYSxiLGMs
-bnVsbCl9LApzYWY6ZnVuY3Rpb24oYSxiKXt0aGlzLmFsKGEsYil9LAphNjpmdW5jdGlvbihhLGIsYyl7
-YS50ZXh0Q29udGVudD1udWxsCmEuYXBwZW5kQ2hpbGQodGhpcy5LKGEsYixudWxsLGMpKX0sCmFsOmZ1
-bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYTYoYSxiLG51bGwpfSwKZ2FHOmZ1bmN0aW9uKGEpe3JldHVy
-biBuZXcgVy5ibihhLCJjbGljayIsITEsdS5DKX0sCiRpdToxLApnYm06ZnVuY3Rpb24oYSl7cmV0dXJu
-IGEudGFnTmFtZX19ClcuZFoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuaC5jKHUu
-Ri5iKGEpKX0sCiRTOjM5fQpXLmQucHJvdG90eXBlPXskaWQ6MX0KVy5xLnByb3RvdHlwZT17CmI3OmZ1
-bmN0aW9uKGEsYixjLGQpe3UuVS5iKGMpCmlmKGMhPW51bGwpdGhpcy5iSShhLGIsYyxkKX0sCmFjOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhpcy5iNyhhLGIsYyxudWxsKX0sCmJJOmZ1bmN0aW9uKGEsYixj
-LGQpe3JldHVybiBhLmFkZEV2ZW50TGlzdGVuZXIoYixILmRNKHUuVS5iKGMpLDEpLGQpfSwKJGlxOjF9
-ClcuYjkucHJvdG90eXBlPXskaWI5OjF9ClcuY0YucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0
-dXJuIGEubGVuZ3RofX0KVy5lMS5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
-dGh9fQpXLmJGLnByb3RvdHlwZT17fQpXLmEzLnByb3RvdHlwZT17CmNsOmZ1bmN0aW9uKGEsYixjLGQp
-e3JldHVybiBhLm9wZW4oYixjLCEwKX0sCiRpYTM6MX0KVy5lMy5wcm90b3R5cGU9ewokMjpmdW5jdGlv
-bihhLGIpe3RoaXMuYS5zZXRSZXF1ZXN0SGVhZGVyKEgubyhhKSxILm8oYikpfSwKJFM6OH0KVy5lNC5w
-cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwCnUucC5iKGEpCnQ9dGhpcy5hCnM9
-dC5zdGF0dXMKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5icigpCnI9cz49MjAwJiZzPDMw
-MApxPXM+MzA3JiZzPDQwMApzPXJ8fHM9PT0wfHxzPT09MzA0fHxxCnA9dGhpcy5iCmlmKHMpe3AuJHRp
-LmgoIjEvIikuYih0KQpzPXAuYQppZihzLmEhPT0wKUguYWsoUC5kMigiRnV0dXJlIGFscmVhZHkgY29t
-cGxldGVkIikpCnMuYkoodCl9ZWxzZSBwLmI5KGEpfSwKJFM6MjZ9ClcuYkcucHJvdG90eXBlPXt9Clcu
-YkgucHJvdG90eXBlPXskaWJIOjF9ClcuYk8ucHJvdG90eXBlPXsKZ2NtOmZ1bmN0aW9uKGEpe2lmKCJv
-cmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILmIoYS5wcm90b2NvbCkrIi8vIitILmIo
-YS5ob3N0KX0sCmk6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpYk86MX0KVy5LLnByb3Rv
-dHlwZT17JGlLOjF9ClcuTy5wcm90b3R5cGU9ewpnWTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEscz10
-LmNoaWxkTm9kZXMubGVuZ3RoCmlmKHM9PT0wKXRocm93IEguYShQLmQyKCJObyBlbGVtZW50cyIpKQpp
-ZihzPjEpdGhyb3cgSC5hKFAuZDIoIk1vcmUgdGhhbiBvbmUgZWxlbWVudCIpKQpyZXR1cm4gdC5maXJz
-dENoaWxkfSwKSTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUuZWguYihiKQp0PWIuYQpzPXRoaXMu
-YQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3RoLHE9MDtxPHI7KytxKXMuYXBwZW5kQ2hp
-bGQodC5maXJzdENoaWxkKQpyZXR1cm59LApsOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCnUuRi5iKGMp
-CnQ9dGhpcy5hCnM9dC5jaGlsZE5vZGVzCmlmKGI8MHx8Yj49cy5sZW5ndGgpcmV0dXJuIEguaShzLGIp
-CnQucmVwbGFjZUNoaWxkKGMsc1tiXSl9LApnRjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEuY2hpbGRO
-b2RlcwpyZXR1cm4gbmV3IFcuYU4odCx0Lmxlbmd0aCxILmE4KHQpLmgoImFOPGFjLkU+IikpfSwKZ206
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jaGlsZE5vZGVzLmxlbmd0aH0sCmo6ZnVuY3Rpb24oYSxi
-KXt2YXIgdApILngoYikKdD10aGlzLmEuY2hpbGROb2RlcwppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVy
-biBILmkodCxiKQpyZXR1cm4gdFtiXX19Clcuay5wcm90b3R5cGU9ewpjbjpmdW5jdGlvbihhKXt2YXIg
-dD1hLnBhcmVudE5vZGUKaWYodCE9bnVsbCl0LnJlbW92ZUNoaWxkKGEpfSwKYk06ZnVuY3Rpb24oYSl7
-dmFyIHQKZm9yKDt0PWEuZmlyc3RDaGlsZCx0IT1udWxsOylhLnJlbW92ZUNoaWxkKHQpfSwKaTpmdW5j
-dGlvbihhKXt2YXIgdD1hLm5vZGVWYWx1ZQpyZXR1cm4gdD09bnVsbD90aGlzLmJ3KGEpOnR9LAokaWs6
-MX0KVy5iVC5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApqOmZ1bmN0
-aW9uKGEsYil7SC54KGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5hKFAuZTUoYixh
-LG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LApsOmZ1bmN0aW9uKGEsYixjKXt1LkYuYihjKQp0
-aHJvdyBILmEoUC5OKCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwK
-TzpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguaShhLGIpCnJldHVybiBh
-W2JdfSwKJGlKOjEsCiRpajoxLAokaW06MX0KVy5iZS5wcm90b3R5cGU9eyRpYmU6MX0KVy5hNS5wcm90
-b3R5cGU9eyRpYTU6MX0KVy5kMS5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
-dGh9fQpXLmJaLnByb3RvdHlwZT17Cks6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZigiY3JlYXRl
-Q29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLmFt
-KGEsYixjLGQpCnQ9Vy5qRigiPHRhYmxlPiIrSC5iKGIpKyI8L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50
-LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzLnRvU3RyaW5nCnQudG9TdHJpbmcKbmV3IFcuTyhzKS5J
-KDAsbmV3IFcuTyh0KSkKcmV0dXJuIHN9fQpXLmQ2LnByb3RvdHlwZT17Cks6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHQscyxyLHEKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdl
-LnByb3RvdHlwZSlyZXR1cm4gdGhpcy5hbShhLGIsYyxkKQp0PWRvY3VtZW50CnM9dC5jcmVhdGVEb2N1
-bWVudEZyYWdtZW50KCkKdD1DLkMuSyh0LmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9T
-dHJpbmcKdD1uZXcgVy5PKHQpCnI9dC5nWSh0KQpyLnRvU3RyaW5nCnQ9bmV3IFcuTyhyKQpxPXQuZ1ko
-dCkKcy50b1N0cmluZwpxLnRvU3RyaW5nCm5ldyBXLk8ocykuSSgwLG5ldyBXLk8ocSkpCnJldHVybiBz
-fX0KVy5kNy5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgppZigiY3JlYXRl
-Q29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLmFt
-KGEsYixjLGQpCnQ9ZG9jdW1lbnQKcz10LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQp0PUMuQy5LKHQu
-Y3JlYXRlRWxlbWVudCgidGFibGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLk8odCkKcj10LmdZ
-KHQpCnMudG9TdHJpbmcKci50b1N0cmluZwpuZXcgVy5PKHMpLkkoMCxuZXcgVy5PKHIpKQpyZXR1cm4g
-c319ClcuYmoucHJvdG90eXBlPXsKYTY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKYS50ZXh0Q29udGVu
-dD1udWxsCnQ9YS5jb250ZW50CnQudG9TdHJpbmcKSi5qayh0KQpzPXRoaXMuSyhhLGIsbnVsbCxjKQph
-LmNvbnRlbnQuYXBwZW5kQ2hpbGQocyl9LAphbDpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmE2KGEs
-YixudWxsKX0sCiRpYmo6MX0KVy5hNy5wcm90b3R5cGU9e30KVy5hQS5wcm90b3R5cGU9eyRpYUE6MSwk
-aWVyOjF9ClcuYWkucHJvdG90eXBlPXskaWFpOjF9ClcuYm0ucHJvdG90eXBlPXskaWJtOjF9ClcuYzMu
-cHJvdG90eXBlPXsKaTpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgiK0guYihhLmxlZnQpKyIs
-ICIrSC5iKGEudG9wKSsiKSAiK0guYihhLndpZHRoKSsiIHggIitILmIoYS5oZWlnaHQpfSwKRzpmdW5j
-dGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5jKGIpJiZhLmxlZnQ9PT1iLmxl
-ZnQmJmEudG9wPT09Yi50b3AmJmEud2lkdGg9PT1iLndpZHRoJiZhLmhlaWdodD09PWIuaGVpZ2h0fSwK
-Z3E6ZnVuY3Rpb24oYSl7cmV0dXJuIFcuaWIoQy5lLmdxKGEubGVmdCksQy5lLmdxKGEudG9wKSxDLmUu
-Z3EoYS53aWR0aCksQy5lLmdxKGEuaGVpZ2h0KSl9fQpXLmM4LnByb3RvdHlwZT17CmdtOmZ1bmN0aW9u
-KGEpe3JldHVybiBhLmxlbmd0aH0sCmo6ZnVuY3Rpb24oYSxiKXtILngoYikKaWYoYj4+PjAhPT1ifHxi
-Pj1hLmxlbmd0aCl0aHJvdyBILmEoUC5lNShiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0s
-Cmw6ZnVuY3Rpb24oYSxiLGMpe3UuRi5iKGMpCnRocm93IEguYShQLk4oIkNhbm5vdCBhc3NpZ24gZWxl
-bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApPOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
-bmd0aClyZXR1cm4gSC5pKGEsYikKcmV0dXJuIGFbYl19LAokaUo6MSwKJGlqOjEsCiRpbToxfQpXLmRp
-LnByb3RvdHlwZT17CkE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwCnUudS5iKGIpCmZvcih0PXRo
-aXMuZ0ooKSxzPXQubGVuZ3RoLHI9dGhpcy5hLHE9MDtxPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAs
-SC5jcikodCksKytxKXtwPXRbcV0KYi4kMihwLHIuZ2V0QXR0cmlidXRlKHApKX19LApnSjpmdW5jdGlv
-bigpe3ZhciB0LHMscixxLHA9dGhpcy5hLmF0dHJpYnV0ZXMsbz1ILm4oW10sdS5zKQpmb3IodD1wLmxl
-bmd0aCxzPXUuaDkscj0wO3I8dDsrK3Ipe2lmKHI+PXAubGVuZ3RoKXJldHVybiBILmkocCxyKQpxPXMu
-YihwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLmIuayhvLHEubmFtZSl9cmV0dXJuIG99fQpX
-LmFwLnByb3RvdHlwZT17Cmo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmdldEF0dHJpYnV0ZShI
-Lm8oYikpfSwKbDpmdW5jdGlvbihhLGIsYyl7dGhpcy5hLnNldEF0dHJpYnV0ZShiLGMpfSwKZ206ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHRoaXMuZ0ooKS5sZW5ndGh9fQpXLmFCLnByb3RvdHlwZT17Cmo6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gdGhpcy5hLmEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5WKEgubyhiKSkp
-fSwKbDpmdW5jdGlvbihhLGIsYyl7dGhpcy5hLmEuc2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5WKGIp
-LGMpfSwKQTpmdW5jdGlvbihhLGIpe3RoaXMuYS5BKDAsbmV3IFcuZXcodGhpcyx1LnUuYihiKSkpfSwK
-Z0o6ZnVuY3Rpb24oKXt2YXIgdD1ILm4oW10sdS5zKQp0aGlzLmEuQSgwLG5ldyBXLmV4KHRoaXMsdCkp
-CnJldHVybiB0fSwKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ0ooKS5sZW5ndGh9LApiNDpmdW5j
-dGlvbihhKXt2YXIgdCxzLHI9SC5uKGEuc3BsaXQoIi0iKSx1LnMpCmZvcih0PTE7dDxyLmxlbmd0aDsr
-K3Qpe3M9clt0XQppZihzLmxlbmd0aD4wKUMuYi5sKHIsdCxzWzBdLnRvVXBwZXJDYXNlKCkrSi5qcyhz
-LDEpKX1yZXR1cm4gQy5iLlQociwiIil9LApWOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAKZm9yKHQ9
-YS5sZW5ndGgscz0wLHI9IiI7czx0Oysrcyl7cT1hW3NdCnA9cS50b0xvd2VyQ2FzZSgpCnI9KHEhPT1w
-JiZzPjA/cisiLSI6cikrcH1yZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn19ClcuZXcucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLmEwKGEpLkgoYSwiZGF0YS0iKSl0aGlzLmIuJDIodGhp
-cy5hLmI0KEMuYS5VKGEsNSkpLGIpfSwKJFM6OH0KVy5leC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
-LGIpe2lmKEouYTAoYSkuSChhLCJkYXRhLSIpKUMuYi5rKHRoaXMuYix0aGlzLmEuYjQoQy5hLlUoYSw1
-KSkpfSwKJFM6OH0KVy5kbi5wcm90b3R5cGU9ewpYOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD1QLmJN
-KHUuTikKZm9yKHQ9dGhpcy5hLmNsYXNzTmFtZS5zcGxpdCgiICIpLHM9dC5sZW5ndGgscj0wO3I8czsr
-K3Ipe3E9Si5kUih0W3JdKQppZihxLmxlbmd0aCE9PTApcC5rKDAscSl9cmV0dXJuIHB9LAphTDpmdW5j
-dGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuVC5iKGEpLlQoMCwiICIpfSwKZ206ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuYS5jbGFzc0xpc3QubGVuZ3RofSwKdzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMu
-YS5jbGFzc0xpc3QuY29udGFpbnMoYikKcmV0dXJuIHR9LAprOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhp
-cy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5hZGQoYikKcmV0dXJuIXN9LApNOmZ1bmN0aW9u
-KGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5yZW1vdmUoYikKcmV0
-dXJuIHN9fQpXLmhfLnByb3RvdHlwZT17fQpXLmM0LnByb3RvdHlwZT17fQpXLmJuLnByb3RvdHlwZT17
-fQpXLmRxLnByb3RvdHlwZT17fQpXLmV6LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0
-aGlzLmEuJDEodS5BLmIoYSkpfSwKJFM6Mjd9ClcuYl8ucHJvdG90eXBlPXsKYkQ6ZnVuY3Rpb24oYSl7
-dmFyIHQKaWYoJC5kci5hPT09MCl7Zm9yKHQ9MDt0PDI2MjsrK3QpJC5kci5sKDAsQy5UW3RdLFcubHIo
-KSkKZm9yKHQ9MDt0PDEyOysrdCkkLmRyLmwoMCxDLm1bdF0sVy5scygpKX19LApXOmZ1bmN0aW9uKGEp
-e3JldHVybiAkLmplKCkudygwLFcuYkQoYSkpfSwKTjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9JC5kci5q
-KDAsSC5iKFcuYkQoYSkpKyI6OiIrYikKaWYodD09bnVsbCl0PSQuZHIuaigwLCIqOjoiK2IpCmlmKHQ9
-PW51bGwpcmV0dXJuITEKcmV0dXJuIEguaGcodC4kNChhLGIsYyx0aGlzKSl9LAokaUc6MX0KVy5hYy5w
-cm90b3R5cGU9ewpnRjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuYU4oYSx0aGlzLmdtKGEpLEguYTgo
-YSkuaCgiYU48YWMuRT4iKSl9fQpXLmJVLnByb3RvdHlwZT17Clc6ZnVuY3Rpb24oYSl7cmV0dXJuIEMu
-Yi5iOCh0aGlzLmEsbmV3IFcuZWQoYSkpfSwKTjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEMuYi5iOCh0
-aGlzLmEsbmV3IFcuZWMoYSxiLGMpKX0sCiRpRzoxfQpXLmVkLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
-KGEpe3JldHVybiB1LmUuYihhKS5XKHRoaXMuYSl9LAokUzoxNH0KVy5lYy5wcm90b3R5cGU9ewokMTpm
-dW5jdGlvbihhKXtyZXR1cm4gdS5lLmIoYSkuTih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxNH0K
-Vy5jZi5wcm90b3R5cGU9ewpiRTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkkoMCxj
-KQp0PWIuYWooMCxuZXcgVy5lVCgpKQpzPWIuYWooMCxuZXcgVy5lVSgpKQp0aGlzLmIuSSgwLHQpCnI9
-dGhpcy5jCnIuSSgwLEMudikKci5JKDAscyl9LApXOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudygw
-LFcuYkQoYSkpfSwKTjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9dGhpcyxzPVcuYkQoYSkscj10LmMKaWYo
-ci53KDAsSC5iKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5jXyhjKQplbHNlIGlmKHIudygwLCIqOjoiK2Ip
-KXJldHVybiB0LmQuY18oYykKZWxzZXtyPXQuYgppZihyLncoMCxILmIocykrIjo6IitiKSlyZXR1cm4h
-MAplbHNlIGlmKHIudygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci53KDAsSC5iKHMpKyI6Oioi
-KSlyZXR1cm4hMAplbHNlIGlmKHIudygwLCIqOjoqIikpcmV0dXJuITB9cmV0dXJuITF9LAokaUc6MX0K
-Vy5lVC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5iLncoQy5tLEgubyhhKSl9LAok
-UzoxMH0KVy5lVS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gQy5iLncoQy5tLEgubyhh
-KSl9LAokUzoxMH0KVy5kQi5wcm90b3R5cGU9ewpOOmZ1bmN0aW9uKGEsYixjKXtpZih0aGlzLmJDKGEs
-YixjKSlyZXR1cm4hMAppZihiPT09InRlbXBsYXRlIiYmYz09PSIiKXJldHVybiEwCmlmKGEuZ2V0QXR0
-cmlidXRlKCJ0ZW1wbGF0ZSIpPT09IiIpcmV0dXJuIHRoaXMuZS53KDAsYikKcmV0dXJuITF9fQpXLmVa
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmIoSC5vKGEpKX0s
-CiRTOjEzfQpXLmRBLnByb3RvdHlwZT17Clc6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5ldy5jKGEpKXJl
-dHVybiExCnQ9dS5nNy5jKGEpCmlmKHQmJlcuYkQoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0dXJuITEK
-aWYodClyZXR1cm4hMApyZXR1cm4hMX0sCk46ZnVuY3Rpb24oYSxiLGMpe2lmKGI9PT0iaXMifHxDLmEu
-SChiLCJvbiIpKXJldHVybiExCnJldHVybiB0aGlzLlcoYSl9LAokaUc6MX0KVy5hTi5wcm90b3R5cGU9
-ewpwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYysxLHI9dC5iCmlmKHM8cil7dC5zYVooSi5mVyh0
-LmEscykpCnQuYz1zCnJldHVybiEwfXQuc2FaKG51bGwpCnQuYz1yCnJldHVybiExfSwKZ3U6ZnVuY3Rp
-b24oKXtyZXR1cm4gdGhpcy5kfSwKc2FaOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5kLmIoYSl9
-LAokaVI6MX0KVy5kbC5wcm90b3R5cGU9eyRpcToxLCRpZXI6MX0KVy5HLnByb3RvdHlwZT17fQpXLmR5
-LnByb3RvdHlwZT17JGlrODoxfQpXLmNtLnByb3RvdHlwZT17CmFPOmZ1bmN0aW9uKGEpe25ldyBXLmY1
-KHRoaXMpLiQyKGEsbnVsbCl9LAphMjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpSi5oRShhKQplbHNl
-IGIucmVtb3ZlQ2hpbGQoYSl9LApiVzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz0hMCxuPW51
-bGwsbT1udWxsCnRyeXtuPUouam8oYSkKbT1uLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnUuaC5iKGEpCnQ9
-ZnVuY3Rpb24oYyl7aWYoIShjLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVy
-biB0cnVlCnZhciBsPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hpbGQhPT1sW2wu
-bGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVuIGluc3RhbmNl
-b2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkpcmV0dXJuIHRy
-dWUKdmFyIGs9MAppZihjLmNoaWxkcmVuKWs9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZhciBqPTA7ajxr
-O2orKyl7dmFyIGk9Yy5jaGlsZHJlbltqXQppZihpLmlkPT0nYXR0cmlidXRlcyd8fGkubmFtZT09J2F0
-dHJpYnV0ZXMnfHxpLmlkPT0nbGFzdENoaWxkJ3x8aS5uYW1lPT0nbGFzdENoaWxkJ3x8aS5pZD09J2No
-aWxkcmVuJ3x8aS5uYW1lPT0nY2hpbGRyZW4nKXJldHVybiB0cnVlfXJldHVybiBmYWxzZX0oYSkKbz1I
-LmRLKHQpPyEwOiEoYS5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKX1jYXRjaChxKXtI
-LlEocSl9cz0iZWxlbWVudCB1bnByaW50YWJsZSIKdHJ5e3M9Si5iMihhKX1jYXRjaChxKXtILlEocSl9
-dHJ5e3I9Vy5iRChhKQp0aGlzLmJWKHUuaC5iKGEpLGIsbyxzLHIsdS5HLmIobiksSC5vKG0pKX1jYXRj
-aChxKXtpZihILlEocSkgaW5zdGFuY2VvZiBQLmExKXRocm93IHEKZWxzZXt0aGlzLmEyKGEsYikKd2lu
-ZG93CnA9IlJlbW92aW5nIGNvcnJ1cHRlZCBlbGVtZW50ICIrSC5iKHMpCmlmKHR5cGVvZiBjb25zb2xl
-IT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHApfX19LApiVjpmdW5jdGlvbihhLGIsYyxk
-LGUsZixnKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzCmlmKGMpe24uYTIoYSxiKQp3aW5kb3cKdD0iUmVt
-b3ZpbmcgZWxlbWVudCBkdWUgdG8gY29ycnVwdGVkIGF0dHJpYnV0ZXMgb24gPCIrZCsiPiIKaWYodHlw
-ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0dXJufWlmKCFu
-LmEuVyhhKSl7bi5hMihhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIGVsZW1lbnQgPCIr
-SC5iKGUpKyI+IGZyb20gIitILmIoYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRv
-dy5jb25zb2xlLndhcm4odCkKcmV0dXJufWlmKGchPW51bGwpaWYoIW4uYS5OKGEsImlzIixnKSl7bi5h
-MihhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIHR5cGUgZXh0ZW5zaW9uIDwiK0guYihl
-KSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNv
-bGUud2Fybih0KQpyZXR1cm59dD1mLmdKKCkKcz1ILm4odC5zbGljZSgwKSxILloodCkuaCgiRjwxPiIp
-KQpmb3Iocj1mLmdKKCkubGVuZ3RoLTEsdD1mLmE7cj49MDstLXIpe2lmKHI+PXMubGVuZ3RoKXJldHVy
-biBILmkocyxyKQpxPXNbcl0KcD1uLmEKbz1KLmp0KHEpCkgubyhxKQppZighcC5OKGEsbyx0LmdldEF0
-dHJpYnV0ZShxKSkpe3dpbmRvdwpwPSJSZW1vdmluZyBkaXNhbGxvd2VkIGF0dHJpYnV0ZSA8IitILmIo
-ZSkrIiAiK3ErJz0iJytILmIodC5nZXRBdHRyaWJ1dGUocSkpKyciPicKaWYodHlwZW9mIGNvbnNvbGUh
-PSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCkKdC5yZW1vdmVBdHRyaWJ1dGUocSl9fWlm
-KHUuYVcuYyhhKSluLmFPKGEuY29udGVudCl9LAokaWpQOjF9ClcuZjUucHJvdG90eXBlPXsKJDI6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPXRoaXMuYQpzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOnAu
-YlcoYSxiKQpicmVhawpjYXNlIDg6Y2FzZSAxMTpjYXNlIDM6Y2FzZSA0OmJyZWFrCmRlZmF1bHQ6cC5h
-MihhLGIpfXQ9YS5sYXN0Q2hpbGQKZm9yKHA9dS5GO251bGwhPXQ7KXtzPW51bGwKdHJ5e3M9dC5wcmV2
-aW91c1NpYmxpbmd9Y2F0Y2gocil7SC5RKHIpCnE9cC5iKHQpCmEucmVtb3ZlQ2hpbGQocSkKdD1udWxs
-CnM9YS5sYXN0Q2hpbGR9aWYodCE9bnVsbCl0aGlzLiQyKHQsYSkKdD1wLmIocyl9fSwKJFM6Mjl9Clcu
-ZGsucHJvdG90eXBlPXt9ClcuZHYucHJvdG90eXBlPXt9ClcuZHcucHJvdG90eXBlPXt9ClcuZEgucHJv
-dG90eXBlPXt9ClcuZEkucHJvdG90eXBlPXt9ClAuZVYucHJvdG90eXBlPXsKYUM6ZnVuY3Rpb24oYSl7
-dmFyIHQscz10aGlzLmEscj1zLmxlbmd0aApmb3IodD0wO3Q8cjsrK3QpaWYoc1t0XT09PWEpcmV0dXJu
-IHQKQy5iLmsocyxhKQpDLmIuayh0aGlzLmIsbnVsbCkKcmV0dXJuIHJ9LAphaTpmdW5jdGlvbihhKXt2
-YXIgdCxzLHIscT10aGlzLHA9e30KaWYoYT09bnVsbClyZXR1cm4gYQppZihILmZkKGEpKXJldHVybiBh
-CmlmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJu
-IGEKaWYoYSBpbnN0YW5jZW9mIFAuYjcpcmV0dXJuIG5ldyBEYXRlKGEuYSkKaWYodS5mdi5jKGEpKXRo
-cm93IEguYShQLmVsKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIFJlZ0V4cCIpKQppZih1LmM4LmMoYSkpcmV0
-dXJuIGEKaWYodS5kLmMoYSkpcmV0dXJuIGEKaWYodS5JLmMoYSkpcmV0dXJuIGEKdD11LmRELmMoYSl8
-fCExCmlmKHQpcmV0dXJuIGEKaWYodS5HLmMoYSkpe3M9cS5hQyhhKQp0PXEuYgppZihzPj10Lmxlbmd0
-aClyZXR1cm4gSC5pKHQscykKcj1wLmE9dFtzXQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5hPXIK
-Qy5iLmwodCxzLHIpCmEuQSgwLG5ldyBQLmVYKHAscSkpCnJldHVybiBwLmF9aWYodS5qLmMoYSkpe3M9
-cS5hQyhhKQpwPXEuYgppZihzPj1wLmxlbmd0aClyZXR1cm4gSC5pKHAscykKcj1wW3NdCmlmKHIhPW51
-bGwpcmV0dXJuIHIKcmV0dXJuIHEuYzcoYSxzKX1pZih1LmVILmMoYSkpe3M9cS5hQyhhKQp0PXEuYgpp
-ZihzPj10Lmxlbmd0aClyZXR1cm4gSC5pKHQscykKcj1wLmI9dFtzXQppZihyIT1udWxsKXJldHVybiBy
-CnI9e30KcC5iPXIKQy5iLmwodCxzLHIpCnEuY2QoYSxuZXcgUC5lWShwLHEpKQpyZXR1cm4gcC5ifXRo
-cm93IEguYShQLmVsKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIG90aGVyIHR5cGUiKSl9LApjNzpmdW5jdGlv
-bihhLGIpe3ZhciB0LHM9Si5hXyhhKSxyPXMuZ20oYSkscT1uZXcgQXJyYXkocikKQy5iLmwodGhpcy5i
-LGIscSkKZm9yKHQ9MDt0PHI7Kyt0KUMuYi5sKHEsdCx0aGlzLmFpKHMuaihhLHQpKSkKcmV0dXJuIHF9
-fQpQLmVYLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmFbYV09dGhpcy5iLmFpKGIp
-fSwKJFM6Mn0KUC5lWS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5iW2FdPXRoaXMu
-Yi5haShiKX0sCiRTOjJ9ClAuZVcucHJvdG90eXBlPXsKY2Q6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIs
-cQp1LmI4LmIoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT10
-W3JdCmIuJDIocSxhW3FdKX19fQpQLmNBLnByb3RvdHlwZT17CmF5OmZ1bmN0aW9uKGEpe3ZhciB0PSQu
-ajEoKS5iCmlmKHQudGVzdChhKSlyZXR1cm4gYQp0aHJvdyBILmEoUC5mWChhLCJ2YWx1ZSIsIk5vdCBh
-IHZhbGlkIGNsYXNzIHRva2VuIikpfSwKaTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5YKCkuVCgwLCIg
-Iil9LApnRjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLlgoKQpyZXR1cm4gUC5pYyh0LHQucixILnYodCku
-ZCl9LApnbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5YKCkuYX0sCnc6ZnVuY3Rpb24oYSxiKXt0aGlz
-LmF5KGIpCnJldHVybiB0aGlzLlgoKS53KDAsYil9LAprOmZ1bmN0aW9uKGEsYil7dGhpcy5heShiKQpy
-ZXR1cm4gSC5oZyh0aGlzLmNqKG5ldyBQLmRUKGIpKSl9LApNOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp0
-aGlzLmF5KGIpCnQ9dGhpcy5YKCkKcz10Lk0oMCxiKQp0aGlzLmFMKHQpCnJldHVybiBzfSwKY2o6ZnVu
-Y3Rpb24oYSl7dmFyIHQscwp1LmNoLmIoYSkKdD10aGlzLlgoKQpzPWEuJDEodCkKdGhpcy5hTCh0KQpy
-ZXR1cm4gc319ClAuZFQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuVC5iKGEpLmso
-MCx0aGlzLmEpfSwKJFM6MzB9ClAuYksucHJvdG90eXBlPXskaWJLOjF9ClAuZjcucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5aLmIoYSkKdD1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0
-aW9uKCl7cmV0dXJuIGIoYyxkLHRoaXMsQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50
-cykpfX0oUC5rVCxhLCExKQpQLmhqKHQsJC5mVigpLGEpCnJldHVybiB0fSwKJFM6NH0KUC5mOC5wcm90
-b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IHRoaXMuYShhKX0sCiRTOjR9ClAuZmcucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmJiKGEpfSwKJFM6MzF9ClAuZmgucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmFPKGEsdS5hbSl9LAokUzozMn0KUC5m
-aS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuWShhKX0sCiRTOjMzfQpQLlku
-cHJvdG90eXBlPXsKajpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIh
-PSJudW1iZXIiKXRocm93IEguYShQLmI0KCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikp
-CnJldHVybiBQLmhoKHRoaXMuYVtiXSl9LApsOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYiE9InN0
-cmluZyImJnR5cGVvZiBiIT0ibnVtYmVyIil0aHJvdyBILmEoUC5iNCgicHJvcGVydHkgaXMgbm90IGEg
-U3RyaW5nIG9yIG51bSIpKQp0aGlzLmFbYl09UC5oaShjKX0sCkc6ZnVuY3Rpb24oYSxiKXtpZihiPT1u
-dWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgUC5ZJiZ0aGlzLmE9PT1iLmF9LAppOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5RKHMp
-CnQ9dGhpcy5iQigwKQpyZXR1cm4gdH19LApjMzpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5hCmlm
-KGI9PW51bGwpdD1udWxsCmVsc2V7dD1ILlooYikKdD1QLmgyKG5ldyBILmE0KGIsdC5oKCJAKDEpIiku
-YihQLmx6KCkpLHQuaCgiYTQ8MSxAPiIpKSwhMCx1LnopfXJldHVybiBQLmhoKHNbYV0uYXBwbHkocyx0
-KSl9LApncTpmdW5jdGlvbihhKXtyZXR1cm4gMH19ClAuYmIucHJvdG90eXBlPXt9ClAuYU8ucHJvdG90
-eXBlPXsKYVU6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWE8MHx8YT49dC5nbSh0KQppZihzKXRocm93
-IEguYShQLkwoYSwwLHQuZ20odCksbnVsbCxudWxsKSl9LApqOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9m
-IGI9PSJudW1iZXIiJiZiPT09Qy5jLmJvKGIpKXRoaXMuYVUoSC54KGIpKQpyZXR1cm4gdGhpcy4kdGku
-ZC5iKHRoaXMuYnooMCxiKSl9LApsOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0aGlzLiR0aS5kLmIoYykK
-dD1DLmMuYm8oYikKaWYoYj09PXQpdGhpcy5hVShiKQp0aGlzLmJBKDAsYixjKX0sCmdtOmZ1bmN0aW9u
-KGEpe3ZhciB0PXRoaXMuYS5sZW5ndGgKaWYodHlwZW9mIHQ9PT0ibnVtYmVyIiYmdD4+PjA9PT10KXJl
-dHVybiB0CnRocm93IEguYShQLmQyKCJCYWQgSnNBcnJheSBsZW5ndGgiKSl9LAokaWo6MSwKJGltOjF9
-ClAuYzUucHJvdG90eXBlPXt9ClAuYmcucHJvdG90eXBlPXskaWJnOjF9ClAuY3YucHJvdG90eXBlPXsK
-WDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcy5hLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSxvPVAu
-Yk0odS5OKQppZihwPT1udWxsKXJldHVybiBvCmZvcih0PXAuc3BsaXQoIiAiKSxzPXQubGVuZ3RoLHI9
-MDtyPHM7KytyKXtxPUouZFIodFtyXSkKaWYocS5sZW5ndGghPT0wKW8uaygwLHEpfXJldHVybiBvfSwK
-YUw6ZnVuY3Rpb24oYSl7dGhpcy5hLnNldEF0dHJpYnV0ZSgiY2xhc3MiLGEuVCgwLCIgIikpfX0KUC5l
-LnByb3RvdHlwZT17CmdDOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5jdihhKX0sCnNhZjpmdW5jdGlv
-bihhLGIpe3RoaXMuYWwoYSxiKX0sCks6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvCmlm
-KGQ9PW51bGwpe3Q9SC5uKFtdLHUuUSkKZD1uZXcgVy5iVSh0KQpDLmIuayh0LFcuaWEobnVsbCkpCkMu
-Yi5rKHQsVy5pZSgpKQpDLmIuayh0LG5ldyBXLmRBKCkpfWM9bmV3IFcuY20oZCkKcz0nPHN2ZyB2ZXJz
-aW9uPSIxLjEiPicrSC5iKGIpKyI8L3N2Zz4iCnQ9ZG9jdW1lbnQKcj10LmJvZHkKcT0ociYmQy5wKS5j
-OChyLHMsYykKcD10LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpxLnRvU3RyaW5nCnQ9bmV3IFcuTyhx
-KQpvPXQuZ1kodCkKZm9yKDt0PW8uZmlyc3RDaGlsZCx0IT1udWxsOylwLmFwcGVuZENoaWxkKHQpCnJl
-dHVybiBwfSwKZ2FHOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5ibihhLCJjbGljayIsITEsdS5DKX0s
-CiRpZToxfQpQLmFoLnByb3RvdHlwZT17JGlqOjEsJGltOjEsJGlXOjF9CkwuZlUucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHQscwp1LlYuYihhKQp0PXRoaXMuYQpzPXRoaXMuYgpMLmh4KHdpbmRv
-dy5sb2NhdGlvbi5wYXRobmFtZSx0LHMsbmV3IEwuZlQodCxzKSkKTC5pTih0aGlzLmMpfSwKJFM6OX0K
-TC5mVC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuZlEod2luZG93LmxvY2F0aW9uLnBhdGhuYW1l
-LHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KTC5mQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-dCxzPXRoaXMKdS5yLmIoYSkKdD1hLnN0YXR1cwppZih0PT09MjAwKXtMLmpfKEMubC5hQigwLGEucmVz
-cG9uc2VUZXh0LG51bGwpKQp0PXMuYQpMLmlQKHQscy5iKQpMLmlaKHMuYyx0KQp0PXMuZAppZih0IT1u
-dWxsKXQuJDAoKX1lbHNlIHdpbmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0gu
-Yih0KSl9LAokUzo1fQpMLmZELnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5mSShhLGIpCndp
-bmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmIodGhpcy5hKSsiOyBwcmV2aWV3IHNlcnZlciBt
-aWdodCBiZSBkaXNjb25uZWN0ZWQuIil9LAokQzoiJDIiLAokUjoyLAokUzoyfQpMLmZTLnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHM9InNlbGVjdGVkLWZpbGUiCnUuaC5iKGEpCmEudG9TdHJp
-bmcKdD1KLkUoYSkKaWYoYS5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5hQihuZXcgVy5hcChhKSku
-VigibmFtZSIpKT09dGhpcy5hLmEpdC5nQyhhKS5rKDAscykKZWxzZSB0LmdDKGEpLk0oMCxzKX0sCiRT
-OjN9CkwuZngucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5oLmIoYSkKJC5qaSgpLnRvU3RyaW5n
-CnUubS5iKCQuamcoKS5qKDAsImhsanMiKSkuYzMoImhpZ2hsaWdodEJsb2NrIixbYV0pfSwKJFM6M30K
-TC5mai5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT0iY29sbGFwc2VkIgp1LlYu
-YihhKQp0PXRoaXMuYQpzPUouRSh0KQpyPXRoaXMuYgppZighcy5nQyh0KS53KDAscSkpe3MuZ0ModCku
-aygwLHEpCkouYWwocikuaygwLHEpfWVsc2V7cy5nQyh0KS5NKDAscSkKSi5hbChyKS5NKDAscSl9fSwK
-JFM6OX0KTC5mcy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuZlEodGhpcy5hLHRoaXMuYix0aGlz
-LmMpfSwKJFM6MH0KTC5mdC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuZlEodGhpcy5hLG51bGws
-bnVsbCl9LAokUzowfQpMLmZ1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXUuci5iKGEp
-LnN0YXR1cwppZih0IT09MjAwKXdpbmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAi
-K0guYih0KSl9LAokUzo1fQpMLmZ2LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5mSShhLGIp
-CndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmIodGhpcy5hLmEpKyI7IHByZXZpZXcgc2Vy
-dmVyIG1pZ2h0IGJlIGRpc2Nvbm5lY3RlZC4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjJ9CkwuZmwucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5kUCh1LmguYihhKSkscz10LiR0aQpzLmgoIn4o
-MSkiKS5iKEwuZlAoKSkKdS5NLmIobnVsbCkKVy5hQyh0LmEsdC5iLEwuZlAoKSwhMSxzLmQpfSwKJFM6
-M30KTC5mbS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5oLmIoYSkKdD1KLmRQ
-KGEpCnM9dC4kdGkKcj1zLmgoIn4oMSkiKS5iKG5ldyBMLmZrKGEpKQp1Lk0uYihudWxsKQpXLmFDKHQu
-YSx0LmIsciwhMSxzLmQpfSwKJFM6M30KTC5may5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LlYu
-YihhKQpMLmlOKHRoaXMuYSl9LAokUzo5fQpMLmZuLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
-ciB0PUouZFAodS5oLmIoYSkpLHM9dC4kdGkKcy5oKCJ+KDEpIikuYihMLmlRKCkpCnUuTS5iKG51bGwp
-ClcuYUModC5hLHQuYixMLmlRKCksITEscy5kKX0sCiRTOjN9CkwuZkUucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7dmFyIHQscyxyCnUuci5iKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7cz1DLmwuYUIo
-MCxhLnJlc3BvbnNlVGV4dCxudWxsKQpyPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIp
-CkouZFEociwiIikKTC5qMChyLHMpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3Rh
-dHVzIG9mICIrSC5iKHQpKX0sCiRTOjV9CkwuZkYucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtM
-LmZJKGEsYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK3RoaXMuYSsiOyBwcmV2aWV3IHNl
-cnZlciBtaWdodCBiZSBkaXNjb25uZWN0ZWQuIil9LAokQzoiJDIiLAokUjoyLAokUzoyfQpMLmZHLnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuci5iKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIw
-MCl7TC5sSShDLmwuYUIoMCxhLnJlc3BvbnNlVGV4dCxudWxsKSkKTC5obygiLmVkaXQtcGFuZWwgLnBh
-bmVsLWNvbnRlbnQiKX1lbHNlIHdpbmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAi
-K0guYih0KSl9LAokUzo1fQpMLmZILnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5mSShhLGIp
-CndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmIodGhpcy5hKSsiOyBwcmV2aWV3IHNlcnZl
-ciBtaWdodCBiZSBkaXNjb25uZWN0ZWQuIil9LAokQzoiJDIiLAokUjoyLAokUzoyfQpMLmZLLnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LkEuYihhKQp0PXdpbmRvdy5sb2NhdGlvbi5w
-YXRobmFtZQpzPUwuZnIod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5mcSh3aW5kb3cubG9jYXRpb24u
-aHJlZikKTC5sQSgpCmlmKHQhPT0iLyImJnQhPT1KLmRSKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5y
-b290IikudGV4dENvbnRlbnQpKUwuaHUodCxzLHIsbmV3IEwuZkoodCxzLHIpKQpMLmlVKCl9LAokUzo2
-fQpMLmZKLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5mUSh0aGlzLmEsdGhpcy5iLHRoaXMuYyl9
-LAokUzowfQpMLmZMLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxCnUuQS5iKGEp
-CnQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5mcih3aW5kb3cubG9jYXRpb24uaHJlZikKcj1M
-LmZxKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQppZih0Lmxlbmd0aD4xKUwuaHUodCxzLHIsbnVsbCkKZWxz
-ZXtxPXUuTgpMLmpfKFAuY08oWyJyZWdpb25zIiwiIiwibmF2Q29udGVudCIsIiJdLHEscSkpCkwuaVoo
-IiZuYnNwOyIsbnVsbCl9fSwKJFM6Nn0KTC5mTS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LkEu
-YihhKQp0aGlzLmEuYmsoTC5pUigpKX0sCiRTOjZ9CkwuZk4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
-YSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaj0iZml4ZWQiCnUuQS5iKGEpCnQ9ZG9jdW1lbnQKcz10
-LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtcGFuZWwiKQpyPXMucXVlcnlTZWxlY3RvcigiLm5hdi1pbm5lciIp
-CnE9dC5xdWVyeVNlbGVjdG9yKCIuaW5mby1wYW5lbCIpCnA9dC5xdWVyeVNlbGVjdG9yKCIucGFuZWwt
-Y29udGFpbmVyIikKbz1DLmUuYTMocy5vZmZzZXRUb3ApCmlmKEMuZS5hMyh3aW5kb3cucGFnZVlPZmZz
-ZXQpPm8pe3Q9Si5FKHIpCmlmKCF0LmdDKHIpLncoMCxqKSl7bj1DLmUuYTMocy5vZmZzZXRXaWR0aCkt
-MTQKbT1zLnN0eWxlCmw9IiIrbisicHgiCm0ud2lkdGg9bAptPXIuc3R5bGUKbD1DLmMuaShuKzcpKyJw
-eCIKbS53aWR0aD1sCnQuZ0MocikuaygwLGopfXQ9Si5FKHApCmlmKCF0LmdDKHApLncoMCxqKSl7az1D
-LmUuYTMocS5vZmZzZXRXaWR0aCkKbT1xLnN0eWxlCmw9IiIraysicHgiCm0ud2lkdGg9bAptPXAuc3R5
-bGUKbD0iIitrKyJweCIKbS53aWR0aD1sCnQuZ0MocCkuaygwLGopfX1lbHNle3Q9Si5FKHIpCmlmKHQu
-Z0MocikudygwLGopKXttPXMuc3R5bGUKbS53aWR0aD0iIgptPXIuc3R5bGUKbS53aWR0aD0iIgp0LmdD
-KHIpLk0oMCxqKX10PUouRShwKQppZih0LmdDKHApLncoMCxqKSl7bT1xLnN0eWxlCm0ud2lkdGg9IiIK
-bT1wLnN0eWxlCm0ud2lkdGg9IiIKdC5nQyhwKS5NKDAsail9fXRoaXMuYS5iayhMLmlSKCkpfSwKJFM6
-Nn0KTC5lMC5wcm90b3R5cGU9e30KTC5jRC5wcm90b3R5cGU9ewpiazpmdW5jdGlvbihhKXt2YXIgdAp1
-Lk0uYihhKQp0PXRoaXMuYgppZih0IT1udWxsKXQuYzQoKQp0aGlzLmI9UC5rNyh0aGlzLmEsYSl9fQpM
-LmNZLnByb3RvdHlwZT17Ck46ZnVuY3Rpb24oYSxiLGMpe3JldHVybiEwfSwKVzpmdW5jdGlvbihhKXty
-ZXR1cm4hMH0sCiRpRzoxfTsoZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUouSS5wcm90b3R5cGUKdC5i
-dz10LmkKdC5idj10LmFoCnQ9Si5heS5wcm90b3R5cGUKdC5ieT10LmkKdD1QLmoucHJvdG90eXBlCnQu
-Yng9dC5hagp0PVAudC5wcm90b3R5cGUKdC5iQj10LmkKdD1XLnUucHJvdG90eXBlCnQuYW09dC5LCnQ9
-Vy5jZi5wcm90b3R5cGUKdC5iQz10Lk4KdD1QLlkucHJvdG90eXBlCnQuYno9dC5qCnQuYkE9dC5sfSko
-KTsoZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmZzKCl7dmFyIHQ9aHVua0hlbHBlcnMuX3N0YXRpY18xLHM9
-aHVua0hlbHBlcnMuX3N0YXRpY18wLHI9aHVua0hlbHBlcnMuaW5zdGFsbEluc3RhbmNlVGVhck9mZixx
-PWh1bmtIZWxwZXJzLmluc3RhbGxTdGF0aWNUZWFyT2ZmCnQoUCwibGgiLCJrZyIsNykKdChQLCJsaSIs
-ImtoIiw3KQp0KFAsImxqIiwia2kiLDcpCnMoUCwiaUkiLCJsYyIsMSkKcihQLmMyLnByb3RvdHlwZSwi
-Z2M1IiwwLDEsbnVsbCxbIiQyIiwiJDEiXSxbImJhIiwiYjkiXSwzNCwwKQpxKFcsImxyIiw0LG51bGws
-WyIkNCJdLFsia2wiXSwxNiwwKQpxKFcsImxzIiw0LG51bGwsWyIkNCJdLFsia20iXSwxNiwwKQp0KFAs
-Imx6IiwiaGkiLDQpCnQoUCwibHkiLCJoaCIsMjgpCnQoTCwiZlAiLCJsbyIsMTUpCnQoTCwiaVEiLCJs
-cCIsMTUpCnMoTCwiaVIiLCJpVSIsMSl9KSgpOyhmdW5jdGlvbiBpbmhlcml0YW5jZSgpe3ZhciB0PWh1
-bmtIZWxwZXJzLm1peGluLHM9aHVua0hlbHBlcnMuaW5oZXJpdCxyPWh1bmtIZWxwZXJzLmluaGVyaXRN
-YW55CnMoUC50LG51bGwpCnIoUC50LFtILmgwLEouSSxKLmFGLFAuYzcsUC5qLEguYVEsUC5SLEguVixI
-LmFYLEguYmksUC5iYyxILmJ5LEguY0osSC5hSSxILmVqLFAucixILmNnLFAuQixILmU4LEguYkwsSC5j
-SyxILmFmLEguZUIsUC5kQyxQLmMyLFAuYVosUC5TLFAuZGgsUC5iWSxQLmQ0LFAuZDUsUC5hdSxQLmRH
-LFAuY2QsUC5kdSxQLmIwLFAubCxQLmNqLFAuYVcsUC5jZSxQLmEyLFAuZjQsUC5mMyxQLnosUC5iNyxQ
-LlUsUC5iOCxQLmNXLFAuYlgsUC5lQSxQLmVfLFAuYWIsUC5tLFAueSxQLnAsUC5hZyxQLmMsUC5ILFAu
-YTYsUC5jayxQLmVtLFAuZHosVy5kVSxXLmhfLFcuYl8sVy5hYyxXLmJVLFcuY2YsVy5kQSxXLmFOLFcu
-ZGwsVy5HLFcuZHksVy5jbSxQLmVWLFAuWSxQLmFoLEwuZTAsTC5jRCxMLmNZXSkKcihKLkksW0ouY0gs
-Si5iSixKLmF5LEouRixKLmJhLEouYXgsSC5DLFcucSxXLmFHLFcuZGssVy5kVixXLmJCLFcuZFcsVy5k
-LFcuZTEsVy5iSCxXLmJPLFcuZHYsVy5kSCxQLmJLXSkKcihKLmF5LFtKLmNaLEouYmssSi5hZF0pCnMo
-Si5lNyxKLkYpCnIoSi5iYSxbSi5iSSxKLmNJXSkKcyhQLmJOLFAuYzcpCnIoUC5iTixbSC5ibCxXLmFx
-LFcuT10pCnMoSC5jeSxILmJsKQpyKFAuaixbSC5iQyxILmFZXSkKcihILmJDLFtILmFlLEguYVAsUC5N
-XSkKcihILmFlLFtILmE0LFAuZHRdKQpzKEguY18sUC5SKQpzKFAuYnEsUC5iYykKcyhQLmF6LFAuYnEp
-CnMoSC5ieixQLmF6KQpzKEguYUosSC5ieSkKcihILmFJLFtILmVlLEguZlIsSC5kOCxILmZ5LEguZnos
-SC5mQSxQLmV0LFAuZXMsUC5ldSxQLmV2LFAuZl8sUC5lQyxQLmVLLFAuZUcsUC5lSCxQLmVJLFAuZUUs
-UC5lSixQLmVELFAuZU4sUC5lTyxQLmVNLFAuZUwsUC5laCxQLmVpLFAuZmYsUC5lUixQLmVRLFAuZVMs
-UC5lYSxQLmViLFAuZFgsUC5kWSxQLmVxLFAuZW4sUC5lbyxQLmVwLFAuZjEsUC5mMixQLmZhLFAuZjks
-UC5mYixQLmZjLFcuZFosVy5lMyxXLmU0LFcuZXcsVy5leCxXLmV6LFcuZWQsVy5lYyxXLmVULFcuZVUs
-Vy5lWixXLmY1LFAuZVgsUC5lWSxQLmRULFAuZjcsUC5mOCxQLmZnLFAuZmgsUC5maSxMLmZVLEwuZlQs
-TC5mQyxMLmZELEwuZlMsTC5meCxMLmZqLEwuZnMsTC5mdCxMLmZ1LEwuZnYsTC5mbCxMLmZtLEwuZmss
-TC5mbixMLmZFLEwuZkYsTC5mRyxMLmZILEwuZkssTC5mSixMLmZMLEwuZk0sTC5mTl0pCnIoUC5yLFtI
-LmNWLEguY0wsSC5kYSxILmQwLFAuYncsSC5kcCxQLmJkLFAuYTEsUC5jVSxQLmRiLFAuZDksUC5iaCxQ
-LmN6LFAuY0JdKQpyKEguZDgsW0guZDMsSC5iNl0pCnMoSC5kZyxQLmJ3KQpzKFAuYlAsUC5CKQpyKFAu
-YlAsW0guYW4sUC5kcyxXLmRpLFcuYUJdKQpzKEguYlEsSC5DKQpyKEguYlEsW0guYzksSC5jYl0pCnMo
-SC5jYSxILmM5KQpzKEguYVIsSC5jYSkKcyhILmNjLEguY2IpCnMoSC5iUixILmNjKQpyKEguYlIsW0gu
-Y1AsSC5jUSxILmNSLEguY1MsSC5jVCxILmJTLEguYVNdKQpyKEguZHAsW0guYzEsSC5jaF0pCnMoUC5j
-MCxQLmMyKQpzKFAuZHgsUC5kRykKcyhQLmM2LFAuY2QpCnMoUC5iVyxQLmNlKQpyKFAuYTIsW1AuY3cs
-UC5jRSxQLmNNXSkKcyhQLmFLLFAuZDUpCnIoUC5hSyxbUC5jeCxQLmNOLFAuZGYsUC5kZV0pCnMoUC5k
-ZCxQLmNFKQpyKFAuVSxbUC5ULFAuZl0pCnIoUC5hMSxbUC5hVSxQLmNHXSkKcyhQLmRtLFAuY2spCnIo
-Vy5xLFtXLmssVy5iRyxXLmFBLFcuYWldKQpyKFcuayxbVy51LFcuYWEsVy5hTCxXLmJtXSkKcihXLnUs
-W1cuaCxQLmVdKQpyKFcuaCxbVy5iMyxXLmN1LFcuYjUsVy5hSCxXLmNGLFcuYmUsVy5kMSxXLmJaLFcu
-ZDYsVy5kNyxXLmJqXSkKcyhXLmJBLFcuZGspCnMoVy5iOSxXLmFHKQpzKFcuYkYsVy5hTCkKcyhXLmEz
-LFcuYkcpCnIoVy5kLFtXLmE3LFcuYTVdKQpzKFcuSyxXLmE3KQpzKFcuZHcsVy5kdikKcyhXLmJULFcu
-ZHcpCnMoVy5jMyxXLmJCKQpzKFcuZEksVy5kSCkKcyhXLmM4LFcuZEkpCnMoVy5hcCxXLmRpKQpzKFAu
-Y0EsUC5iVykKcihQLmNBLFtXLmRuLFAuY3ZdKQpzKFcuYzQsUC5iWSkKcyhXLmJuLFcuYzQpCnMoVy5k
-cSxQLmQ0KQpzKFcuZEIsVy5jZikKcyhQLmVXLFAuZVYpCnIoUC5ZLFtQLmJiLFAuYzVdKQpzKFAuYU8s
-UC5jNSkKcyhQLmJnLFAuZSkKdChILmJsLEguYVgpCnQoSC5jOSxQLmwpCnQoSC5jYSxILlYpCnQoSC5j
-YixQLmwpCnQoSC5jYyxILlYpCnQoUC5jNyxQLmwpCnQoUC5jZSxQLmFXKQp0KFAuYnEsUC5jaikKdChX
-LmRrLFcuZFUpCnQoVy5kdixQLmwpCnQoVy5kdyxXLmFjKQp0KFcuZEgsUC5sKQp0KFcuZEksVy5hYykK
-dChQLmM1LFAubCl9KSgpCnZhciB2PXt0eXBlVW5pdmVyc2U6e2VDOm5ldyBNYXAoKSx0Ujp7fSxlVDp7
-fSx0UFY6e30sc0VBOltdfSxtYW5nbGVkR2xvYmFsTmFtZXM6e2Y6ImludCIsVDoiZG91YmxlIixVOiJu
-dW0iLGM6IlN0cmluZyIsejoiYm9vbCIscDoiTnVsbCIsbToiTGlzdCJ9LG1hbmdsZWROYW1lczp7fSxn
-ZXRUeXBlRnJvbU5hbWU6Z2V0R2xvYmFsRnJvbU5hbWUsbWV0YWRhdGE6W10sdHlwZXM6WyJwKCkiLCJ+
-KCkiLCJwKEAsQCkiLCJwKHUpIiwiQChAKSIsInAoYTMpIiwicChkKSIsIn4ofigpKSIsInAoYyxjKSIs
-InAoSykiLCJ6KGMpIiwicChAKSIsImMoZikiLCJjKGMpIiwieihHKSIsIn4oSykiLCJ6KHUsYyxjLGJf
-KSIsInAoYTYsQCkiLCJwKGMsQCkiLCJ+KGMsZikiLCJ+KGNbQF0pIiwiQChALGMpIiwicChjKSIsImFo
-KEAsQCkiLCJmKGYsZikiLCJAKGMpIiwicChhNSkiLCJAKGQpIiwidChAKSIsIn4oayxrKSIsInooTTxj
-PikiLCJiYihAKSIsImFPPEA+KEApIiwiWShAKSIsIn4odFthZ10pIiwieTxjLGM+KHk8YyxjPixjKSIs
-InAofigpKSIsInAoQFthZ10pIiwiUzxAPihAKSIsInooaykiLCJhaChmKSJdLGludGVyY2VwdG9yc0J5
-VGFnOm51bGwsbGVhZlRhZ3M6bnVsbH0KSC5reih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7ImFk
-IjoiYXkiLCJjWiI6ImF5IiwiYmsiOiJheSIsImxLIjoiZCIsImxTIjoiZCIsImxKIjoiZSIsImxUIjoi
-ZSIsIm1oIjoiYTUiLCJsTCI6ImgiLCJsViI6ImgiLCJtXyI6ImsiLCJsUiI6ImsiLCJtYyI6ImFMIiwi
-bFoiOiJLIiwibE4iOiJhNyIsImxRIjoiYWkiLCJsTSI6ImFhIiwibTAiOiJhYSIsImxYIjoiYVIiLCJs
-VyI6IkMiLCJjSCI6eyJ6IjpbXX0sImJKIjp7InAiOltdfSwiYXkiOnsiaFEiOltdLCJhYiI6W119LCJG
-Ijp7Im0iOlsiMSJdLCJqIjpbIjEiXX0sImU3Ijp7IkYiOlsiMSJdLCJtIjpbIjEiXSwiaiI6WyIxIl19
-LCJhRiI6eyJSIjpbIjEiXX0sImJhIjp7IlQiOltdLCJVIjpbXX0sImJJIjp7ImYiOltdLCJUIjpbXSwi
-VSI6W119LCJjSSI6eyJUIjpbXSwiVSI6W119LCJheCI6eyJjIjpbXSwiY1giOltdfSwiY3kiOnsiYVgi
-OlsiZiJdLCJsIjpbImYiXSwibSI6WyJmIl0sImoiOlsiZiJdLCJsLkUiOiJmIiwiYVguRSI6ImYifSwi
-YkMiOnsiaiI6WyIxIl19LCJhZSI6eyJqIjpbIjEiXX0sImFRIjp7IlIiOlsiMSJdfSwiYTQiOnsiYWUi
-OlsiMiJdLCJqIjpbIjIiXSwiYWUuRSI6IjIiLCJqLkUiOiIyIn0sImFZIjp7ImoiOlsiMSJdLCJqLkUi
-OiIxIn0sImNfIjp7IlIiOlsiMSJdfSwiYmwiOnsiYVgiOlsiMSJdLCJsIjpbIjEiXSwibSI6WyIxIl0s
-ImoiOlsiMSJdfSwiYmkiOnsiYTYiOltdfSwiYnoiOnsiYXoiOlsiMSIsIjIiXSwiYnEiOlsiMSIsIjIi
-XSwiYmMiOlsiMSIsIjIiXSwiY2oiOlsiMSIsIjIiXSwieSI6WyIxIiwiMiJdfSwiYnkiOnsieSI6WyIx
-IiwiMiJdfSwiYUoiOnsiYnkiOlsiMSIsIjIiXSwieSI6WyIxIiwiMiJdfSwiY0oiOnsiaE8iOltdfSwi
-Y1YiOnsiciI6W119LCJjTCI6eyJyIjpbXX0sImRhIjp7InIiOltdfSwiY2ciOnsiYWciOltdfSwiYUki
-OnsiYWIiOltdfSwiZDgiOnsiYWIiOltdfSwiZDMiOnsiYWIiOltdfSwiYjYiOnsiYWIiOltdfSwiZDAi
-OnsiciI6W119LCJkZyI6eyJyIjpbXX0sImFuIjp7ImhTIjpbIjEiLCIyIl0sIkIiOlsiMSIsIjIiXSwi
-eSI6WyIxIiwiMiJdLCJCLksiOiIxIiwiQi5WIjoiMiJ9LCJhUCI6eyJqIjpbIjEiXSwiai5FIjoiMSJ9
-LCJiTCI6eyJSIjpbIjEiXX0sImNLIjp7ImhaIjpbXSwiY1giOltdfSwiQyI6eyJXIjpbXX0sImJRIjp7
-IkoiOlsiQCJdLCJDIjpbXSwiVyI6W119LCJhUiI6eyJsIjpbIlQiXSwiSiI6WyJAIl0sIm0iOlsiVCJd
-LCJDIjpbXSwiViI6WyJUIl0sIlciOltdLCJqIjpbIlQiXSwibC5FIjoiVCJ9LCJiUiI6eyJsIjpbImYi
-XSwibSI6WyJmIl0sIkoiOlsiQCJdLCJDIjpbXSwiViI6WyJmIl0sIlciOltdLCJqIjpbImYiXX0sImNQ
-Ijp7ImwiOlsiZiJdLCJtIjpbImYiXSwiSiI6WyJAIl0sIkMiOltdLCJWIjpbImYiXSwiVyI6W10sImoi
-OlsiZiJdLCJsLkUiOiJmIn0sImNRIjp7ImwiOlsiZiJdLCJtIjpbImYiXSwiSiI6WyJAIl0sIkMiOltd
-LCJWIjpbImYiXSwiVyI6W10sImoiOlsiZiJdLCJsLkUiOiJmIn0sImNSIjp7ImwiOlsiZiJdLCJtIjpb
-ImYiXSwiSiI6WyJAIl0sIkMiOltdLCJWIjpbImYiXSwiVyI6W10sImoiOlsiZiJdLCJsLkUiOiJmIn0s
-ImNTIjp7ImwiOlsiZiJdLCJtIjpbImYiXSwiSiI6WyJAIl0sIkMiOltdLCJWIjpbImYiXSwiVyI6W10s
-ImoiOlsiZiJdLCJsLkUiOiJmIn0sImNUIjp7ImwiOlsiZiJdLCJtIjpbImYiXSwiSiI6WyJAIl0sIkMi
-OltdLCJWIjpbImYiXSwiVyI6W10sImoiOlsiZiJdLCJsLkUiOiJmIn0sImJTIjp7ImwiOlsiZiJdLCJt
-IjpbImYiXSwiSiI6WyJAIl0sIkMiOltdLCJWIjpbImYiXSwiVyI6W10sImoiOlsiZiJdLCJsLkUiOiJm
-In0sImFTIjp7ImFoIjpbXSwibCI6WyJmIl0sIm0iOlsiZiJdLCJKIjpbIkAiXSwiQyI6W10sIlYiOlsi
-ZiJdLCJXIjpbXSwiaiI6WyJmIl0sImwuRSI6ImYifSwiZHAiOnsiciI6W119LCJjMSI6eyJyIjpbXX0s
-ImNoIjp7InIiOltdfSwiZEMiOnsiazYiOltdfSwiYzAiOnsiYzIiOlsiMSJdfSwiUyI6eyJiRSI6WyIx
-Il19LCJhdSI6eyJyIjpbXX0sImRHIjp7Imk4IjpbXX0sImR4Ijp7Imk4IjpbXX0sImM2Ijp7ImNkIjpb
-IjEiXSwiTSI6WyIxIl0sImoiOlsiMSJdfSwiYjAiOnsiUiI6WyIxIl19LCJiTiI6eyJsIjpbIjEiXSwi
-bSI6WyIxIl0sImoiOlsiMSJdfSwiYlAiOnsiQiI6WyIxIiwiMiJdLCJ5IjpbIjEiLCIyIl19LCJCIjp7
-InkiOlsiMSIsIjIiXX0sImJjIjp7InkiOlsiMSIsIjIiXX0sImF6Ijp7ImJxIjpbIjEiLCIyIl0sImJj
-IjpbIjEiLCIyIl0sImNqIjpbIjEiLCIyIl0sInkiOlsiMSIsIjIiXX0sImJXIjp7ImFXIjpbIjEiXSwi
-TSI6WyIxIl0sImoiOlsiMSJdfSwiY2QiOnsiTSI6WyIxIl0sImoiOlsiMSJdfSwiZHMiOnsiQiI6WyJj
-IiwiQCJdLCJ5IjpbImMiLCJAIl0sIkIuSyI6ImMiLCJCLlYiOiJAIn0sImR0Ijp7ImFlIjpbImMiXSwi
-aiI6WyJjIl0sImFlLkUiOiJjIiwiai5FIjoiYyJ9LCJjdyI6eyJhMiI6WyJtPGY+IiwiYyJdLCJhMi5T
-IjoibTxmPiJ9LCJjeCI6eyJhSyI6WyJtPGY+IiwiYyJdfSwiY0UiOnsiYTIiOlsiYyIsIm08Zj4iXX0s
-ImNNIjp7ImEyIjpbInQiLCJjIl0sImEyLlMiOiJ0In0sImNOIjp7ImFLIjpbImMiLCJ0Il19LCJkZCI6
-eyJhMiI6WyJjIiwibTxmPiJdLCJhMi5TIjoiYyJ9LCJkZiI6eyJhSyI6WyJjIiwibTxmPiJdfSwiZGUi
-OnsiYUsiOlsibTxmPiIsImMiXX0sIlQiOnsiVSI6W119LCJidyI6eyJyIjpbXX0sImJkIjp7InIiOltd
-fSwiYTEiOnsiciI6W119LCJhVSI6eyJyIjpbXX0sImNHIjp7InIiOltdfSwiY1UiOnsiciI6W119LCJk
-YiI6eyJyIjpbXX0sImQ5Ijp7InIiOltdfSwiYmgiOnsiciI6W119LCJjeiI6eyJyIjpbXX0sImNXIjp7
-InIiOltdfSwiYlgiOnsiciI6W119LCJjQiI6eyJyIjpbXX0sImYiOnsiVSI6W119LCJtIjp7ImoiOlsi
-MSJdfSwiTSI6eyJqIjpbIjEiXX0sImMiOnsiY1giOltdfSwiSCI6eyJrNCI6W119LCJjayI6eyJkYyI6
-W119LCJkeiI6eyJkYyI6W119LCJkbSI6eyJkYyI6W119LCJoIjp7InUiOltdLCJrIjpbXSwicSI6W119
-LCJiMyI6eyJ1IjpbXSwiayI6W10sInEiOltdfSwiY3UiOnsidSI6W10sImsiOltdLCJxIjpbXX0sImI1
-Ijp7InUiOltdLCJrIjpbXSwicSI6W119LCJhSCI6eyJ1IjpbXSwiayI6W10sInEiOltdfSwiYWEiOnsi
-ayI6W10sInEiOltdfSwiYUwiOnsiayI6W10sInEiOltdfSwiYkIiOnsiaDUiOlsiVSJdfSwiYXEiOnsi
-bCI6WyIxIl0sIm0iOlsiMSJdLCJqIjpbIjEiXSwibC5FIjoiMSJ9LCJ1Ijp7ImsiOltdLCJxIjpbXX0s
-ImI5Ijp7ImFHIjpbXX0sImNGIjp7InUiOltdLCJrIjpbXSwicSI6W119LCJiRiI6eyJrIjpbXSwicSI6
-W119LCJhMyI6eyJxIjpbXX0sImJHIjp7InEiOltdfSwiSyI6eyJkIjpbXX0sIk8iOnsibCI6WyJrIl0s
-Im0iOlsiayJdLCJqIjpbImsiXSwibC5FIjoiayJ9LCJrIjp7InEiOltdfSwiYlQiOnsiYWMiOlsiayJd
-LCJsIjpbImsiXSwibSI6WyJrIl0sIkoiOlsiayJdLCJqIjpbImsiXSwibC5FIjoiayIsImFjLkUiOiJr
-In0sImJlIjp7InUiOltdLCJrIjpbXSwicSI6W119LCJhNSI6eyJkIjpbXX0sImQxIjp7InUiOltdLCJr
-IjpbXSwicSI6W119LCJiWiI6eyJ1IjpbXSwiayI6W10sInEiOltdfSwiZDYiOnsidSI6W10sImsiOltd
-LCJxIjpbXX0sImQ3Ijp7InUiOltdLCJrIjpbXSwicSI6W119LCJiaiI6eyJ1IjpbXSwiayI6W10sInEi
-OltdfSwiYTciOnsiZCI6W119LCJhQSI6eyJlciI6W10sInEiOltdfSwiYWkiOnsicSI6W119LCJibSI6
-eyJrIjpbXSwicSI6W119LCJjMyI6eyJoNSI6WyJVIl19LCJjOCI6eyJhYyI6WyJrIl0sImwiOlsiayJd
-LCJtIjpbImsiXSwiSiI6WyJrIl0sImoiOlsiayJdLCJsLkUiOiJrIiwiYWMuRSI6ImsifSwiZGkiOnsi
-QiI6WyJjIiwiYyJdLCJ5IjpbImMiLCJjIl19LCJhcCI6eyJCIjpbImMiLCJjIl0sInkiOlsiYyIsImMi
-XSwiQi5LIjoiYyIsIkIuViI6ImMifSwiYUIiOnsiQiI6WyJjIiwiYyJdLCJ5IjpbImMiLCJjIl0sIkIu
-SyI6ImMiLCJCLlYiOiJjIn0sImRuIjp7ImFXIjpbImMiXSwiTSI6WyJjIl0sImoiOlsiYyJdfSwiYzQi
-OnsiYlkiOlsiMSJdfSwiYm4iOnsiYzQiOlsiMSJdLCJiWSI6WyIxIl19LCJiXyI6eyJHIjpbXX0sImJV
-Ijp7IkciOltdfSwiY2YiOnsiRyI6W119LCJkQiI6eyJHIjpbXX0sImRBIjp7IkciOltdfSwiYU4iOnsi
-UiI6WyIxIl19LCJkbCI6eyJlciI6W10sInEiOltdfSwiZHkiOnsiazgiOltdfSwiY20iOnsialAiOltd
-fSwiY0EiOnsiYVciOlsiYyJdLCJNIjpbImMiXSwiaiI6WyJjIl19LCJiYiI6eyJZIjpbXX0sImFPIjp7
-ImwiOlsiMSJdLCJtIjpbIjEiXSwiWSI6W10sImoiOlsiMSJdLCJsLkUiOiIxIn0sImJnIjp7ImUiOltd
-LCJ1IjpbXSwiayI6W10sInEiOltdfSwiY3YiOnsiYVciOlsiYyJdLCJNIjpbImMiXSwiaiI6WyJjIl19
-LCJlIjp7InUiOltdLCJrIjpbXSwicSI6W119LCJhaCI6eyJtIjpbImYiXSwiVyI6W10sImoiOlsiZiJd
-fSwiY1kiOnsiRyI6W119fScpKQpILmt5KHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3siYkMiOjEs
-ImJsIjoxLCJkNCI6MSwiZDUiOjIsImJOIjoxLCJiUCI6MiwiYlciOjEsImM3IjoxLCJjZSI6MSwiYzUi
-OjF9JykpCnZhciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5mcApyZXR1cm57YTp0KCJiMyIpLG46
-dCgiYXUiKSx2OnQoImI1IiksZDp0KCJhRyIpLFg6dCgiYUgiKSxEOnQoImJ6PGE2LEA+IiksaDp0KCJ1
-IiksYlU6dCgiciIpLEE6dCgiZCIpLGFTOnQoInEiKSxjODp0KCJiOSIpLFo6dCgiYWIiKSxjOnQoImJF
-PEA+Iikscjp0KCJhMyIpLEk6dCgiYkgiKSxvOnQoImhPIiksZWg6dCgiajxrPiIpLFI6dCgiajxAPiIp
-LFE6dCgiRjxHPiIpLHM6dCgiRjxjPiIpLGI6dCgiRjxAPiIpLHQ6dCgiRjxmPiIpLGVIOnQoImhRIiks
-Zzp0KCJhZCIpLGFVOnQoIko8QD4iKSxhbTp0KCJhTzxAPiIpLEI6dCgiYW48YTYsQD4iKSxtOnQoIlki
-KSx3OnQoImJLIiksajp0KCJtPEA+IiksTDp0KCJtPGY+IiksZjp0KCJ5PGMsYz4iKSxHOnQoInk8QCxA
-PiIpLGR2OnQoImE0PGMsYz4iKSxWOnQoIksiKSxkRDp0KCJDIiksYm06dCgiYVMiKSxGOnQoImsiKSxl
-OnQoIkciKSxQOnQoInAiKSxLOnQoInQiKSxnQjp0KCJiZSIpLHA6dCgiYTUiKSxxOnQoImg1PFU+Iiks
-ZnY6dCgiaFoiKSxhdjp0KCJhZiIpLGV3OnQoImJnIiksVDp0KCJNPGM+IiksbDp0KCJhZyIpLE46dCgi
-YyIpLGRHOnQoImMoYykiKSxnNzp0KCJlIiksZm86dCgiYTYiKSxhVzp0KCJiaiIpLGk6dCgiVyIpLGdj
-OnQoImFoIiksYWs6dCgiYmsiKSxXOnQoImF6PGMsYz4iKSxrOnQoImRjIiksZzQ6dCgiYUEiKSxjaTp0
-KCJlciIpLGcyOnQoImFpIiksRTp0KCJjMDxhMz4iKSxoOTp0KCJibSIpLGFjOnQoIk8iKSxDOnQoImJu
-PEs+IiksUzp0KCJhcTx1PiIpLHg6dCgiYVo8QCxAPiIpLGFvOnQoIlM8YTM+IiksXzp0KCJTPEA+Iiks
-Zko6dCgiUzxmPiIpLE86dCgiYl8iKSxKOnQoImR1IiksY0o6dCgieiIpLGFsOnQoInoodCkiKSxiZjp0
-KCJ6KEApIiksejp0KCJAIiksZk86dCgiQCgpIiksVTp0KCJAKGQpIikseTp0KCJAKHQpIiksZXA6dCgi
-QCh0LHQpIiksWTp0KCJAKHQsYWcpIiksY2g6dCgiQChNPGM+KSIpLGI4OnQoIkAoQCxAKSIpLEg6dCgi
-fiIpLE06dCgifigpIiksYW46dCgifihhNSkiKSx1OnQoIn4oYyxjKSIpLGNBOnQoIn4oYyxAKSIpfX0p
-KCk7KGZ1bmN0aW9uIGNvbnN0YW50cygpe3ZhciB0PWh1bmtIZWxwZXJzLm1ha2VDb25zdExpc3QKQy5w
-PVcuYUgucHJvdG90eXBlCkMuTj1XLmJGLnByb3RvdHlwZQpDLk89Vy5hMy5wcm90b3R5cGUKQy5QPUou
-SS5wcm90b3R5cGUKQy5iPUouRi5wcm90b3R5cGUKQy5jPUouYkkucHJvdG90eXBlCkMuUT1KLmJKLnBy
-b3RvdHlwZQpDLmU9Si5iYS5wcm90b3R5cGUKQy5hPUouYXgucHJvdG90eXBlCkMuUj1KLmFkLnByb3Rv
-dHlwZQpDLlk9Vy5iTy5wcm90b3R5cGUKQy5hXz1ILmFTLnByb3RvdHlwZQpDLkI9Si5jWi5wcm90b3R5
-cGUKQy5DPVcuYloucHJvdG90eXBlCkMubj1KLmJrLnByb3RvdHlwZQpDLm89Vy5hQS5wcm90b3R5cGUK
-Qy5hMT1uZXcgUC5jeCgpCkMuRD1uZXcgUC5jdygpCkMucT1mdW5jdGlvbiBnZXRUYWdGYWxsYmFjayhv
-KSB7CiAgdmFyIHMgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7CiAgcmV0dXJuIHMu
-c3Vic3RyaW5nKDgsIHMubGVuZ3RoIC0gMSk7Cn0KQy5FPWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmlu
-Z0Z1bmN0aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykg
-ewogICAgdmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJp
-bmcoOCwgcy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRh
-ZykgewogICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBu
-YW1lID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2Jq
-ZWN0IE9iamVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9
-CiAgfQogIGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewog
-ICAgaWYgKHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJl
-dHVybiAiSFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwog
-IH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9
-PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1
-bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwog
-ICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJl
-dHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFn
-KSB7IHJldHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9i
-amVjdCI7CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNC
-cm93c2VyID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHBy
-b3RvdHlwZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWlu
-YXRvciB9Owp9CkMuSj1mdW5jdGlvbihnZXRUYWdGYWxsYmFjaykgewogIHJldHVybiBmdW5jdGlvbiho
-b29rcykgewogICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT0gIm9iamVjdCIpIHJldHVybiBob29rczsK
-ICAgIHZhciB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7CiAgICBpZiAodWEuaW5kZXhPZigiRHVtcFJl
-bmRlclRyZWUiKSA+PSAwKSByZXR1cm4gaG9va3M7CiAgICBpZiAodWEuaW5kZXhPZigiQ2hyb21lIikg
-Pj0gMCkgewogICAgICBmdW5jdGlvbiBjb25maXJtKHApIHsKICAgICAgICByZXR1cm4gdHlwZW9mIHdp
-bmRvdyA9PSAib2JqZWN0IiAmJiB3aW5kb3dbcF0gJiYgd2luZG93W3BdLm5hbWUgPT0gcDsKICAgICAg
-fQogICAgICBpZiAoY29uZmlybSgiV2luZG93IikgJiYgY29uZmlybSgiSFRNTEVsZW1lbnQiKSkgcmV0
-dXJuIGhvb2tzOwogICAgfQogICAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRmFsbGJhY2s7CiAgfTsKfQpD
-LkY9ZnVuY3Rpb24oaG9va3MpIHsKICBpZiAodHlwZW9mIGRhcnRFeHBlcmltZW50YWxGaXh1cEdldFRh
-ZyAhPSAiZnVuY3Rpb24iKSByZXR1cm4gaG9va3M7CiAgaG9va3MuZ2V0VGFnID0gZGFydEV4cGVyaW1l
-bnRhbEZpeHVwR2V0VGFnKGhvb2tzLmdldFRhZyk7Cn0KQy5HPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFy
-IGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJvdG90
-eXBlRm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWco
-byk7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9uKSBy
-ZXR1cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAgICBy
-ZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAgIGlm
-ICh0YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9yVGFn
-KHRhZyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlwZUZv
-clRhZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMuST1mdW5jdGlvbihob29rcykgewogIHZhciB1
-c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2Vu
-dCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiRmlyZWZveCIpID09IC0xKSByZXR1cm4gaG9v
-a3M7CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVm
-b3JlVW5sb2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAog
-ICAgIkdlb0dlb2xvY2F0aW9uIjogIkdlb2xvY2F0aW9uIiwKICAgICJMb2NhdGlvbiI6ICIhTG9jYXRp
-b24iLAogICAgIldvcmtlck1lc3NhZ2VFdmVudCI6ICJNZXNzYWdlRXZlbnQiLAogICAgIlhNTERvY3Vt
-ZW50IjogIiFEb2N1bWVudCJ9OwogIGZ1bmN0aW9uIGdldFRhZ0ZpcmVmb3gobykgewogICAgdmFyIHRh
-ZyA9IGdldFRhZyhvKTsKICAgIHJldHVybiBxdWlja01hcFt0YWddIHx8IHRhZzsKICB9CiAgaG9va3Mu
-Z2V0VGFnID0gZ2V0VGFnRmlyZWZveDsKfQpDLkg9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgdXNlckFn
-ZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiAi
-IjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIlRyaWRlbnQvIikgPT0gLTEpIHJldHVybiBob29rczsK
-ICB2YXIgZ2V0VGFnID0gaG9va3MuZ2V0VGFnOwogIHZhciBxdWlja01hcCA9IHsKICAgICJCZWZvcmVV
-bmxvYWRFdmVudCI6ICJFdmVudCIsCiAgICAiRGF0YVRyYW5zZmVyIjogIkNsaXBib2FyZCIsCiAgICAi
-SFRNTERERWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiSFRNTERURWxlbWVudCI6ICJIVE1MRWxl
-bWVudCIsCiAgICAiSFRNTFBocmFzZUVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIlBvc2l0aW9u
-IjogIkdlb3Bvc2l0aW9uIgogIH07CiAgZnVuY3Rpb24gZ2V0VGFnSUUobykgewogICAgdmFyIHRhZyA9
-IGdldFRhZyhvKTsKICAgIHZhciBuZXdUYWcgPSBxdWlja01hcFt0YWddOwogICAgaWYgKG5ld1RhZykg
-cmV0dXJuIG5ld1RhZzsKICAgIGlmICh0YWcgPT0gIk9iamVjdCIpIHsKICAgICAgaWYgKHdpbmRvdy5E
-YXRhVmlldyAmJiAobyBpbnN0YW5jZW9mIHdpbmRvdy5EYXRhVmlldykpIHJldHVybiAiRGF0YVZpZXci
-OwogICAgfQogICAgcmV0dXJuIHRhZzsKICB9CiAgZnVuY3Rpb24gcHJvdG90eXBlRm9yVGFnSUUodGFn
-KSB7CiAgICB2YXIgY29uc3RydWN0b3IgPSB3aW5kb3dbdGFnXTsKICAgIGlmIChjb25zdHJ1Y3RvciA9
-PSBudWxsKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQog
-IGhvb2tzLmdldFRhZyA9IGdldFRhZ0lFOwogIGhvb2tzLnByb3RvdHlwZUZvclRhZyA9IHByb3RvdHlw
-ZUZvclRhZ0lFOwp9CkMucj1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMubD1uZXcg
-UC5jTSgpCkMuSz1uZXcgUC5jVygpCkMuZj1uZXcgUC5kZCgpCkMuTD1uZXcgUC5kZigpCkMuZD1uZXcg
-UC5keCgpCkMuTT1uZXcgUC5iOCgwKQpDLnQ9bmV3IFAuYjgoMmU1KQpDLlM9bmV3IFAuY04obnVsbCkK
-Qy51PUgubih0KFsxMjcsMjA0Nyw2NTUzNSwxMTE0MTExXSksdS50KQpDLmg9SC5uKHQoWzAsMCwzMjc3
-NiwzMzc5MiwxLDEwMjQwLDAsMF0pLHUudCkKQy5UPUgubih0KFsiKjo6Y2xhc3MiLCIqOjpkaXIiLCIq
-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
-ZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5zKQpDLmk9SC5uKHQoWzAsMCw2NTQ5MCw0NTA1NSw2NTUz
-NSwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkKQy5qPUgubih0KFswLDAsMjY2MjQsMTAyMyw2NTUzNCwy
-MDQ3LDY1NTM0LDIwNDddKSx1LnQpCkMuVT1ILm4odChbIkhFQUQiLCJBUkVBIiwiQkFTRSIsIkJBU0VG
-T05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNFVCIsIkhSIiwi
-SU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFNIiwiU09VUkNF
-IiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LnMpCkMudj1ILm4odChbXSksdS5zKQpDLnc9SC5uKHQo
-W10pLHUuYikKQy5XPUgubih0KFswLDAsMzI3MjIsMTIyODcsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFd
-KSx1LnQpCkMuaz1ILm4odChbMCwwLDI0NTc2LDEwMjMsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1
-LnQpCkMueD1ILm4odChbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50
-KQpDLlg9SC5uKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNSwzNDgxNSw2NTUzNCwxODQzMV0pLHUudCkK
-Qy55PUgubih0KFswLDAsNjU0OTAsMTIyODcsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQpCkMu
-ej1ILm4odChbImJpbmQiLCJpZiIsInJlZiIsInJlcGVhdCIsInN5bnRheCJdKSx1LnMpCkMubT1ILm4o
-dChbIkE6OmhyZWYiLCJBUkVBOjpocmVmIiwiQkxPQ0tRVU9URTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91
-bmQiLCJDT01NQU5EOjppY29uIiwiREVMOjpjaXRlIiwiRk9STTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJ
-TlBVVDo6c3JjIiwiSU5TOjpjaXRlIiwiUTo6Y2l0ZSIsIlZJREVPOjpwb3N0ZXIiXSksdS5zKQpDLlo9
-bmV3IEguYUooMCx7fSxDLnYsSC5mcCgiYUo8YyxjPiIpKQpDLlY9SC5uKHQoW10pLEguZnAoIkY8YTY+
-IikpCkMuQT1uZXcgSC5hSigwLHt9LEMuVixILmZwKCJhSjxhNixAPiIpKQpDLmEwPW5ldyBILmJpKCJj
-YWxsIil9KSgpOyhmdW5jdGlvbiBzdGF0aWNGaWVsZHMoKXskLmFtPTAKJC5ieD1udWxsCiQuaEo9bnVs
-bAokLmlLPW51bGwKJC5pSD1udWxsCiQuaVQ9bnVsbAokLmZvPW51bGwKJC5mQj1udWxsCiQuaHM9bnVs
-bAokLmJzPW51bGwKJC5jbj1udWxsCiQuY289bnVsbAokLmhtPSExCiQudz1DLmQKJC5YPVtdCiQuYXc9
-bnVsbAokLmZaPW51bGwKJC5oTj1udWxsCiQuaE09bnVsbAokLmRyPVAuZTkodS5OLHUuWil9KSgpOyhm
-dW5jdGlvbiBsYXp5SW5pdGlhbGl6ZXJzKCl7dmFyIHQ9aHVua0hlbHBlcnMubGF6eQp0KCQsImxQIiwi
-ZlYiLGZ1bmN0aW9uKCl7cmV0dXJuIEguaHIoIl8kZGFydF9kYXJ0Q2xvc3VyZSIpfSkKdCgkLCJsVSIs
-Imh5IixmdW5jdGlvbigpe3JldHVybiBILmhyKCJfJGRhcnRfanMiKX0pCnQoJCwibTEiLCJqMiIsZnVu
-Y3Rpb24oKXtyZXR1cm4gSC5hbyhILmVrKHsKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4iJHJlY2Vp
-dmVyJCJ9fSkpfSkKdCgkLCJtMiIsImozIixmdW5jdGlvbigpe3JldHVybiBILmFvKEguZWsoeyRtZXRo
-b2QkOm51bGwsCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnQoJCwi
-bTMiLCJqNCIsZnVuY3Rpb24oKXtyZXR1cm4gSC5hbyhILmVrKG51bGwpKX0pCnQoJCwibTQiLCJqNSIs
-ZnVuY3Rpb24oKXtyZXR1cm4gSC5hbyhmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1
-bWVudHMkJwp0cnl7bnVsbC4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBz
-Lm1lc3NhZ2V9fSgpKX0pCnQoJCwibTciLCJqOCIsZnVuY3Rpb24oKXtyZXR1cm4gSC5hbyhILmVrKHZv
-aWQgMCkpfSkKdCgkLCJtOCIsImo5IixmdW5jdGlvbigpe3JldHVybiBILmFvKGZ1bmN0aW9uKCl7dmFy
-ICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXsodm9pZCAwKS4kbWV0aG9kJCgkYXJndW1l
-bnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwibTYiLCJqNyIsZnVu
-Y3Rpb24oKXtyZXR1cm4gSC5hbyhILmkzKG51bGwpKX0pCnQoJCwibTUiLCJqNiIsZnVuY3Rpb24oKXty
-ZXR1cm4gSC5hbyhmdW5jdGlvbigpe3RyeXtudWxsLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1l
-c3NhZ2V9fSgpKX0pCnQoJCwibWEiLCJqYiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5hbyhILmkzKHZvaWQg
-MCkpfSkKdCgkLCJtOSIsImphIixmdW5jdGlvbigpe3JldHVybiBILmFvKGZ1bmN0aW9uKCl7dHJ5eyh2
-b2lkIDApLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwibWQiLCJo
-QSIsZnVuY3Rpb24oKXtyZXR1cm4gUC5rZigpfSkKdCgkLCJtYiIsImpjIixmdW5jdGlvbigpe3JldHVy
-biBQLmtjKCl9KQp0KCQsIm1lIiwiamQiLGZ1bmN0aW9uKCl7cmV0dXJuIEguak8oSC5rWChILm4oWy0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0y
-LC0yLC0yLDYyLC0yLDYyLC0yLDYzLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0y
-LC0xLC0yLC0yLC0yLDAsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgs
-MTksMjAsMjEsMjIsMjMsMjQsMjUsLTIsLTIsLTIsLTIsNjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIs
-MzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIs
-LTIsLTIsLTIsLTJdLHUudCkpKX0pCnQoJCwibWkiLCJqZiIsZnVuY3Rpb24oKXtyZXR1cm4gUC5pXygi
-XltcXC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKdCgkLCJtcyIsImpoIixmdW5jdGlvbigpe3JldHVybiBQ
-LmtXKCl9KQp0KCQsIm1nIiwiamUiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuaFQoWyJBIiwiQUJCUiIsIkFD
-Uk9OWU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwiQiIsIkJESSIs
-IkJETyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNBUFRJT04iLCJD
-RU5URVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRBVEEiLCJEQVRB
-TElTVCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwiRFQiLCJFTSIs
-IkZJRUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJGT1JNIiwiSDEi
-LCJIMiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJIiwiSUZSQU1F
-IiwiSU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwiTUFQIiwiTUFS
-SyIsIk1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BUSU9OIiwiT1VU
-UFVUIiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIsIlNFTEVDVCIs
-IlNNQUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNVTU1BUlkiLCJT
-VVAiLCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJUSEVBRCIsIlRJ
-TUUiLCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJdLHUuTil9KQp0
-KCQsImxPIiwiajEiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuaV8oIl5cXFMrJCIpfSkKdCgkLCJtcSIsImpn
-IixmdW5jdGlvbigpe3JldHVybiB1Lm0uYihQLmlGKHNlbGYpKX0pCnQoJCwibWYiLCJoQiIsZnVuY3Rp
-b24oKXtyZXR1cm4gSC5ocigiXyRkYXJ0X2RhcnRPYmplY3QiKX0pCnQoJCwibXIiLCJoQyIsZnVuY3Rp
-b24oKXtyZXR1cm4gZnVuY3Rpb24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQp0KCQsIm13Iiwiamki
-LGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLmUwKCl9KQp0KCQsImxZIiwiaHoiLGZ1bmN0aW9uKCl7cmV0
-dXJuIG5ldyBMLmNZKCl9KX0pKCk7KGZ1bmN0aW9uIG5hdGl2ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2
-YXIgdD1mdW5jdGlvbihhKXt2YXIgbj17fQpuW2FdPTEKcmV0dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxw
-ZXJzLmNvbnZlcnRUb0Zhc3RPYmplY3QobikpWzBdfQp2LmdldElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7
-cmV0dXJuIHQoIl9fX2RhcnRfIithK3YuaXNvbGF0ZVRhZyl9CnZhciBzPSJfX19kYXJ0X2lzb2xhdGVf
-dGFnc18iCnZhciByPU9iamVjdFtzXXx8KE9iamVjdFtzXT1PYmplY3QuY3JlYXRlKG51bGwpKQp2YXIg
-cT0iX1p4WXhYIgpmb3IodmFyIHA9MDs7cCsrKXt2YXIgbz10KHErIl8iK3ArIl8iKQppZighKG8gaW4g
-cikpe3Jbb109MQp2Lmlzb2xhdGVUYWc9bwpicmVha319di5kaXNwYXRjaFByb3BlcnR5TmFtZT12Lmdl
-dElzb2xhdGVUYWcoImRpc3BhdGNoX3JlY29yZCIpfSgpCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50
-ZXJjZXB0b3JzQnlUYWcoe0RPTUVycm9yOkouSSxET01JbXBsZW1lbnRhdGlvbjpKLkksTWVkaWFFcnJv
-cjpKLkksTmF2aWdhdG9yOkouSSxOYXZpZ2F0b3JDb25jdXJyZW50SGFyZHdhcmU6Si5JLE5hdmlnYXRv
-clVzZXJNZWRpYUVycm9yOkouSSxPdmVyY29uc3RyYWluZWRFcnJvcjpKLkksUG9zaXRpb25FcnJvcjpK
-LkksUmFuZ2U6Si5JLFNRTEVycm9yOkouSSxEYXRhVmlldzpILkMsQXJyYXlCdWZmZXJWaWV3OkguQyxG
-bG9hdDMyQXJyYXk6SC5hUixGbG9hdDY0QXJyYXk6SC5hUixJbnQxNkFycmF5OkguY1AsSW50MzJBcnJh
-eTpILmNRLEludDhBcnJheTpILmNSLFVpbnQxNkFycmF5OkguY1MsVWludDMyQXJyYXk6SC5jVCxVaW50
-OENsYW1wZWRBcnJheTpILmJTLENhbnZhc1BpeGVsQXJyYXk6SC5iUyxVaW50OEFycmF5OkguYVMsSFRN
-TEF1ZGlvRWxlbWVudDpXLmgsSFRNTEJSRWxlbWVudDpXLmgsSFRNTEJ1dHRvbkVsZW1lbnQ6Vy5oLEhU
-TUxDYW52YXNFbGVtZW50OlcuaCxIVE1MQ29udGVudEVsZW1lbnQ6Vy5oLEhUTUxETGlzdEVsZW1lbnQ6
-Vy5oLEhUTUxEYXRhRWxlbWVudDpXLmgsSFRNTERhdGFMaXN0RWxlbWVudDpXLmgsSFRNTERldGFpbHNF
-bGVtZW50OlcuaCxIVE1MRGlhbG9nRWxlbWVudDpXLmgsSFRNTERpdkVsZW1lbnQ6Vy5oLEhUTUxFbWJl
-ZEVsZW1lbnQ6Vy5oLEhUTUxGaWVsZFNldEVsZW1lbnQ6Vy5oLEhUTUxIUkVsZW1lbnQ6Vy5oLEhUTUxI
-ZWFkRWxlbWVudDpXLmgsSFRNTEhlYWRpbmdFbGVtZW50OlcuaCxIVE1MSHRtbEVsZW1lbnQ6Vy5oLEhU
-TUxJRnJhbWVFbGVtZW50OlcuaCxIVE1MSW1hZ2VFbGVtZW50OlcuaCxIVE1MSW5wdXRFbGVtZW50Olcu
-aCxIVE1MTElFbGVtZW50OlcuaCxIVE1MTGFiZWxFbGVtZW50OlcuaCxIVE1MTGVnZW5kRWxlbWVudDpX
-LmgsSFRNTExpbmtFbGVtZW50OlcuaCxIVE1MTWFwRWxlbWVudDpXLmgsSFRNTE1lZGlhRWxlbWVudDpX
-LmgsSFRNTE1lbnVFbGVtZW50OlcuaCxIVE1MTWV0YUVsZW1lbnQ6Vy5oLEhUTUxNZXRlckVsZW1lbnQ6
-Vy5oLEhUTUxNb2RFbGVtZW50OlcuaCxIVE1MT0xpc3RFbGVtZW50OlcuaCxIVE1MT2JqZWN0RWxlbWVu
-dDpXLmgsSFRNTE9wdEdyb3VwRWxlbWVudDpXLmgsSFRNTE9wdGlvbkVsZW1lbnQ6Vy5oLEhUTUxPdXRw
-dXRFbGVtZW50OlcuaCxIVE1MUGFyYW1FbGVtZW50OlcuaCxIVE1MUGljdHVyZUVsZW1lbnQ6Vy5oLEhU
-TUxQcmVFbGVtZW50OlcuaCxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcuaCxIVE1MUXVvdGVFbGVtZW50Olcu
-aCxIVE1MU2NyaXB0RWxlbWVudDpXLmgsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5oLEhUTUxTbG90RWxlbWVu
-dDpXLmgsSFRNTFNvdXJjZUVsZW1lbnQ6Vy5oLEhUTUxTcGFuRWxlbWVudDpXLmgsSFRNTFN0eWxlRWxl
-bWVudDpXLmgsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6Vy5oLEhUTUxUYWJsZUNlbGxFbGVtZW50Olcu
-aCxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6Vy5oLEhUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50Olcu
-aCxIVE1MVGFibGVDb2xFbGVtZW50OlcuaCxIVE1MVGV4dEFyZWFFbGVtZW50OlcuaCxIVE1MVGltZUVs
-ZW1lbnQ6Vy5oLEhUTUxUaXRsZUVsZW1lbnQ6Vy5oLEhUTUxUcmFja0VsZW1lbnQ6Vy5oLEhUTUxVTGlz
-dEVsZW1lbnQ6Vy5oLEhUTUxVbmtub3duRWxlbWVudDpXLmgsSFRNTFZpZGVvRWxlbWVudDpXLmgsSFRN
-TERpcmVjdG9yeUVsZW1lbnQ6Vy5oLEhUTUxGb250RWxlbWVudDpXLmgsSFRNTEZyYW1lRWxlbWVudDpX
-LmgsSFRNTEZyYW1lU2V0RWxlbWVudDpXLmgsSFRNTE1hcnF1ZWVFbGVtZW50OlcuaCxIVE1MRWxlbWVu
-dDpXLmgsSFRNTEFuY2hvckVsZW1lbnQ6Vy5iMyxIVE1MQXJlYUVsZW1lbnQ6Vy5jdSxIVE1MQmFzZUVs
-ZW1lbnQ6Vy5iNSxCbG9iOlcuYUcsSFRNTEJvZHlFbGVtZW50OlcuYUgsQ0RBVEFTZWN0aW9uOlcuYWEs
-Q2hhcmFjdGVyRGF0YTpXLmFhLENvbW1lbnQ6Vy5hYSxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246Vy5hYSxU
-ZXh0OlcuYWEsQ1NTU3R5bGVEZWNsYXJhdGlvbjpXLmJBLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOlcuYkEs
-Q1NTMlByb3BlcnRpZXM6Vy5iQSxYTUxEb2N1bWVudDpXLmFMLERvY3VtZW50OlcuYUwsRE9NRXhjZXB0
-aW9uOlcuZFYsRE9NUmVjdFJlYWRPbmx5OlcuYkIsRE9NVG9rZW5MaXN0OlcuZFcsRWxlbWVudDpXLnUs
-QWJvcnRQYXltZW50RXZlbnQ6Vy5kLEFuaW1hdGlvbkV2ZW50OlcuZCxBbmltYXRpb25QbGF5YmFja0V2
-ZW50OlcuZCxBcHBsaWNhdGlvbkNhY2hlRXJyb3JFdmVudDpXLmQsQmFja2dyb3VuZEZldGNoQ2xpY2tF
-dmVudDpXLmQsQmFja2dyb3VuZEZldGNoRXZlbnQ6Vy5kLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDpX
-LmQsQmFja2dyb3VuZEZldGNoZWRFdmVudDpXLmQsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OlcuZCxC
-ZWZvcmVVbmxvYWRFdmVudDpXLmQsQmxvYkV2ZW50OlcuZCxDYW5NYWtlUGF5bWVudEV2ZW50OlcuZCxD
-bGlwYm9hcmRFdmVudDpXLmQsQ2xvc2VFdmVudDpXLmQsQ3VzdG9tRXZlbnQ6Vy5kLERldmljZU1vdGlv
-bkV2ZW50OlcuZCxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OlcuZCxFcnJvckV2ZW50OlcuZCxFeHRlbmRh
-YmxlRXZlbnQ6Vy5kLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6Vy5kLEZldGNoRXZlbnQ6Vy5kLEZvbnRG
-YWNlU2V0TG9hZEV2ZW50OlcuZCxGb3JlaWduRmV0Y2hFdmVudDpXLmQsR2FtZXBhZEV2ZW50OlcuZCxI
-YXNoQ2hhbmdlRXZlbnQ6Vy5kLEluc3RhbGxFdmVudDpXLmQsTWVkaWFFbmNyeXB0ZWRFdmVudDpXLmQs
-TWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5kLE1lZGlhUXVlcnlMaXN0RXZlbnQ6Vy5kLE1lZGlhU3RyZWFt
-RXZlbnQ6Vy5kLE1lZGlhU3RyZWFtVHJhY2tFdmVudDpXLmQsTWVzc2FnZUV2ZW50OlcuZCxNSURJQ29u
-bmVjdGlvbkV2ZW50OlcuZCxNSURJTWVzc2FnZUV2ZW50OlcuZCxNdXRhdGlvbkV2ZW50OlcuZCxOb3Rp
-ZmljYXRpb25FdmVudDpXLmQsUGFnZVRyYW5zaXRpb25FdmVudDpXLmQsUGF5bWVudFJlcXVlc3RFdmVu
-dDpXLmQsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDpXLmQsUG9wU3RhdGVFdmVudDpXLmQsUHJlc2Vu
-dGF0aW9uQ29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50OlcuZCxQcmVzZW50YXRpb25Db25uZWN0aW9uQ2xv
-c2VFdmVudDpXLmQsUHJvbWlzZVJlamVjdGlvbkV2ZW50OlcuZCxQdXNoRXZlbnQ6Vy5kLFJUQ0RhdGFD
-aGFubmVsRXZlbnQ6Vy5kLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6Vy5kLFJUQ1BlZXJDb25uZWN0aW9u
-SWNlRXZlbnQ6Vy5kLFJUQ1RyYWNrRXZlbnQ6Vy5kLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6
-Vy5kLFNlbnNvckVycm9yRXZlbnQ6Vy5kLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6Vy5kLFNwZWVjaFJl
-Y29nbml0aW9uRXZlbnQ6Vy5kLFNwZWVjaFN5bnRoZXNpc0V2ZW50OlcuZCxTdG9yYWdlRXZlbnQ6Vy5k
-LFN5bmNFdmVudDpXLmQsVHJhY2tFdmVudDpXLmQsVHJhbnNpdGlvbkV2ZW50OlcuZCxXZWJLaXRUcmFu
-c2l0aW9uRXZlbnQ6Vy5kLFZSRGV2aWNlRXZlbnQ6Vy5kLFZSRGlzcGxheUV2ZW50OlcuZCxWUlNlc3Np
-b25FdmVudDpXLmQsTW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDpXLmQsVVNCQ29ubmVjdGlvbkV2ZW50
-OlcuZCxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6Vy5kLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OlcuZCxPZmZs
-aW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6Vy5kLFdlYkdMQ29udGV4dEV2ZW50OlcuZCxFdmVudDpXLmQs
-SW5wdXRFdmVudDpXLmQsRXZlbnRUYXJnZXQ6Vy5xLEZpbGU6Vy5iOSxIVE1MRm9ybUVsZW1lbnQ6Vy5j
-RixIaXN0b3J5OlcuZTEsSFRNTERvY3VtZW50OlcuYkYsWE1MSHR0cFJlcXVlc3Q6Vy5hMyxYTUxIdHRw
-UmVxdWVzdEV2ZW50VGFyZ2V0OlcuYkcsSW1hZ2VEYXRhOlcuYkgsTG9jYXRpb246Vy5iTyxNb3VzZUV2
-ZW50OlcuSyxEcmFnRXZlbnQ6Vy5LLFBvaW50ZXJFdmVudDpXLkssV2hlZWxFdmVudDpXLkssRG9jdW1l
-bnRGcmFnbWVudDpXLmssU2hhZG93Um9vdDpXLmssRG9jdW1lbnRUeXBlOlcuayxOb2RlOlcuayxOb2Rl
-TGlzdDpXLmJULFJhZGlvTm9kZUxpc3Q6Vy5iVCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLmJlLFByb2dy
-ZXNzRXZlbnQ6Vy5hNSxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6Vy5hNSxIVE1MU2VsZWN0RWxlbWVudDpX
-LmQxLEhUTUxUYWJsZUVsZW1lbnQ6Vy5iWixIVE1MVGFibGVSb3dFbGVtZW50OlcuZDYsSFRNTFRhYmxl
-U2VjdGlvbkVsZW1lbnQ6Vy5kNyxIVE1MVGVtcGxhdGVFbGVtZW50OlcuYmosQ29tcG9zaXRpb25FdmVu
-dDpXLmE3LEZvY3VzRXZlbnQ6Vy5hNyxLZXlib2FyZEV2ZW50OlcuYTcsVGV4dEV2ZW50OlcuYTcsVG91
-Y2hFdmVudDpXLmE3LFVJRXZlbnQ6Vy5hNyxXaW5kb3c6Vy5hQSxET01XaW5kb3c6Vy5hQSxEZWRpY2F0
-ZWRXb3JrZXJHbG9iYWxTY29wZTpXLmFpLFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTpXLmFpLFNoYXJl
-ZFdvcmtlckdsb2JhbFNjb3BlOlcuYWksV29ya2VyR2xvYmFsU2NvcGU6Vy5haSxBdHRyOlcuYm0sQ2xp
-ZW50UmVjdDpXLmMzLERPTVJlY3Q6Vy5jMyxOYW1lZE5vZGVNYXA6Vy5jOCxNb3pOYW1lZEF0dHJNYXA6
-Vy5jOCxJREJLZXlSYW5nZTpQLmJLLFNWR1NjcmlwdEVsZW1lbnQ6UC5iZyxTVkdBRWxlbWVudDpQLmUs
-U1ZHQW5pbWF0ZUVsZW1lbnQ6UC5lLFNWR0FuaW1hdGVNb3Rpb25FbGVtZW50OlAuZSxTVkdBbmltYXRl
-VHJhbnNmb3JtRWxlbWVudDpQLmUsU1ZHQW5pbWF0aW9uRWxlbWVudDpQLmUsU1ZHQ2lyY2xlRWxlbWVu
-dDpQLmUsU1ZHQ2xpcFBhdGhFbGVtZW50OlAuZSxTVkdEZWZzRWxlbWVudDpQLmUsU1ZHRGVzY0VsZW1l
-bnQ6UC5lLFNWR0Rpc2NhcmRFbGVtZW50OlAuZSxTVkdFbGxpcHNlRWxlbWVudDpQLmUsU1ZHRkVCbGVu
-ZEVsZW1lbnQ6UC5lLFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZSxTVkdGRUNvbXBvbmVudFRyYW5z
-ZmVyRWxlbWVudDpQLmUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OlAuZSxTVkdGRUNvbnZvbHZlTWF0cml4
-RWxlbWVudDpQLmUsU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OlAuZSxTVkdGRURpc3BsYWNlbWVu
-dE1hcEVsZW1lbnQ6UC5lLFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmUsU1ZHRkVGbG9vZEVsZW1l
-bnQ6UC5lLFNWR0ZFRnVuY0FFbGVtZW50OlAuZSxTVkdGRUZ1bmNCRWxlbWVudDpQLmUsU1ZHRkVGdW5j
-R0VsZW1lbnQ6UC5lLFNWR0ZFRnVuY1JFbGVtZW50OlAuZSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6
-UC5lLFNWR0ZFSW1hZ2VFbGVtZW50OlAuZSxTVkdGRU1lcmdlRWxlbWVudDpQLmUsU1ZHRkVNZXJnZU5v
-ZGVFbGVtZW50OlAuZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OlAuZSxTVkdGRU9mZnNldEVsZW1lbnQ6
-UC5lLFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5lLFNWR0ZFU3BlY3VsYXJMaWdodGluZ0VsZW1lbnQ6
-UC5lLFNWR0ZFU3BvdExpZ2h0RWxlbWVudDpQLmUsU1ZHRkVUaWxlRWxlbWVudDpQLmUsU1ZHRkVUdXJi
-dWxlbmNlRWxlbWVudDpQLmUsU1ZHRmlsdGVyRWxlbWVudDpQLmUsU1ZHRm9yZWlnbk9iamVjdEVsZW1l
-bnQ6UC5lLFNWR0dFbGVtZW50OlAuZSxTVkdHZW9tZXRyeUVsZW1lbnQ6UC5lLFNWR0dyYXBoaWNzRWxl
-bWVudDpQLmUsU1ZHSW1hZ2VFbGVtZW50OlAuZSxTVkdMaW5lRWxlbWVudDpQLmUsU1ZHTGluZWFyR3Jh
-ZGllbnRFbGVtZW50OlAuZSxTVkdNYXJrZXJFbGVtZW50OlAuZSxTVkdNYXNrRWxlbWVudDpQLmUsU1ZH
-TWV0YWRhdGFFbGVtZW50OlAuZSxTVkdQYXRoRWxlbWVudDpQLmUsU1ZHUGF0dGVybkVsZW1lbnQ6UC5l
-LFNWR1BvbHlnb25FbGVtZW50OlAuZSxTVkdQb2x5bGluZUVsZW1lbnQ6UC5lLFNWR1JhZGlhbEdyYWRp
-ZW50RWxlbWVudDpQLmUsU1ZHUmVjdEVsZW1lbnQ6UC5lLFNWR1NldEVsZW1lbnQ6UC5lLFNWR1N0b3BF
-bGVtZW50OlAuZSxTVkdTdHlsZUVsZW1lbnQ6UC5lLFNWR1NWR0VsZW1lbnQ6UC5lLFNWR1N3aXRjaEVs
-ZW1lbnQ6UC5lLFNWR1N5bWJvbEVsZW1lbnQ6UC5lLFNWR1RTcGFuRWxlbWVudDpQLmUsU1ZHVGV4dENv
-bnRlbnRFbGVtZW50OlAuZSxTVkdUZXh0RWxlbWVudDpQLmUsU1ZHVGV4dFBhdGhFbGVtZW50OlAuZSxT
-VkdUZXh0UG9zaXRpb25pbmdFbGVtZW50OlAuZSxTVkdUaXRsZUVsZW1lbnQ6UC5lLFNWR1VzZUVsZW1l
-bnQ6UC5lLFNWR1ZpZXdFbGVtZW50OlAuZSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5lLFNWR0NvbXBvbmVu
-dFRyYW5zZmVyRnVuY3Rpb25FbGVtZW50OlAuZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OlAuZSxTVkdN
-UGF0aEVsZW1lbnQ6UC5lLFNWR0VsZW1lbnQ6UC5lfSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFm
-VGFncyh7RE9NRXJyb3I6dHJ1ZSxET01JbXBsZW1lbnRhdGlvbjp0cnVlLE1lZGlhRXJyb3I6dHJ1ZSxO
-YXZpZ2F0b3I6dHJ1ZSxOYXZpZ2F0b3JDb25jdXJyZW50SGFyZHdhcmU6dHJ1ZSxOYXZpZ2F0b3JVc2Vy
-TWVkaWFFcnJvcjp0cnVlLE92ZXJjb25zdHJhaW5lZEVycm9yOnRydWUsUG9zaXRpb25FcnJvcjp0cnVl
-LFJhbmdlOnRydWUsU1FMRXJyb3I6dHJ1ZSxEYXRhVmlldzp0cnVlLEFycmF5QnVmZmVyVmlldzpmYWxz
-ZSxGbG9hdDMyQXJyYXk6dHJ1ZSxGbG9hdDY0QXJyYXk6dHJ1ZSxJbnQxNkFycmF5OnRydWUsSW50MzJB
-cnJheTp0cnVlLEludDhBcnJheTp0cnVlLFVpbnQxNkFycmF5OnRydWUsVWludDMyQXJyYXk6dHJ1ZSxV
-aW50OENsYW1wZWRBcnJheTp0cnVlLENhbnZhc1BpeGVsQXJyYXk6dHJ1ZSxVaW50OEFycmF5OmZhbHNl
-LEhUTUxBdWRpb0VsZW1lbnQ6dHJ1ZSxIVE1MQlJFbGVtZW50OnRydWUsSFRNTEJ1dHRvbkVsZW1lbnQ6
-dHJ1ZSxIVE1MQ2FudmFzRWxlbWVudDp0cnVlLEhUTUxDb250ZW50RWxlbWVudDp0cnVlLEhUTUxETGlz
-dEVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUxpc3RFbGVtZW50OnRydWUs
-SFRNTERldGFpbHNFbGVtZW50OnRydWUsSFRNTERpYWxvZ0VsZW1lbnQ6dHJ1ZSxIVE1MRGl2RWxlbWVu
-dDp0cnVlLEhUTUxFbWJlZEVsZW1lbnQ6dHJ1ZSxIVE1MRmllbGRTZXRFbGVtZW50OnRydWUsSFRNTEhS
-RWxlbWVudDp0cnVlLEhUTUxIZWFkRWxlbWVudDp0cnVlLEhUTUxIZWFkaW5nRWxlbWVudDp0cnVlLEhU
-TUxIdG1sRWxlbWVudDp0cnVlLEhUTUxJRnJhbWVFbGVtZW50OnRydWUsSFRNTEltYWdlRWxlbWVudDp0
-cnVlLEhUTUxJbnB1dEVsZW1lbnQ6dHJ1ZSxIVE1MTElFbGVtZW50OnRydWUsSFRNTExhYmVsRWxlbWVu
-dDp0cnVlLEhUTUxMZWdlbmRFbGVtZW50OnRydWUsSFRNTExpbmtFbGVtZW50OnRydWUsSFRNTE1hcEVs
-ZW1lbnQ6dHJ1ZSxIVE1MTWVkaWFFbGVtZW50OnRydWUsSFRNTE1lbnVFbGVtZW50OnRydWUsSFRNTE1l
-dGFFbGVtZW50OnRydWUsSFRNTE1ldGVyRWxlbWVudDp0cnVlLEhUTUxNb2RFbGVtZW50OnRydWUsSFRN
-TE9MaXN0RWxlbWVudDp0cnVlLEhUTUxPYmplY3RFbGVtZW50OnRydWUsSFRNTE9wdEdyb3VwRWxlbWVu
-dDp0cnVlLEhUTUxPcHRpb25FbGVtZW50OnRydWUsSFRNTE91dHB1dEVsZW1lbnQ6dHJ1ZSxIVE1MUGFy
-YW1FbGVtZW50OnRydWUsSFRNTFBpY3R1cmVFbGVtZW50OnRydWUsSFRNTFByZUVsZW1lbnQ6dHJ1ZSxI
-VE1MUHJvZ3Jlc3NFbGVtZW50OnRydWUsSFRNTFF1b3RlRWxlbWVudDp0cnVlLEhUTUxTY3JpcHRFbGVt
-ZW50OnRydWUsSFRNTFNoYWRvd0VsZW1lbnQ6dHJ1ZSxIVE1MU2xvdEVsZW1lbnQ6dHJ1ZSxIVE1MU291
-cmNlRWxlbWVudDp0cnVlLEhUTUxTcGFuRWxlbWVudDp0cnVlLEhUTUxTdHlsZUVsZW1lbnQ6dHJ1ZSxI
-VE1MVGFibGVDYXB0aW9uRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNlbGxFbGVtZW50OnRydWUsSFRNTFRh
-YmxlRGF0YUNlbGxFbGVtZW50OnRydWUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1M
-VGFibGVDb2xFbGVtZW50OnRydWUsSFRNTFRleHRBcmVhRWxlbWVudDp0cnVlLEhUTUxUaW1lRWxlbWVu
-dDp0cnVlLEhUTUxUaXRsZUVsZW1lbnQ6dHJ1ZSxIVE1MVHJhY2tFbGVtZW50OnRydWUsSFRNTFVMaXN0
-RWxlbWVudDp0cnVlLEhUTUxVbmtub3duRWxlbWVudDp0cnVlLEhUTUxWaWRlb0VsZW1lbnQ6dHJ1ZSxI
-VE1MRGlyZWN0b3J5RWxlbWVudDp0cnVlLEhUTUxGb250RWxlbWVudDp0cnVlLEhUTUxGcmFtZUVsZW1l
-bnQ6dHJ1ZSxIVE1MRnJhbWVTZXRFbGVtZW50OnRydWUsSFRNTE1hcnF1ZWVFbGVtZW50OnRydWUsSFRN
-TEVsZW1lbnQ6ZmFsc2UsSFRNTEFuY2hvckVsZW1lbnQ6dHJ1ZSxIVE1MQXJlYUVsZW1lbnQ6dHJ1ZSxI
-VE1MQmFzZUVsZW1lbnQ6dHJ1ZSxCbG9iOmZhbHNlLEhUTUxCb2R5RWxlbWVudDp0cnVlLENEQVRBU2Vj
-dGlvbjp0cnVlLENoYXJhY3RlckRhdGE6dHJ1ZSxDb21tZW50OnRydWUsUHJvY2Vzc2luZ0luc3RydWN0
-aW9uOnRydWUsVGV4dDp0cnVlLENTU1N0eWxlRGVjbGFyYXRpb246dHJ1ZSxNU1N0eWxlQ1NTUHJvcGVy
-dGllczp0cnVlLENTUzJQcm9wZXJ0aWVzOnRydWUsWE1MRG9jdW1lbnQ6dHJ1ZSxEb2N1bWVudDpmYWxz
-ZSxET01FeGNlcHRpb246dHJ1ZSxET01SZWN0UmVhZE9ubHk6ZmFsc2UsRE9NVG9rZW5MaXN0OnRydWUs
-RWxlbWVudDpmYWxzZSxBYm9ydFBheW1lbnRFdmVudDp0cnVlLEFuaW1hdGlvbkV2ZW50OnRydWUsQW5p
-bWF0aW9uUGxheWJhY2tFdmVudDp0cnVlLEFwcGxpY2F0aW9uQ2FjaGVFcnJvckV2ZW50OnRydWUsQmFj
-a2dyb3VuZEZldGNoQ2xpY2tFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaEV2ZW50OnRydWUsQmFja2dy
-b3VuZEZldGNoRmFpbEV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoZWRFdmVudDp0cnVlLEJlZm9yZUlu
-c3RhbGxQcm9tcHRFdmVudDp0cnVlLEJlZm9yZVVubG9hZEV2ZW50OnRydWUsQmxvYkV2ZW50OnRydWUs
-Q2FuTWFrZVBheW1lbnRFdmVudDp0cnVlLENsaXBib2FyZEV2ZW50OnRydWUsQ2xvc2VFdmVudDp0cnVl
-LEN1c3RvbUV2ZW50OnRydWUsRGV2aWNlTW90aW9uRXZlbnQ6dHJ1ZSxEZXZpY2VPcmllbnRhdGlvbkV2
-ZW50OnRydWUsRXJyb3JFdmVudDp0cnVlLEV4dGVuZGFibGVFdmVudDp0cnVlLEV4dGVuZGFibGVNZXNz
-YWdlRXZlbnQ6dHJ1ZSxGZXRjaEV2ZW50OnRydWUsRm9udEZhY2VTZXRMb2FkRXZlbnQ6dHJ1ZSxGb3Jl
-aWduRmV0Y2hFdmVudDp0cnVlLEdhbWVwYWRFdmVudDp0cnVlLEhhc2hDaGFuZ2VFdmVudDp0cnVlLElu
-c3RhbGxFdmVudDp0cnVlLE1lZGlhRW5jcnlwdGVkRXZlbnQ6dHJ1ZSxNZWRpYUtleU1lc3NhZ2VFdmVu
-dDp0cnVlLE1lZGlhUXVlcnlMaXN0RXZlbnQ6dHJ1ZSxNZWRpYVN0cmVhbUV2ZW50OnRydWUsTWVkaWFT
-dHJlYW1UcmFja0V2ZW50OnRydWUsTWVzc2FnZUV2ZW50OnRydWUsTUlESUNvbm5lY3Rpb25FdmVudDp0
-cnVlLE1JRElNZXNzYWdlRXZlbnQ6dHJ1ZSxNdXRhdGlvbkV2ZW50OnRydWUsTm90aWZpY2F0aW9uRXZl
-bnQ6dHJ1ZSxQYWdlVHJhbnNpdGlvbkV2ZW50OnRydWUsUGF5bWVudFJlcXVlc3RFdmVudDp0cnVlLFBh
-eW1lbnRSZXF1ZXN0VXBkYXRlRXZlbnQ6dHJ1ZSxQb3BTdGF0ZUV2ZW50OnRydWUsUHJlc2VudGF0aW9u
-Q29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50OnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZl
-bnQ6dHJ1ZSxQcm9taXNlUmVqZWN0aW9uRXZlbnQ6dHJ1ZSxQdXNoRXZlbnQ6dHJ1ZSxSVENEYXRhQ2hh
-bm5lbEV2ZW50OnRydWUsUlRDRFRNRlRvbmVDaGFuZ2VFdmVudDp0cnVlLFJUQ1BlZXJDb25uZWN0aW9u
-SWNlRXZlbnQ6dHJ1ZSxSVENUcmFja0V2ZW50OnRydWUsU2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVu
-dDp0cnVlLFNlbnNvckVycm9yRXZlbnQ6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkVycm9yOnRydWUsU3Bl
-ZWNoUmVjb2duaXRpb25FdmVudDp0cnVlLFNwZWVjaFN5bnRoZXNpc0V2ZW50OnRydWUsU3RvcmFnZUV2
-ZW50OnRydWUsU3luY0V2ZW50OnRydWUsVHJhY2tFdmVudDp0cnVlLFRyYW5zaXRpb25FdmVudDp0cnVl
-LFdlYktpdFRyYW5zaXRpb25FdmVudDp0cnVlLFZSRGV2aWNlRXZlbnQ6dHJ1ZSxWUkRpc3BsYXlFdmVu
-dDp0cnVlLFZSU2Vzc2lvbkV2ZW50OnRydWUsTW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDp0cnVlLFVT
-QkNvbm5lY3Rpb25FdmVudDp0cnVlLElEQlZlcnNpb25DaGFuZ2VFdmVudDp0cnVlLEF1ZGlvUHJvY2Vz
-c2luZ0V2ZW50OnRydWUsT2ZmbGluZUF1ZGlvQ29tcGxldGlvbkV2ZW50OnRydWUsV2ViR0xDb250ZXh0
-RXZlbnQ6dHJ1ZSxFdmVudDpmYWxzZSxJbnB1dEV2ZW50OmZhbHNlLEV2ZW50VGFyZ2V0OmZhbHNlLEZp
-bGU6dHJ1ZSxIVE1MRm9ybUVsZW1lbnQ6dHJ1ZSxIaXN0b3J5OnRydWUsSFRNTERvY3VtZW50OnRydWUs
-WE1MSHR0cFJlcXVlc3Q6dHJ1ZSxYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0OmZhbHNlLEltYWdlRGF0
-YTp0cnVlLExvY2F0aW9uOnRydWUsTW91c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBvaW50ZXJF
-dmVudDp0cnVlLFdoZWVsRXZlbnQ6dHJ1ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93Um9vdDp0
-cnVlLERvY3VtZW50VHlwZTp0cnVlLE5vZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05vZGVMaXN0
-OnRydWUsSFRNTFBhcmFncmFwaEVsZW1lbnQ6dHJ1ZSxQcm9ncmVzc0V2ZW50OnRydWUsUmVzb3VyY2VQ
-cm9ncmVzc0V2ZW50OnRydWUsSFRNTFNlbGVjdEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVFbGVtZW50OnRy
-dWUsSFRNTFRhYmxlUm93RWxlbWVudDp0cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRydWUsSFRN
-TFRlbXBsYXRlRWxlbWVudDp0cnVlLENvbXBvc2l0aW9uRXZlbnQ6dHJ1ZSxGb2N1c0V2ZW50OnRydWUs
-S2V5Ym9hcmRFdmVudDp0cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1ZSxVSUV2ZW50OmZh
-bHNlLFdpbmRvdzp0cnVlLERPTVdpbmRvdzp0cnVlLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOnRy
-dWUsU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1
-ZSxXb3JrZXJHbG9iYWxTY29wZTp0cnVlLEF0dHI6dHJ1ZSxDbGllbnRSZWN0OnRydWUsRE9NUmVjdDp0
-cnVlLE5hbWVkTm9kZU1hcDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLElEQktleVJhbmdlOnRydWUs
-U1ZHU2NyaXB0RWxlbWVudDp0cnVlLFNWR0FFbGVtZW50OnRydWUsU1ZHQW5pbWF0ZUVsZW1lbnQ6dHJ1
-ZSxTVkdBbmltYXRlTW90aW9uRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50OnRy
-dWUsU1ZHQW5pbWF0aW9uRWxlbWVudDp0cnVlLFNWR0NpcmNsZUVsZW1lbnQ6dHJ1ZSxTVkdDbGlwUGF0
-aEVsZW1lbnQ6dHJ1ZSxTVkdEZWZzRWxlbWVudDp0cnVlLFNWR0Rlc2NFbGVtZW50OnRydWUsU1ZHRGlz
-Y2FyZEVsZW1lbnQ6dHJ1ZSxTVkdFbGxpcHNlRWxlbWVudDp0cnVlLFNWR0ZFQmxlbmRFbGVtZW50OnRy
-dWUsU1ZHRkVDb2xvck1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxlbWVu
-dDp0cnVlLFNWR0ZFQ29tcG9zaXRlRWxlbWVudDp0cnVlLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVtZW50
-OnRydWUsU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVEaXNwbGFjZW1lbnRNYXBF
-bGVtZW50OnRydWUsU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVGbG9vZEVsZW1lbnQ6
-dHJ1ZSxTVkdGRUZ1bmNBRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0JFbGVtZW50OnRydWUsU1ZHRkVGdW5j
-R0VsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNSRWxlbWVudDp0cnVlLFNWR0ZFR2F1c3NpYW5CbHVyRWxlbWVu
-dDp0cnVlLFNWR0ZFSW1hZ2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1l
-cmdlTm9kZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OnRydWUsU1ZHRkVPZmZzZXRF
-bGVtZW50OnRydWUsU1ZHRkVQb2ludExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFU3BlY3VsYXJMaWdodGlu
-Z0VsZW1lbnQ6dHJ1ZSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVRpbGVFbGVtZW50OnRy
-dWUsU1ZHRkVUdXJidWxlbmNlRWxlbWVudDp0cnVlLFNWR0ZpbHRlckVsZW1lbnQ6dHJ1ZSxTVkdGb3Jl
-aWduT2JqZWN0RWxlbWVudDp0cnVlLFNWR0dFbGVtZW50OnRydWUsU1ZHR2VvbWV0cnlFbGVtZW50OnRy
-dWUsU1ZHR3JhcGhpY3NFbGVtZW50OnRydWUsU1ZHSW1hZ2VFbGVtZW50OnRydWUsU1ZHTGluZUVsZW1l
-bnQ6dHJ1ZSxTVkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdNYXJrZXJFbGVtZW50OnRydWUs
-U1ZHTWFza0VsZW1lbnQ6dHJ1ZSxTVkdNZXRhZGF0YUVsZW1lbnQ6dHJ1ZSxTVkdQYXRoRWxlbWVudDp0
-cnVlLFNWR1BhdHRlcm5FbGVtZW50OnRydWUsU1ZHUG9seWdvbkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5bGlu
-ZUVsZW1lbnQ6dHJ1ZSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdSZWN0RWxlbWVudDp0
-cnVlLFNWR1NldEVsZW1lbnQ6dHJ1ZSxTVkdTdG9wRWxlbWVudDp0cnVlLFNWR1N0eWxlRWxlbWVudDp0
-cnVlLFNWR1NWR0VsZW1lbnQ6dHJ1ZSxTVkdTd2l0Y2hFbGVtZW50OnRydWUsU1ZHU3ltYm9sRWxlbWVu
-dDp0cnVlLFNWR1RTcGFuRWxlbWVudDp0cnVlLFNWR1RleHRDb250ZW50RWxlbWVudDp0cnVlLFNWR1Rl
-eHRFbGVtZW50OnRydWUsU1ZHVGV4dFBhdGhFbGVtZW50OnRydWUsU1ZHVGV4dFBvc2l0aW9uaW5nRWxl
-bWVudDp0cnVlLFNWR1RpdGxlRWxlbWVudDp0cnVlLFNWR1VzZUVsZW1lbnQ6dHJ1ZSxTVkdWaWV3RWxl
-bWVudDp0cnVlLFNWR0dyYWRpZW50RWxlbWVudDp0cnVlLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVuY3Rp
-b25FbGVtZW50OnRydWUsU1ZHRkVEcm9wU2hhZG93RWxlbWVudDp0cnVlLFNWR01QYXRoRWxlbWVudDp0
-cnVlLFNWR0VsZW1lbnQ6ZmFsc2V9KQpILmJRLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZl
-clZpZXciCkguYzkuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5jYS4kbmF0
-aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILmFSLiRuYXRpdmVTdXBlcmNsYXNzVGFn
-PSJBcnJheUJ1ZmZlclZpZXciCkguY2IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmll
-dyIKSC5jYy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILmJSLiRuYXRpdmVT
-dXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXcifSkoKQpjb252ZXJ0QWxsVG9GYXN0T2JqZWN0KHcp
-CmNvbnZlcnRUb0Zhc3RPYmplY3QoJCk7KGZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBkb2N1bWVudD09PSJ1
-bmRlZmluZWQiKXthKG51bGwpCnJldHVybn1pZih0eXBlb2YgZG9jdW1lbnQuY3VycmVudFNjcmlwdCE9
-J3VuZGVmaW5lZCcpe2EoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkKcmV0dXJufXZhciB0PWRvY3VtZW50
-LnNjcmlwdHMKZnVuY3Rpb24gb25Mb2FkKGIpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7KytyKXRbcl0u
-cmVtb3ZlRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKQphKGIudGFyZ2V0KX1mb3IodmFy
-IHM9MDtzPHQubGVuZ3RoOysrcyl0W3NdLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxmYWxz
-ZSl9KShmdW5jdGlvbihhKXt2LmN1cnJlbnRTY3JpcHQ9YQppZih0eXBlb2YgZGFydE1haW5SdW5uZXI9
-PT0iZnVuY3Rpb24iKWRhcnRNYWluUnVubmVyKEwuaU8sW10pCmVsc2UgTC5pTyhbXSl9KX0pKCkKLy8j
-IHNvdXJjZU1hcHBpbmdVUkw9bWlncmF0aW9uLmpzLm1hcAo=
+biBvCnM9cC5qMih0LGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5cGVvZiBiPT0i
+bnVtYmVyIiYmKGImMHgzZmZmZmZmKT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJuIG8Kcz1wLmoy
+KHEsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAuYWEoYil9LAphYTpmdW5j
+dGlvbihhKXt2YXIgdCxzLHI9dGhpcy5kCmlmKHI9PW51bGwpcmV0dXJuIG51bGwKdD10aGlzLkJ0KHIs
+Si5oZihhKSYweDNmZmZmZmYpCnM9dGhpcy5GaCh0LGEpCmlmKHM8MClyZXR1cm4gbnVsbApyZXR1cm4g
+dFtzXS5ifSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPUguTGgobikK
+bS5kLmIoYikKbS5jaFsxXS5iKGMpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD1uLmIKbi5FSCh0PT1u
+dWxsP24uYj1uLnpLKCk6dCxiLGMpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYweDNmZmZm
+ZmYpPT09Yil7cz1uLmMKbi5FSChzPT1udWxsP24uYz1uLnpLKCk6cyxiLGMpfWVsc2V7cj1uLmQKaWYo
+cj09bnVsbClyPW4uZD1uLnpLKCkKcT1KLmhmKGIpJjB4M2ZmZmZmZgpwPW4uQnQocixxKQppZihwPT1u
+dWxsKW4uRUkocixxLFtuLkhuKGIsYyldKQplbHNle289bi5GaChwLGIpCmlmKG8+PTApcFtvXS5iPWMK
+ZWxzZSBwLnB1c2gobi5IbihiLGMpKX19fSwKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkgu
+TGgocikuQygifigxLDIpIikuYihiKQp0PXIuZQpzPXIucgpmb3IoO3QhPW51bGw7KXtiLiQyKHQuYSx0
+LmIpCmlmKHMhPT1yLnIpdGhyb3cgSC5iKFAuYTQocikpCnQ9dC5jfX0sCkVIOmZ1bmN0aW9uKGEsYixj
+KXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpCnIuZC5iKGIpCnIuY2hbMV0uYihjKQp0PXMuajIoYSxiKQpp
+Zih0PT1udWxsKXMuRUkoYSxiLHMuSG4oYixjKSkKZWxzZSB0LmI9Y30sCmtzOmZ1bmN0aW9uKCl7dGhp
+cy5yPXRoaXMucisxJjY3MTA4ODYzfSwKSG46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxo
+KHMpLHE9bmV3IEguZGIoci5kLmIoYSksci5jaFsxXS5iKGIpKQppZihzLmU9PW51bGwpcy5lPXMuZj1x
+CmVsc2V7dD1zLmYKcS5kPXQKcy5mPXQuYz1xfSsrcy5hCnMua3MoKQpyZXR1cm4gcX0sCkZoOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7
+KytzKWlmKEouUk0oYVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfSwKdzpmdW5jdGlvbihhKXtyZXR1
+cm4gUC5uTyh0aGlzKX0sCmoyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19LApCdDpmdW5jdGlvbihh
+LGIpe3JldHVybiBhW2JdfSwKRUk6ZnVuY3Rpb24oYSxiLGMpe2FbYl09Y30sCnJuOmZ1bmN0aW9uKGEs
+Yil7ZGVsZXRlIGFbYl19LApYdTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmoyKGEsYikhPW51bGx9
+LAp6SzpmdW5jdGlvbigpe3ZhciB0PSI8bm9uLWlkZW50aWZpZXIta2V5PiIscz1PYmplY3QuY3JlYXRl
+KG51bGwpCnRoaXMuRUkocyx0LHMpCnRoaXMucm4ocyx0KQpyZXR1cm4gc30sCiRpRm86MX0KSC5kYi5w
+cm90b3R5cGU9e30KSC5pNS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmF9
+LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLHM9bmV3IEguTjYodCx0LnIsdGhpcy4kdGkuQygi
+TjY8MT4iKSkKcy5jPXQuZQpyZXR1cm4gc319CkguTjYucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmEKaWYodC5iIT09cy5yKXRo
+cm93IEguYihQLmE0KHMpKQplbHNle3M9dC5jCmlmKHM9PW51bGwpe3Quc3FZKG51bGwpCnJldHVybiEx
+fWVsc2V7dC5zcVkocy5hKQp0LmM9dC5jLmMKcmV0dXJuITB9fX0sCnNxWTpmdW5jdGlvbihhKXt0aGlz
+LmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjoxfQpILmRDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e3JldHVybiB0aGlzLmEoYSl9LAokUzo0fQpILndOLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6MjJ9CkguVlgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuYShILnkoYSkpfSwKJFM6Mzh9CkguVlIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihh
+KXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5hKyIvIit0aGlzLmIuZmxhZ3N9LApnSGM6ZnVuY3Rpb24oKXt2
+YXIgdD10aGlzLHM9dC5jCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10LmIKcmV0dXJuIHQuYz1ILnY0KHQu
+YSxzLm11bHRpbGluZSwhcy5pZ25vcmVDYXNlLHMudW5pY29kZSxzLmRvdEFsbCwhMCl9LApkZDpmdW5j
+dGlvbihhLGIpe3JldHVybiBuZXcgSC5LVyh0aGlzLGIsMCl9LApVWjpmdW5jdGlvbihhLGIpe3ZhciB0
+LHM9dGhpcy5nSGMoKQpzLmxhc3RJbmRleD1iCnQ9cy5leGVjKGEpCmlmKHQ9PW51bGwpcmV0dXJuIG51
+bGwKcmV0dXJuIG5ldyBILkVLKHQpfSwKJGl2WDoxLAokaXdMOjF9CkguRUsucHJvdG90eXBlPXsKcTpm
+dW5jdGlvbihhLGIpe3ZhciB0CkguU2MoYikKdD10aGlzLmIKaWYoYj49dC5sZW5ndGgpcmV0dXJuIEgu
+T0godCxiKQpyZXR1cm4gdFtiXX0sCiRpT2Q6MSwKJGlpYjoxfQpILktXLnByb3RvdHlwZT17Cmdrejpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IEguUGIodGhpcy5hLHRoaXMuYix0aGlzLmMpfX0KSC5QYi5wcm90
+b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQscyxy
+LHEscD10aGlzLG89cC5iCmlmKG89PW51bGwpcmV0dXJuITEKdD1wLmMKaWYodDw9by5sZW5ndGgpe3M9
+cC5hCnI9cy5VWihvLHQpCmlmKHIhPW51bGwpe3AuZD1yCm89ci5iCnQ9by5pbmRleApxPXQrb1swXS5s
+ZW5ndGgKaWYodD09PXEpe2lmKHMuYi51bmljb2RlKXtvPXAuYwp0PW8rMQpzPXAuYgppZih0PHMubGVu
+Z3RoKXtvPUouclkocykubShzLG8pCmlmKG8+PTU1Mjk2JiZvPD01NjMxOSl7bz1DLnhCLm0ocyx0KQpv
+PW8+PTU2MzIwJiZvPD01NzM0M31lbHNlIG89ITF9ZWxzZSBvPSExfWVsc2Ugbz0hMQpxPShvP3ErMTpx
+KSsxfXAuYz1xCnJldHVybiEwfX1wLmI9cC5kPW51bGwKcmV0dXJuITF9LAokaUFuOjF9CkgudFEucHJv
+dG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYiE9PTApSC52aChQLngoYixudWxsKSkK
+cmV0dXJuIHRoaXMuY30sCiRpT2Q6MX0KSC51bi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0
+dXJuIG5ldyBILlNkKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguU2QucHJvdG90eXBlPXsKRjpmdW5j
+dGlvbigpe3ZhciB0LHMscj10aGlzLHE9ci5jLHA9ci5iLG89cC5sZW5ndGgsbj1yLmEsbT1uLmxlbmd0
+aAppZihxK28+bSl7ci5kPW51bGwKcmV0dXJuITF9dD1uLmluZGV4T2YocCxxKQppZih0PDApe3IuYz1t
+KzEKci5kPW51bGwKcmV0dXJuITF9cz10K28Kci5kPW5ldyBILnRRKHQscCkKci5jPXM9PT1yLmM/cysx
+OnMKcmV0dXJuITB9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LAokaUFuOjF9CkguRVQucHJv
+dG90eXBlPXskaUVUOjEsJGlBUzoxfQpILmIwLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVy
+biBhLmxlbmd0aH0sCiRpWGo6MX0KSC5EZy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhi
+KQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXtILklnKGMp
+Ckgub2QoYixhLGEubGVuZ3RoKQphW2JdPWN9LAokaWNYOjEsCiRpek06MX0KSC5QZy5wcm90b3R5cGU9
+ewpZOmZ1bmN0aW9uKGEsYixjKXtILlNjKGMpCkgub2QoYixhLGEubGVuZ3RoKQphW2JdPWN9LAokaWNY
+OjEsCiRpek06MX0KSC54ai5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIs
+YSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmRFLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtI
+LlNjKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguWkEucHJvdG90eXBlPXsKcTpm
+dW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC53Zi5w
+cm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJu
+IGFbYl19fQpILlBxLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCkgub2QoYixhLGEu
+bGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZUUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVy
+biBhW2JdfX0KSC5WNi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApx
+OmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LAokaVY2
+OjEsCiRpbjY6MX0KSC5SRy5wcm90b3R5cGU9e30KSC5WUC5wcm90b3R5cGU9e30KSC5XQi5wcm90b3R5
+cGU9e30KSC5aRy5wcm90b3R5cGU9e30KSC5KYy5wcm90b3R5cGU9ewpDOmZ1bmN0aW9uKGEpe3JldHVy
+biBILmNFKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9LApLcTpmdW5jdGlvbihhKXtyZXR1cm4gSC52NSh2
+LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0KSC5HLnByb3RvdHlwZT17fQpILnU5LnByb3RvdHlwZT17Cnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX19CkguaHoucHJvdG90eXBlPXt9CkguaU0ucHJvdG90eXBl
+PXt9ClAudGgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLHM9dC5hCnQuYT1u
+dWxsCnMuJDAoKX0sCiRTOjEyfQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMK
+dGhpcy5hLmE9dS5NLmIoYSkKdD10aGlzLmIKcz10aGlzLmMKdC5maXJzdENoaWxkP3QucmVtb3ZlQ2hp
+bGQocyk6dC5hcHBlbmRDaGlsZChzKX0sCiRTOjM2fQpQLlZzLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLlczLnByb3RvdHlwZT17
+CkNZOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNlbGYuc2V0VGltZW91dChI
+LnRSKG5ldyBQLnlIKHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5MNCgiYHNldFRpbWVvdXQo
+KWAgbm90IGZvdW5kLiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuJDAo
+KX0sCiRDOiIkMCIsCiRSOjAsCiRTOjJ9ClAuUGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxiKXt2
+YXIgdAppZihhPT1udWxsKWE9bmV3IFAubigpCnQ9dGhpcy5hCmlmKHQuYSE9PTApdGhyb3cgSC5iKFAu
+UFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQp0Lk5rKGEsYil9LApwbTpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9e30KUC5GZS5wcm90b3R5cGU9ewpI
+UjpmdW5jdGlvbihhKXtpZigodGhpcy5jJjE1KSE9PTYpcmV0dXJuITAKcmV0dXJuIHRoaXMuYi5iLmJ2
+KHUuYWwuYih0aGlzLmQpLGEuYSx1LmNKLHUuSyl9LApLdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmUs
+cz11Lnoscj11LksscT10aGlzLiR0aS5DKCIyLyIpLHA9dGhpcy5iLmIKaWYodS5ZLmModCkpcmV0dXJu
+IHEuYihwLnJwKHQsYS5hLGEuYixzLHIsdS5sKSkKZWxzZSByZXR1cm4gcS5iKHAuYnYodS55LmIodCks
+YS5hLHMscikpfX0KUC52cy5wcm90b3R5cGU9ewpTcTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9
+dGhpcy4kdGkKcS5LcShjKS5DKCIxLygyKSIpLmIoYSkKdD0kLlgzCmlmKHQhPT1DLk5VKXtjLkMoIkA8
+MC8+IikuS3EocS5kKS5DKCIxKDIpIikuYihhKQppZihiIT1udWxsKWI9UC5WSChiLHQpfXM9bmV3IFAu
+dnMoJC5YMyxjLkMoInZzPDA+IikpCnI9Yj09bnVsbD8xOjMKdGhpcy54ZihuZXcgUC5GZShzLHIsYSxi
+LHEuQygiQDwxPiIpLktxKGMpLkMoIkZlPDEsMj4iKSkpCnJldHVybiBzfSwKVzc6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gdGhpcy5TcShhLG51bGwsYil9LApPQTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5iZi5i
+KG51bGwpCnQ9dGhpcy4kdGkKcz0kLlgzCnI9bmV3IFAudnMocyx0KQppZihzIT09Qy5OVSlhPVAuVkgo
+YSxzKQp0aGlzLnhmKG5ldyBQLkZlKHIsMixudWxsLGEsdC5DKCJAPDE+IikuS3EodC5kKS5DKCJGZTwx
+LDI+IikpKQpyZXR1cm4gcn0sCnhmOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMuYQppZihyPD0x
+KXthLmE9dS54LmIocy5jKQpzLmM9YX1lbHNle2lmKHI9PT0yKXt0PXUuXy5iKHMuYykKcj10LmEKaWYo
+cjw0KXt0LnhmKGEpCnJldHVybn1zLmE9cgpzLmM9dC5jfVAuVGsobnVsbCxudWxsLHMuYix1Lk0uYihu
+ZXcgUC5kYShzLGEpKSl9fSwKalE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPXRoaXMsbj17fQpu
+LmE9YQppZihhPT1udWxsKXJldHVybgp0PW8uYQppZih0PD0xKXtzPXUueC5iKG8uYykKcj1vLmM9YQpp
+ZihzIT1udWxsKXtmb3IoO3E9ci5hLHEhPW51bGw7cj1xKTtyLmE9c319ZWxzZXtpZih0PT09Mil7cD11
+Ll8uYihvLmMpCnQ9cC5hCmlmKHQ8NCl7cC5qUShhKQpyZXR1cm59by5hPXQKby5jPXAuY31uLmE9by5O
+OChhKQpQLlRrKG51bGwsbnVsbCxvLmIsdS5NLmIobmV3IFAub1EobixvKSkpfX0sCmFoOmZ1bmN0aW9u
+KCl7dmFyIHQ9dS54LmIodGhpcy5jKQp0aGlzLmM9bnVsbApyZXR1cm4gdGhpcy5OOCh0KX0sCk44OmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLHM9bnVsbDt0IT1udWxsO3M9dCx0PXIpe3I9dC5hCnQu
+YT1zfXJldHVybiBzfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy4kdGkKci5DKCIxLyIp
+LmIoYSkKaWYoci5DKCJiODwxPiIpLmMoYSkpaWYoci5jKGEpKVAuQTkoYSxzKQplbHNlIFAuazMoYSxz
+KQplbHNle3Q9cy5haCgpCnIuZC5iKGEpCnMuYT00CnMuYz1hClAuSFoocyx0KX19LApaTDpmdW5jdGlv
+bihhLGIpe3ZhciB0LHM9dGhpcwp1LmwuYihiKQp0PXMuYWgoKQpzLmE9OApzLmM9bmV3IFAuQ3coYSxi
+KQpQLkhaKHMsdCl9LApYZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4kdGkKcy5DKCIxLyIpLmIo
+YSkKaWYocy5DKCJiODwxPiIpLmMoYSkpe3QuY1UoYSkKcmV0dXJufXQuYT0xClAuVGsobnVsbCxudWxs
+LHQuYix1Lk0uYihuZXcgUC5ySCh0LGEpKSl9LApjVTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4k
+dGkKcy5DKCJiODwxPiIpLmIoYSkKaWYocy5jKGEpKXtpZihhLmdBVCgpKXt0LmE9MQpQLlRrKG51bGws
+bnVsbCx0LmIsdS5NLmIobmV3IFAuS0YodCxhKSkpfWVsc2UgUC5BOShhLHQpCnJldHVybn1QLmszKGEs
+dCl9LApOazpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxsLHRoaXMuYix1Lk0uYihu
+ZXcgUC5aTCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigp
+e1AuSFoodGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7
+UC5IWih0aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt2YXIgdD10aGlzLmEKdC5hPTAKdC5ISChhKX0sCiRTOjEyfQpQLlU3LnByb3RvdHlwZT17CiQyOmZ1
+bmN0aW9uKGEsYil7dS5sLmIoYikKdGhpcy5hLlpMKGEsYil9LAokMTpmdW5jdGlvbihhKXtyZXR1cm4g
+dGhpcy4kMihhLG51bGwpfSwKJEM6IiQyIiwKJEQ6ZnVuY3Rpb24oKXtyZXR1cm5bbnVsbF19LAokUzoy
+NX0KUC52ci5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0s
+CiRTOjB9ClAuckgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmEscz10LiR0aS5k
+LmIodGhpcy5iKSxyPXQuYWgoKQp0LmE9NAp0LmM9cwpQLkhaKHQscil9LAokUzowfQpQLktGLnByb3Rv
+dHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5BOSh0aGlzLmIsdGhpcy5hKX0sCiRTOjB9ClAuWkwucHJvdG90
+eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLlJULnBy
+b3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPW51bGwKdHJ5e3I9
+bi5jCm09ci5iLmIuenoodS5mTy5iKHIuZCksdS56KX1jYXRjaChxKXt0PUguUnUocSkKcz1ILnRzKHEp
+CmlmKG4uZCl7cj11Lm4uYihuLmEuYS5jKS5hCnA9dApwPXI9PW51bGw/cD09bnVsbDpyPT09cApyPXB9
+ZWxzZSByPSExCnA9bi5iCmlmKHIpcC5iPXUubi5iKG4uYS5hLmMpCmVsc2UgcC5iPW5ldyBQLkN3KHQs
+cykKcC5hPSEwCnJldHVybn1pZih1LmMuYyhtKSl7aWYobSBpbnN0YW5jZW9mIFAudnMmJm0uYT49NCl7
+aWYobS5hPT09OCl7cj1uLmIKci5iPXUubi5iKG0uYykKci5hPSEwfXJldHVybn1vPW4uYS5hCnI9bi5i
+CnIuYj1tLlc3KG5ldyBQLmpaKG8pLHUueikKci5hPSExfX0sCiRTOjJ9ClAualoucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRTOjM0fQpQLnJxLnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzCnRyeXtyPW0uYgpxPXIuJHRpCnA9cS5kCm89
+cC5iKG0uYykKbS5hLmI9ci5iLmIuYnYocS5DKCIyLygxKSIpLmIoci5kKSxvLHEuQygiMi8iKSxwKX1j
+YXRjaChuKXt0PUguUnUobikKcz1ILnRzKG4pCnI9bS5hCnIuYj1uZXcgUC5Ddyh0LHMpCnIuYT0hMH19
+LAokUzoyfQpQLlJXLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbSxs
+PXRoaXMKdHJ5e3Q9dS5uLmIobC5hLmEuYykKcT1sLmMKaWYoSC5vVChxLkhSKHQpKSYmcS5lIT1udWxs
+KXtwPWwuYgpwLmI9cS5Ldyh0KQpwLmE9ITF9fWNhdGNoKG8pe3M9SC5SdShvKQpyPUgudHMobykKcT11
+Lm4uYihsLmEuYS5jKQpwPXEuYQpuPXMKbT1sLmIKaWYocD09bnVsbD9uPT1udWxsOnA9PT1uKW0uYj1x
+CmVsc2UgbS5iPW5ldyBQLkN3KHMscikKbS5hPSEwfX0sCiRTOjJ9ClAuT00ucHJvdG90eXBlPXt9ClAu
+cWgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMscT17fSxwPW5ldyBQLnZz
+KCQuWDMsdS5mSikKcS5hPTAKdD1ILkxoKHIpCnM9dC5DKCJ+KDEpIikuYihuZXcgUC5CNShxLHIpKQp1
+Lk0uYihuZXcgUC5QSShxLHApKQpXLkpFKHIuYSxyLmIscywhMSx0LmQpCnJldHVybiBwfX0KUC5CNS5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILkxoKHRoaXMuYikuZC5iKGEpOysrdGhpcy5hLmF9LAok
+UzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYikuQygiYzgoMSkiKX19ClAuUEkucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuSEgodGhpcy5hLmEpfSwKJFM6MH0KUC5NTy5wcm90b3R5cGU9
+e30KUC5rVC5wcm90b3R5cGU9e30KUC5Ddy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBI
+LmQodGhpcy5hKX0sCiRpWFM6MX0KUC5tMC5wcm90b3R5cGU9eyRpSkI6MX0KUC5wSy5wcm90b3R5cGU9
+ewokMDpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcy5hLHI9cy5hCnM9cj09bnVsbD9zLmE9bmV3IFAubigp
+OnIKcj10aGlzLmIKaWYocj09bnVsbCl0aHJvdyBILmIocykKdD1ILmIocykKdC5zdGFjaz1yLncoMCkK
+dGhyb3cgdH0sCiRTOjB9ClAuSmkucHJvdG90eXBlPXsKYkg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9
+bnVsbAp1Lk0uYihhKQp0cnl7aWYoQy5OVT09PSQuWDMpe2EuJDAoKQpyZXR1cm59UC5UOChxLHEsdGhp
+cyxhLHUuSCl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQLkwyKHEscSx0aGlzLHQsdS5sLmIo
+cykpfX0sCkRsOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT1udWxsCmMuQygifigwKSIpLmIoYSkK
+Yy5iKGIpCnRyeXtpZihDLk5VPT09JC5YMyl7YS4kMShiKQpyZXR1cm59UC55dihxLHEsdGhpcyxhLGIs
+dS5ILGMpfWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5iKHMp
+KX19LApSVDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5oaih0aGlzLGIuQygiMCgpIikuYihhKSxi
+KX0sCkdZOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5WcCh0aGlzLHUuTS5iKGEpKX0sClB5OmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIG5ldyBQLk9SKHRoaXMsYi5DKCJ+KDApIikuYihhKSxiKX0sCnE6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gbnVsbH0sCnp6OmZ1bmN0aW9uKGEsYil7Yi5DKCIwKCkiKS5iKGEpCmlmKCQu
+WDM9PT1DLk5VKXJldHVybiBhLiQwKCkKcmV0dXJuIFAuVDgobnVsbCxudWxsLHRoaXMsYSxiKX0sCmJ2
+OmZ1bmN0aW9uKGEsYixjLGQpe2MuQygiQDwwPiIpLktxKGQpLkMoIjEoMikiKS5iKGEpCmQuYihiKQpp
+ZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIs
+YyxkKX0sCnJwOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8MD4iKS5LcShlKS5LcShmKS5DKCIx
+KDIsMykiKS5iKGEpCmUuYihiKQpmLmIoYykKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDIoYixjKQpy
+ZXR1cm4gUC5ReChudWxsLG51bGwsdGhpcyxhLGIsYyxkLGUsZil9fQpQLmhqLnByb3RvdHlwZT17CiQw
+OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS56eih0aGlzLmIsdGhpcy5jKX0sCiRTOmZ1bmN0aW9uKCl7
+cmV0dXJuIHRoaXMuYy5DKCIwKCkiKX19ClAuVnAucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpcy5hLmJIKHRoaXMuYil9LAokUzoyfQpQLk9SLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMuYwpyZXR1cm4gdGhpcy5hLkRsKHRoaXMuYix0LmIoYSksdCl9LAokUzpmdW5jdGlv
+bigpe3JldHVybiB0aGlzLmMuQygifigwKSIpfX0KUC5iNi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24o
+YSl7dmFyIHQ9dGhpcyxzPW5ldyBQLmxtKHQsdC5yLEguTGgodCkuQygibG08MT4iKSkKcy5jPXQuZQpy
+ZXR1cm4gc30sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3Q9dGhpcy5iCmlmKHQ9
+PW51bGwpcmV0dXJuITEKcmV0dXJuIHUuSi5iKHRbYl0pIT1udWxsfWVsc2V7cz10aGlzLlBSKGIpCnJl
+dHVybiBzfX0sClBSOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiExCnJl
+dHVybiB0aGlzLkRGKHRbdGhpcy5OKGEpXSxhKT49MH0sCmk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9
+dGhpcwpILkxoKHIpLmQuYihiKQppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7
+dD1yLmIKcmV0dXJuIHIuYlEodD09bnVsbD9yLmI9UC5UMigpOnQsYil9ZWxzZSBpZih0eXBlb2YgYj09
+Im51bWJlciImJihiJjEwNzM3NDE4MjMpPT09Yil7cz1yLmMKcmV0dXJuIHIuYlEocz09bnVsbD9yLmM9
+UC5UMigpOnMsYil9ZWxzZSByZXR1cm4gci5CNyhiKX0sCkI3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixx
+PXRoaXMKSC5MaChxKS5kLmIoYSkKdD1xLmQKaWYodD09bnVsbCl0PXEuZD1QLlQyKCkKcz1xLk4oYSkK
+cj10W3NdCmlmKHI9PW51bGwpdFtzXT1bcS55byhhKV0KZWxzZXtpZihxLkRGKHIsYSk+PTApcmV0dXJu
+ITEKci5wdXNoKHEueW8oYSkpfXJldHVybiEwfSwKUjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGIhPT0i
+X19wcm90b19fIilyZXR1cm4gdGhpcy5MKHRoaXMuYixiKQplbHNle3Q9dGhpcy5xZyhiKQpyZXR1cm4g
+dH19LApxZzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmQKaWYobz09bnVsbClyZXR1
+cm4hMQp0PXAuTihhKQpzPW9bdF0Kcj1wLkRGKHMsYSkKaWYocjwwKXJldHVybiExCnE9cy5zcGxpY2Uo
+ciwxKVswXQppZigwPT09cy5sZW5ndGgpZGVsZXRlIG9bdF0KcC5HUyhxKQpyZXR1cm4hMH0sCmJROmZ1
+bmN0aW9uKGEsYil7SC5MaCh0aGlzKS5kLmIoYikKaWYodS5KLmIoYVtiXSkhPW51bGwpcmV0dXJuITEK
+YVtiXT10aGlzLnlvKGIpCnJldHVybiEwfSwKTDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwp
+cmV0dXJuITEKdD11LkouYihhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMuR1ModCkKZGVsZXRl
+IGFbYl0KcmV0dXJuITB9LApTOmZ1bmN0aW9uKCl7dGhpcy5yPTEwNzM3NDE4MjMmdGhpcy5yKzF9LAp5
+bzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1uZXcgUC5ibihILkxoKHMpLmQuYihhKSkKaWYocy5l
+PT1udWxsKXMuZT1zLmY9cgplbHNle3Q9cy5mCnIuYz10CnMuZj10LmI9cn0rK3MuYQpzLlMoKQpyZXR1
+cm4gcn0sCkdTOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1hLmMscj1hLmIKaWYocz09bnVsbCl0LmU9
+cgplbHNlIHMuYj1yCmlmKHI9PW51bGwpdC5mPXMKZWxzZSByLmM9czstLXQuYQp0LlMoKX0sCk46ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sCkRGOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0oYVtz
+XS5hLGIpKXJldHVybiBzCnJldHVybi0xfX0KUC5ibi5wcm90b3R5cGU9e30KUC5sbS5wcm90b3R5cGU9
+ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQu
+YQppZih0LmIhPT1zLnIpdGhyb3cgSC5iKFAuYTQocykpCmVsc2V7cz10LmMKaWYocz09bnVsbCl7dC5z
+aihudWxsKQpyZXR1cm4hMX1lbHNle3Quc2oodC4kdGkuZC5iKHMuYSkpCnQuYz10LmMuYgpyZXR1cm4h
+MH19fSwKc2o6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KUC5tVy5w
+cm90b3R5cGU9e30KUC5MVS5wcm90b3R5cGU9eyRpY1g6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsK
+Z2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5hNyhhLHRoaXMuZ0EoYSksSC56SyhhKS5DKCJhNzxs
+RC5FPiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LApLOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscwpILnpLKGEpLkMoIn4obEQuRSkiKS5iKGIpCnQ9dGhpcy5nQShhKQpmb3Iocz0wO3M8
+dDsrK3Mpe2IuJDEodGhpcy5xKGEscykpCmlmKHQhPT10aGlzLmdBKGEpKXRocm93IEguYihQLmE0KGEp
+KX19LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC56SyhhKQpyZXR1cm4gbmV3IEguQTgoYSx0Lktx
+KGMpLkMoIjEobEQuRSkiKS5iKGIpLHQuQygiQDxsRC5FPiIpLktxKGMpLkMoIkE4PDEsMj4iKSl9LApk
+dTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdApILnpLKGEpLkMoImxELkUiKS5iKGQpClAuakIoYixjLHRo
+aXMuZ0EoYSkpCmZvcih0PWI7dDxjOysrdCl0aGlzLlkoYSx0LGQpfSwKdzpmdW5jdGlvbihhKXtyZXR1
+cm4gUC5XRShhLCJbIiwiXSIpfX0KUC5pbC5wcm90b3R5cGU9e30KUC5yYS5wcm90b3R5cGU9ewokMjpm
+dW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5hCmlmKCFzLmEpdGhpcy5iLmErPSIsICIKcy5hPSExCnM9
+dGhpcy5iCnQ9cy5hKz1ILmQoYSkKcy5hPXQrIjogIgpzLmErPUguZChiKX0sCiRTOjF9ClAuWWsucHJv
+dG90eXBlPXsKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC5MaCh0aGlzKS5DKCJ+KFlrLkssWWsuViki
+KS5iKGIpCmZvcih0PUouSVQodGhpcy5nVigpKTt0LkYoKTspe3M9dC5nbCgpCmIuJDIocyx0aGlzLnEo
+MCxzKSl9fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSG0odGhpcy5nVigpKX0sCnc6ZnVuY3Rpb24o
+YSl7cmV0dXJuIFAubk8odGhpcyl9LAokaVowOjF9ClAuS1AucHJvdG90eXBlPXsKWTpmdW5jdGlvbihh
+LGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0LmQuYihiKQp0LmNoWzFdLmIoYykKdGhyb3cgSC5iKFAuTDQo
+IkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIG1hcCIpKX19ClAuUG4ucHJvdG90eXBlPXsKcTpmdW5j
+dGlvbihhLGIpe3JldHVybiB0aGlzLmEucSgwLGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5M
+aCh0aGlzKQp0aGlzLmEuWSgwLHQuZC5iKGIpLHQuY2hbMV0uYihjKSl9LApLOmZ1bmN0aW9uKGEsYil7
+dGhpcy5hLksoMCxILkxoKHRoaXMpLkMoIn4oMSwyKSIpLmIoYikpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5hCnJldHVybiB0LmdBKHQpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuYSl9
+LAokaVowOjF9ClAuR2oucHJvdG90eXBlPXt9ClAubGYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXty
+ZXR1cm4gUC5XRSh0aGlzLCJ7IiwifSIpfX0KUC5Wai5wcm90b3R5cGU9eyRpY1g6MSwkaXh1OjF9ClAu
+WHYucHJvdG90eXBlPXsKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1KLklUKEguTGgodGhpcyku
+QygiY1g8MT4iKS5iKGIpKTt0LkYoKTspdGhpcy5pKDAsdC5nbCgpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIFAuV0UodGhpcywieyIsIn0iKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPVAucmoodGhpcyx0
+aGlzLnIsSC5MaCh0aGlzKS5kKQppZighcy5GKCkpcmV0dXJuIiIKaWYoYj09PSIiKXt0PSIiCmRvIHQr
+PUguZChzLmQpCndoaWxlKHMuRigpKX1lbHNle3Q9SC5kKHMuZCkKZm9yKDtzLkYoKTspdD10K2IrSC5k
+KHMuZCl9cmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaWNYOjEsCiRpeHU6MX0KUC5uWS5w
+cm90b3R5cGU9e30KUC5XWS5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5
+cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4gdGhpcy5j
+LnEoMCxiKQplbHNlIGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3Q9c1tiXQpy
+ZXR1cm4gdHlwZW9mIHQ9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6dH19LApnQTpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5iPT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApnVjpmdW5jdGlvbigp
+e2lmKHRoaXMuYj09bnVsbCl7dmFyIHQ9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgodCkuQygi
+aTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxy
+PXRoaXMKaWYoci5iPT1udWxsKXIuYy5ZKDAsYixjKQplbHNlIGlmKHIueDQoYikpe3Q9ci5iCnRbYl09
+YwpzPXIuYQppZihzPT1udWxsP3QhPW51bGw6cyE9PXQpc1tiXT1udWxsfWVsc2Ugci5YSygpLlkoMCxi
+LGMpfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0aGlzLmMueDQoYSkKcmV0
+dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSl9LApLOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuY0EuYihiKQppZihwLmI9PW51bGwpcmV0dXJuIHAu
+Yy5LKDAsYikKdD1wLkNmKCkKZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCnE9cC5iW3JdCmlm
+KHR5cGVvZiBxPT0idW5kZWZpbmVkIil7cT1QLlFlKHAuYVtyXSkKcC5iW3JdPXF9Yi4kMihyLHEpCmlm
+KHQhPT1wLmMpdGhyb3cgSC5iKFAuYTQocCkpfX0sCkNmOmZ1bmN0aW9uKCl7dmFyIHQ9dS5qLmIodGhp
+cy5jKQppZih0PT1udWxsKXQ9dGhpcy5jPUguVk0oT2JqZWN0LmtleXModGhpcy5hKSx1LnMpCnJldHVy
+biB0fSwKWEs6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG89dGhpcwppZihvLmI9PW51bGwpcmV0dXJu
+IG8uYwp0PVAuRmwodS5OLHUueikKcz1vLkNmKCkKZm9yKHI9MDtxPXMubGVuZ3RoLHI8cTsrK3Ipe3A9
+c1tyXQp0LlkoMCxwLG8ucSgwLHApKX1pZihxPT09MClDLk5tLmkocyxudWxsKQplbHNlIEMuTm0uc0Eo
+cywwKQpvLmE9by5iPW51bGwKcmV0dXJuIG8uYz10fSwKZmI6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoIU9i
+amVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkpcmV0dXJuIG51bGwKdD1Q
+LlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT10fX0KUC5pOC5wcm90b3R5cGU9ewpnQTpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHQ9
+dGhpcy5hCmlmKHQuYj09bnVsbCl0PXQuZ1YoKS5FKDAsYikKZWxzZXt0PXQuQ2YoKQppZihiPDB8fGI+
+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKdD10W2JdfXJldHVybiB0fSwKZ2t6OmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMuYQppZih0LmI9PW51bGwpe3Q9dC5nVigpCnQ9dC5na3oodCl9ZWxzZXt0PXQuQ2Yo
+KQp0PW5ldyBKLm0xKHQsdC5sZW5ndGgsSC50Nih0KS5DKCJtMTwxPiIpKX1yZXR1cm4gdH19ClAuQ1Yu
+cHJvdG90eXBlPXsKeXI6ZnVuY3Rpb24oYSxhMCxhMSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixp
+LGgsZyxmLGUsZCxjLGI9IkludmFsaWQgYmFzZTY0IGVuY29kaW5nIGxlbmd0aCAiCmExPVAuakIoYTAs
+YTEsYS5sZW5ndGgpCnQ9JC5WNygpCmZvcihzPWEwLHI9cyxxPW51bGwscD0tMSxvPS0xLG49MDtzPGEx
+O3M9bSl7bT1zKzEKbD1DLnhCLlcoYSxzKQppZihsPT09Mzcpe2s9bSsyCmlmKGs8PWExKXtqPUgub28o
+Qy54Qi5XKGEsbSkpCmk9SC5vbyhDLnhCLlcoYSxtKzEpKQpoPWoqMTYraS0oaSYyNTYpCmlmKGg9PT0z
+NyloPS0xCm09a31lbHNlIGg9LTF9ZWxzZSBoPWwKaWYoMDw9aCYmaDw9MTI3KXtpZihoPDB8fGg+PXQu
+bGVuZ3RoKXJldHVybiBILk9IKHQsaCkKZz10W2hdCmlmKGc+PTApe2g9Qy54Qi5tKCJBQkNERUZHSElK
+S0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvIixnKQpp
+ZihoPT09bCljb250aW51ZQpsPWh9ZWxzZXtpZihnPT09LTEpe2lmKHA8MCl7Zj1xPT1udWxsP251bGw6
+cS5hLmxlbmd0aAppZihmPT1udWxsKWY9MApwPWYrKHMtcikKbz1zfSsrbgppZihsPT09NjEpY29udGlu
+dWV9bD1ofWlmKGchPT0tMil7aWYocT09bnVsbClxPW5ldyBQLlJuKCIiKQpxLmErPUMueEIuTmooYSxy
+LHMpCnEuYSs9SC5MdyhsKQpyPW0KY29udGludWV9fXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2
+NCBkYXRhIixhLHMpKX1pZihxIT1udWxsKXtmPXEuYSs9Qy54Qi5OaihhLHIsYTEpCmU9Zi5sZW5ndGgK
+aWYocD49MClQLnhNKGEsbyxhMSxwLG4sZSkKZWxzZXtkPUMuam4uelkoZS0xLDQpKzEKaWYoZD09PTEp
+dGhyb3cgSC5iKFAucnIoYixhLGExKSkKZm9yKDtkPDQ7KXtmKz0iPSIKcS5hPWY7KytkfX1mPXEuYQpy
+ZXR1cm4gQy54Qi5pNyhhLGEwLGExLGYuY2hhckNvZGVBdCgwKT09MD9mOmYpfWM9YTEtYTAKaWYocD49
+MClQLnhNKGEsbyxhMSxwLG4sYykKZWxzZXtkPUMuam4uelkoYyw0KQppZihkPT09MSl0aHJvdyBILmIo
+UC5ycihiLGEsYTEpKQppZihkPjEpYT1DLnhCLmk3KGEsYTEsYTEsZD09PTI/Ij09IjoiPSIpfXJldHVy
+biBhfX0KUC5VOC5wcm90b3R5cGU9e30KUC5Vay5wcm90b3R5cGU9e30KUC53SS5wcm90b3R5cGU9e30K
+UC5aaS5wcm90b3R5cGU9e30KUC5ieS5wcm90b3R5cGU9ewpwVzpmdW5jdGlvbihhLGIsYyl7dmFyIHQK
+dS5lcC5iKGMpCnQ9UC5CUyhiLHRoaXMuZ0hlKCkuYSkKcmV0dXJuIHR9LApnSGU6ZnVuY3Rpb24oKXty
+ZXR1cm4gQy5BM319ClAuTXgucHJvdG90eXBlPXt9ClAudTUucHJvdG90eXBlPXsKZ1pFOmZ1bmN0aW9u
+KCl7cmV0dXJuIEMuUWt9fQpQLkUzLnByb3RvdHlwZT17CldKOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1Q
+LmpCKDAsbnVsbCxhLmdBKGEpKSxxPXItMAppZihxPT09MClyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCkK
+dD1uZXcgVWludDhBcnJheShxKjMpCnM9bmV3IFAuUncodCkKaWYocy5HeChhLDAscikhPT1yKXMuTzYo
+YS5tKDAsci0xKSwwKQpyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodC5zdWJhcnJheSgwLEguck0oMCxzLmIs
+dC5sZW5ndGgpKSl9fQpQLlJ3LnByb3RvdHlwZT17Ck82OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEs
+cD10aGlzCmlmKChiJjY0NTEyKT09PTU2MzIwKVAuWlooYSxiKQplbHNle3Q9cC5jCnM9cC5iKysKcj1D
+LmpuLkFnKDIyNCxhLkhaKDAsMTIpKQpxPXQubGVuZ3RoCmlmKHM+PXEpcmV0dXJuIEguT0godCxzKQp0
+W3NdPXIKcj1wLmIrKwpzPUMuam4uQWcoMTI4LGEuSFooMCw2KS56TSgwLDYzKSkKaWYocj49cSlyZXR1
+cm4gSC5PSCh0LHIpCnRbcl09cwpzPXAuYisrCnI9Qy5qbi5BZygxMjgsYS56TSgwLDYzKSkKaWYocz49
+cSlyZXR1cm4gSC5PSCh0LHMpCnRbc109cgpyZXR1cm4hMX19LApHeDpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHEscCxvLG4sbT10aGlzCmlmKGIhPT1jJiZQLk1kKGEubSgwLGMtMSkpKS0tYwpmb3IodD1t
+LmMscz10Lmxlbmd0aCxyPWI7cjxjOysrcil7cT1hLm0oMCxyKQppZihxLkN0KDAsMTI3KSl7cD1tLmIK
+aWYocD49cylicmVhawptLmI9cCsxCkMuTkEuWSh0LHAscSl9ZWxzZSBpZihQLk1kKHEpKXtpZihtLmIr
+Mz49cylicmVhawpvPXIrMQppZihtLk82KHEsYS5tKDAsbykpKXI9b31lbHNlIGlmKHEuQ3QoMCwyMDQ3
+KSl7cD1tLmIKbj1wKzEKaWYobj49cylicmVhawptLmI9bgpuPUMuam4uQWcoMTkyLHEuSFooMCw2KSkK
+aWYocD49cylyZXR1cm4gSC5PSCh0LHApCnRbcF09bgpuPW0uYisrCnA9Qy5qbi5BZygxMjgscS56TSgw
+LDYzKSkKaWYobj49cylyZXR1cm4gSC5PSCh0LG4pCnRbbl09cH1lbHNle3A9bS5iCmlmKHArMj49cyli
+cmVhawptLmI9cCsxCm49Qy5qbi5BZygyMjQscS5IWigwLDEyKSkKaWYocD49cylyZXR1cm4gSC5PSCh0
+LHApCnRbcF09bgpuPW0uYisrCnA9Qy5qbi5BZygxMjgscS5IWigwLDYpLnpNKDAsNjMpKQppZihuPj1z
+KXJldHVybiBILk9IKHQsbikKdFtuXT1wCnA9bS5iKysKbj1DLmpuLkFnKDEyOCxxLnpNKDAsNjMpKQpp
+ZihwPj1zKXJldHVybiBILk9IKHQscCkKdFtwXT1ufX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsK
+V0o6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsCnUuTC5iKGEpCnQ9UC5reSghMSxhLDAs
+bnVsbCkKaWYodCE9bnVsbClyZXR1cm4gdApzPVAuakIoMCxudWxsLEouSG0oYSkpCnI9UC5jUChhLDAs
+cykKaWYocj4wKXtxPVAuSE0oYSwwLHIpCmlmKHI9PT1zKXJldHVybiBxCnA9bmV3IFAuUm4ocSkKbz1y
+Cm49ITF9ZWxzZXtvPTAKcD1udWxsCm49ITB9aWYocD09bnVsbClwPW5ldyBQLlJuKCIiKQptPW5ldyBQ
+LmJ6KCExLHApCm0uYz1uCm0uTUUoYSxvLHMpCmlmKG0uZT4wKXtILnZoKFAucnIoIlVuZmluaXNoZWQg
+VVRGLTggb2N0ZXQgc2VxdWVuY2UiLGEscykpCnAuYSs9SC5Mdyg2NTUzMykKbS5mPW0uZT1tLmQ9MH1s
+PXAuYQpyZXR1cm4gbC5jaGFyQ29kZUF0KDApPT0wP2w6bH19ClAuYnoucHJvdG90eXBlPXsKTUU6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMsZz0iQmFkIFVURi04
+IGVuY29kaW5nIDB4Igp1LkwuYihhKQp0PWguZApzPWguZQpyPWguZgpoLmY9aC5lPWguZD0wCiRsYWJl
+bDAkMDpmb3IocT1KLlU2KGEpLHA9aC5iLG89YjshMDtvPWopeyRsYWJlbDEkMTppZihzPjApe2Rve2lm
+KG89PT1jKWJyZWFrICRsYWJlbDAkMApuPXEucShhLG8pCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0
+dXJuIG4uek0oKQppZigobiYxOTIpIT09MTI4KXttPVAucnIoZytDLmpuLldaKG4sMTYpLGEsbykKdGhy
+b3cgSC5iKG0pfWVsc2V7dD0odDw8NnxuJjYzKT4+PjA7LS1zOysrb319d2hpbGUocz4wKQptPXItMQpp
+ZihtPDB8fG0+PTQpcmV0dXJuIEguT0goQy5HYixtKQppZih0PD1DLkdiW21dKXttPVAucnIoIk92ZXJs
+b25nIGVuY29kaW5nIG9mIDB4IitDLmpuLldaKHQsMTYpLGEsby1yLTEpCnRocm93IEguYihtKX1pZih0
+PjExMTQxMTEpe209UC5ycigiQ2hhcmFjdGVyIG91dHNpZGUgdmFsaWQgVW5pY29kZSByYW5nZTogMHgi
+K0Muam4uV1oodCwxNiksYSxvLXItMSkKdGhyb3cgSC5iKG0pfWlmKCFoLmN8fHQhPT02NTI3OSlwLmEr
+PUguTHcodCkKaC5jPSExfWZvcihtPW88YzttOyl7bD1QLmNQKGEsbyxjKQppZihsPjApe2guYz0hMQpr
+PW8rbApwLmErPVAuSE0oYSxvLGspCmlmKGs9PT1jKWJyZWFrfWVsc2Ugaz1vCmo9aysxCm49cS5xKGEs
+aykKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5KKCkKaWYobjwwKXtpPVAucnIoIk5lZ2F0
+aXZlIFVURi04IGNvZGUgdW5pdDogLTB4IitDLmpuLldaKC1uLDE2KSxhLGotMSkKdGhyb3cgSC5iKGkp
+fWVsc2V7aWYoKG4mMjI0KT09PTE5Mil7dD1uJjMxCnM9MQpyPTEKY29udGludWUgJGxhYmVsMCQwfWlm
+KChuJjI0MCk9PT0yMjQpe3Q9biYxNQpzPTIKcj0yCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDgp
+PT09MjQwJiZuPDI0NSl7dD1uJjcKcz0zCnI9Mwpjb250aW51ZSAkbGFiZWwwJDB9aT1QLnJyKGcrQy5q
+bi5XWihuLDE2KSxhLGotMSkKdGhyb3cgSC5iKGkpfX1icmVhayAkbGFiZWwwJDB9aWYocz4wKXtoLmQ9
+dApoLmU9cwpoLmY9cn19fQpQLldGLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+CnUuZm8uYihhKQp0PXRoaXMuYgpzPXRoaXMuYQp0LmErPXMuYQpyPXQuYSs9SC5kKGEuYSkKdC5hPXIr
+IjogIgp0LmErPVAucChiKQpzLmE9IiwgIn0sCiRTOjE3fQpQLmEyLnByb3RvdHlwZT17fQpQLmlQLnBy
+b3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0
+YW5jZW9mIFAuaVAmJnRoaXMuYT09PWIuYSYmITB9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5h
+CnJldHVybih0XkMuam4ud0codCwzMCkpJjEwNzM3NDE4MjN9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMscz1QLkdxKEgudEoodCkpLHI9UC5oMChILk5TKHQpKSxxPVAuaDAoSC5qQSh0KSkscD1QLmgwKEgu
+S0wodCkpLG89UC5oMChILmNoKHQpKSxuPVAuaDAoSC5KZCh0KSksbT1QLlZ4KEgubzEodCkpLGw9cysi
+LSIrcisiLSIrcSsiICIrcCsiOiIrbysiOiIrbisiLiIrbQpyZXR1cm4gbH19ClAuQ1AucHJvdG90eXBl
+PXt9ClAuWFMucHJvdG90eXBlPXt9ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10
+aGlzLmEKaWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAodCkKcmV0dXJuIkFz
+c2VydGlvbiBmYWlsZWQifX0KUC5uLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93
+IG9mIG51bGwuIn19ClAudS5wcm90b3R5cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJJbnZhbGlkIGFy
+Z3VtZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApndTpmdW5jdGlvbigpe3JldHVybiIifSwKdzpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysiKSI6IiIKbz1w
+LmQKdD1vPT1udWxsPyIiOiI6ICIrSC5kKG8pCnM9cC5nWigpK24rdAppZighcC5hKXJldHVybiBzCnI9
+cC5ndSgpCnE9UC5wKHAuYikKcmV0dXJuIHMrcisiOiAiK3F9fQpQLmJKLnByb3RvdHlwZT17CmdaOmZ1
+bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcy5l
+CmlmKHI9PW51bGwpe3I9dGhpcy5mCnQ9ciE9bnVsbD8iOiBOb3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRv
+ICIrSC5kKHIpOiIifWVsc2V7cz10aGlzLmYKaWYocz09bnVsbCl0PSI6IE5vdCBncmVhdGVyIHRoYW4g
+b3IgZXF1YWwgdG8gIitILmQocikKZWxzZSBpZihzPnIpdD0iOiBOb3QgaW4gcmFuZ2UgIitILmQocikr
+Ii4uIitILmQocykrIiwgaW5jbHVzaXZlIgplbHNlIHQ9czxyPyI6IFZhbGlkIHZhbHVlIHJhbmdlIGlz
+IGVtcHR5IjoiOiBPbmx5IHZhbGlkIHZhbHVlIGlzICIrSC5kKHIpfXJldHVybiB0fX0KUC5lWS5wcm90
+b3R5cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFy
+IHQscz1ILlNjKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYoczww
+KXJldHVybiI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1
+cm4iOiBubyBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhh
+biAiK0guZCh0KX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1wLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxqPW5ldyBQLlJuKCIi
+KQprLmE9IiIKZm9yKHQ9bC5jLHM9dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7KytyLHA9IiwgIil7
+bz10W3JdCmouYT1xK3AKcT1qLmErPVAucChvKQprLmE9IiwgIn1sLmQuSygwLG5ldyBQLldGKGssaikp
+Cm49UC5wKGwuYSkKbT1qLncoMCkKdD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6
+ICciK0guZChsLmIuYSkrIidcblJlY2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBbIittKyJdIgpyZXR1
+cm4gdH19ClAudWIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iVW5zdXBwb3J0ZWQgb3Bl
+cmF0aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEKcmV0dXJuIHQhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmltcGxlbWVudGVkRXJy
+b3IifX0KUC5sai5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJCYWQgc3RhdGU6ICIrdGhp
+cy5hfX0KUC5VVi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQppZih0PT1udWxs
+KXJldHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uLiIKcmV0dXJuIkNv
+bmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5wKHQpKyIuIn19ClAuazUu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9LAokaVhTOjF9ClAu
+S1kucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iU3RhY2sgT3ZlcmZsb3cifSwKJGlYUzox
+fQpQLmMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQ9PW51bGw/
+IlJlYWRpbmcgc3RhdGljIHZhcmlhYmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5n
+IHN0YXRpYyB2YXJpYWJsZSAnIit0KyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5w
+cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfX0KUC5hRS5w
+cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMu
+YSxnPSIiIT09aD8iRm9ybWF0RXhjZXB0aW9uOiAiK2g6IkZvcm1hdEV4Y2VwdGlvbiIsZj10aGlzLmMs
+ZT10aGlzLmIKaWYodHlwZW9mIGU9PSJzdHJpbmciKXtpZihmIT1udWxsKWg9ZjwwfHxmPmUubGVuZ3Ro
+CmVsc2UgaD0hMQppZihoKWY9bnVsbAppZihmPT1udWxsKXt0PWUubGVuZ3RoPjc4P0MueEIuTmooZSww
+LDc1KSsiLi4uIjplCnJldHVybiBnKyJcbiIrdH1mb3Iocz0xLHI9MCxxPSExLHA9MDtwPGY7KytwKXtv
+PUMueEIuVyhlLHApCmlmKG89PT0xMCl7aWYociE9PXB8fCFxKSsrcwpyPXArMQpxPSExfWVsc2UgaWYo
+bz09PTEzKXsrK3MKcj1wKzEKcT0hMH19Zz1zPjE/ZysoIiAoYXQgbGluZSAiK3MrIiwgY2hhcmFjdGVy
+ICIrKGYtcisxKSsiKVxuIik6ZysoIiAoYXQgY2hhcmFjdGVyICIrKGYrMSkrIilcbiIpCm49ZS5sZW5n
+dGgKZm9yKHA9ZjtwPG47KytwKXtvPUMueEIubShlLHApCmlmKG89PT0xMHx8bz09PTEzKXtuPXAKYnJl
+YWt9fWlmKG4tcj43OClpZihmLXI8NzUpe209cis3NQpsPXIKaz0iIgpqPSIuLi4ifWVsc2V7aWYobi1m
+PDc1KXtsPW4tNzUKbT1uCmo9IiJ9ZWxzZXtsPWYtMzYKbT1mKzM2Cmo9Ii4uLiJ9az0iLi4uIn1lbHNl
+e209bgpsPXIKaz0iIgpqPSIifWk9Qy54Qi5OaihlLGwsbSkKcmV0dXJuIGcraytpK2orIlxuIitDLnhC
+Lkl4KCIgIixmLWwray5sZW5ndGgpKyJeXG4ifWVsc2UgcmV0dXJuIGYhPW51bGw/ZysoIiAoYXQgb2Zm
+c2V0ICIrSC5kKGYpKyIpIik6Z319ClAuRUgucHJvdG90eXBlPXt9ClAuS04ucHJvdG90eXBlPXt9ClAu
+Y1gucHJvdG90eXBlPXsKZXY6ZnVuY3Rpb24oYSxiKXt2YXIgdD1ILkxoKHRoaXMpCnJldHVybiBuZXcg
+SC5VNSh0aGlzLHQuQygiYTIoY1guRSkiKS5iKGIpLHQuQygiVTU8Y1guRT4iKSl9LApnQTpmdW5jdGlv
+bihhKXt2YXIgdCxzPXRoaXMuZ2t6KHRoaXMpCmZvcih0PTA7cy5GKCk7KSsrdApyZXR1cm4gdH0sCmds
+MDpmdW5jdGlvbihhKXtyZXR1cm4hdGhpcy5na3oodGhpcykuRigpfSwKZ3I4OmZ1bmN0aW9uKGEpe3Zh
+ciB0LHM9dGhpcy5na3oodGhpcykKaWYoIXMuRigpKXRocm93IEguYihILldwKCkpCnQ9cy5nbCgpCmlm
+KHMuRigpKXRocm93IEguYihILmRVKCkpCnJldHVybiB0fSwKRTpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cgpQLmsxKGIsImluZGV4IikKZm9yKHQ9dGhpcy5na3oodGhpcykscz0wO3QuRigpOyl7cj10LmdsKCkK
+aWYoYj09PXMpcmV0dXJuIHI7KytzfXRocm93IEguYihQLkNmKGIsdGhpcywiaW5kZXgiLG51bGwscykp
+fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5FUCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90b3R5cGU9
+e30KUC56TS5wcm90b3R5cGU9eyRpY1g6MX0KUC5aMC5wcm90b3R5cGU9e30KUC5jOC5wcm90b3R5cGU9
+ewpnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFAuay5wcm90b3R5cGUuZ2lPLmNhbGwodGhpcyx0aGlzKX0s
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifX0KUC5GSy5wcm90b3R5cGU9e30KUC5rLnByb3RvdHlw
+ZT17Y29uc3RydWN0b3I6UC5rLCRpazoxLApETjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzPT09Yn0s
+CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUSh0aGlzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIklu
+c3RhbmNlIG9mICciK0guZChILk0odGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dS5vLmIoYikK
+dGhyb3cgSC5iKFAubHIodGhpcyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwKdG9TdHJpbmc6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy53KHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30KUC5pYi5wcm90b3R5
+cGU9eyRpT2Q6MX0KUC54dS5wcm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30KUC5xVS5wcm90b3R5
+cGU9eyRpdlg6MX0KUC5Sbi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxl
+bmd0aH0sCnc6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/
+dDp0fSwKJGlCTDoxfQpQLkdELnByb3RvdHlwZT17fQpQLm4xLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9u
+KGEsYil7dmFyIHQscyxyLHEKdS5mLmIoYSkKSC55KGIpCnQ9Si5yWShiKS5PWShiLCI9IikKaWYodD09
+PS0xKXtpZihiIT09IiIpYS5ZKDAsUC5rdShiLDAsYi5sZW5ndGgsdGhpcy5hLCEwKSwiIil9ZWxzZSBp
+Zih0IT09MCl7cz1DLnhCLk5qKGIsMCx0KQpyPUMueEIuRyhiLHQrMSkKcT10aGlzLmEKYS5ZKDAsUC5r
+dShzLDAscy5sZW5ndGgscSwhMCksUC5rdShyLDAsci5sZW5ndGgscSwhMCkpfXJldHVybiBhfSwKJFM6
+MTh9ClAuY1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmIoUC5ycigiSWxsZWdh
+bCBJUHY0IGFkZHJlc3MsICIrYSx0aGlzLmEsYikpfSwKJFM6MzV9ClAuVkMucHJvdG90eXBlPXsKJDI6
+ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBJUHY2IGFkZHJlc3MsICIrYSx0aGlz
+LmEsYikpfSwKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRTOjIwfQpQLnRw
+LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYi1hPjQpdGhpcy5hLiQyKCJhbiBJ
+UHY2IHBhcnQgY2FuIG9ubHkgY29udGFpbiBhIG1heGltdW0gb2YgNCBoZXggZGlnaXRzIixhKQp0PVAu
+UUEoQy54Qi5Oaih0aGlzLmIsYSxiKSxudWxsLDE2KQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVy
+biB0LkooKQppZih0PDB8fHQ+NjU1MzUpdGhpcy5hLiQyKCJlYWNoIHBhcnQgbXVzdCBiZSBpbiB0aGUg
+cmFuZ2Ugb2YgYDB4MC4uMHhGRkZGYCIsYSkKcmV0dXJuIHR9LAokUzoyMX0KUC5Ebi5wcm90b3R5cGU9
+ewpna3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5ifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMu
+YwppZih0PT1udWxsKXJldHVybiIiCmlmKEMueEIubih0LCJbIikpcmV0dXJuIEMueEIuTmoodCwxLHQu
+bGVuZ3RoLTEpCnJldHVybiB0fSwKZ3RwOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxs
+KXJldHVybiBQLndLKHRoaXMuYSkKcmV0dXJuIHR9LApndFA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYK
+cmV0dXJuIHQ9PW51bGw/IiI6dH0sCmdLYTpmdW5jdGlvbigpe3ZhciB0PXRoaXMucgpyZXR1cm4gdD09
+bnVsbD8iIjp0fSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLngKaWYocyE9bnVsbClyZXR1cm4g
+cwp0PXRoaXMuZQppZih0Lmxlbmd0aCE9PTAmJkMueEIuVyh0LDApPT09NDcpdD1DLnhCLkcodCwxKQpz
+PXQ9PT0iIj9DLnhEOlAuT1cobmV3IEguQTgoSC5WTSh0LnNwbGl0KCIvIiksdS5zKSx1LmRPLmIoUC5Q
+SCgpKSx1LmRvKSx1Lk4pCnRoaXMuc282KHMpCnJldHVybiBzfSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQs
+cz10aGlzCmlmKHMuUT09bnVsbCl7dD1zLmYKcy5zUkgobmV3IFAuR2ooUC5XWCh0PT1udWxsPyIiOnQp
+LHUuVykpfXJldHVybiBzLlF9LApKaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbwpmb3IodD0w
+LHM9MDtDLnhCLlFpKGIsIi4uLyIscyk7KXtzKz0zOysrdH1yPUMueEIuY24oYSwiLyIpCndoaWxlKCEw
+KXtpZighKHI+MCYmdD4wKSlicmVhawpxPUMueEIuUGsoYSwiLyIsci0xKQppZihxPDApYnJlYWsKcD1y
+LXEKbz1wIT09MgppZighb3x8cD09PTMpaWYoQy54Qi5tKGEscSsxKT09PTQ2KW89IW98fEMueEIubShh
+LHErMik9PT00NgplbHNlIG89ITEKZWxzZSBvPSExCmlmKG8pYnJlYWs7LS10CnI9cX1yZXR1cm4gQy54
+Qi5pNyhhLHIrMSxudWxsLEMueEIuRyhiLHMtMyp0KSl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPXRoaXMs
+aj1udWxsCmlmKGEuZ0ZpKCkubGVuZ3RoIT09MCl7dD1hLmdGaSgpCmlmKGEuZ2NqKCkpe3M9YS5na3Uo
+KQpyPWEuZ0pmKGEpCnE9YS5neEEoKT9hLmd0cChhKTpqfWVsc2V7cT1qCnI9cQpzPSIifXA9UC54ZShh
+LmdJaShhKSkKbz1hLmdRRCgpP2EuZ3RQKCk6an1lbHNle3Q9ay5hCmlmKGEuZ2NqKCkpe3M9YS5na3Uo
+KQpyPWEuZ0pmKGEpCnE9UC53QihhLmd4QSgpP2EuZ3RwKGEpOmosdCkKcD1QLnhlKGEuZ0lpKGEpKQpv
+PWEuZ1FEKCk/YS5ndFAoKTpqfWVsc2V7cz1rLmIKcj1rLmMKcT1rLmQKaWYoYS5nSWkoYSk9PT0iIil7
+cD1rLmUKbz1hLmdRRCgpP2EuZ3RQKCk6ay5mfWVsc2V7aWYoYS5ndFQoKSlwPVAueGUoYS5nSWkoYSkp
+CmVsc2V7bj1rLmUKaWYobi5sZW5ndGg9PT0wKWlmKHI9PW51bGwpcD10Lmxlbmd0aD09PTA/YS5nSWko
+YSk6UC54ZShhLmdJaShhKSkKZWxzZSBwPVAueGUoIi8iK2EuZ0lpKGEpKQplbHNle209ay5KaChuLGEu
+Z0lpKGEpKQpsPXQubGVuZ3RoPT09MAppZighbHx8ciE9bnVsbHx8Qy54Qi5uKG4sIi8iKSlwPVAueGUo
+bSkKZWxzZSBwPVAud0YobSwhbHx8ciE9bnVsbCl9fW89YS5nUUQoKT9hLmd0UCgpOmp9fX1yZXR1cm4g
+bmV3IFAuRG4odCxzLHIscSxwLG8sYS5nWjgoKT9hLmdLYSgpOmopfSwKZ2NqOmZ1bmN0aW9uKCl7cmV0
+dXJuIHRoaXMuYyE9bnVsbH0sCmd4QTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmQhPW51bGx9LApnUUQ6
+ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mIT1udWxsfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMu
+ciE9bnVsbH0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLm4odGhpcy5lLCIvIil9LAp0NDpmdW5j
+dGlvbigpe3ZhciB0LHMscj10aGlzLHE9ci5hCmlmKHEhPT0iIiYmcSE9PSJmaWxlIil0aHJvdyBILmIo
+UC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHEpKyIgVVJJIikpCnE9
+ci5mCmlmKChxPT1udWxsPyIiOnEpIT09IiIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEg
+ZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIpKQpxPXIucgppZigocT09
+bnVsbD8iIjpxKSE9PSIiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBm
+cm9tIGEgVVJJIHdpdGggYSBmcmFnbWVudCBjb21wb25lbnQiKSkKdD0kLndRKCkKaWYoSC5vVCh0KSlx
+PVAubW4ocikKZWxzZXtpZihyLmMhPW51bGwmJnIuZ0pmKHIpIT09IiIpSC52aChQLkw0KCJDYW5ub3Qg
+ZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZpbGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBhbiBhdXRo
+b3JpdHkiKSkKcz1yLmdGaigpClAua0UocywhMSkKcT1QLnZnKEMueEIubihyLmUsIi8iKT8iLyI6IiIs
+cywiLyIpCnE9cS5jaGFyQ29kZUF0KDApPT0wP3E6cX1yZXR1cm4gcX0sCnc6ZnVuY3Rpb24oYSl7dmFy
+IHQscyxyLHE9dGhpcyxwPXEueQppZihwPT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09MD9wKyI6Ijoi
+IgpzPXEuYwpyPXM9PW51bGwKaWYoIXJ8fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5iCmlmKHQubGVu
+Z3RoIT09MClwPXArdCsiQCIKaWYoIXIpcCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsiOiIrSC5kKHQp
+fWVsc2UgcD10CnArPXEuZQp0PXEuZgppZih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxs
+KXA9cCsiIyIrdApwPXEueT1wLmNoYXJDb2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwKRE46ZnVuY3Rp
+b24oYSxiKXt2YXIgdCxzLHI9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlmKHI9PT1iKXJldHVybiEw
+CmlmKHUudS5jKGIpKWlmKHIuYT09Yi5nRmkoKSlpZihyLmMhPW51bGw9PT1iLmdjaigpKWlmKHIuYj09
+Yi5na3UoKSlpZihyLmdKZihyKT09Yi5nSmYoYikpaWYoci5ndHAocik9PWIuZ3RwKGIpKWlmKHIuZT09
+PWIuZ0lpKGIpKXt0PXIuZgpzPXQ9PW51bGwKaWYoIXM9PT1iLmdRRCgpKXtpZihzKXQ9IiIKaWYodD09
+PWIuZ3RQKCkpe3Q9ci5yCnM9dD09bnVsbAppZighcz09PWIuZ1o4KCkpe2lmKHMpdD0iIgp0PXQ9PT1i
+LmdLYSgpfWVsc2UgdD0hMX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxz
+ZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQpyZXR1cm4gdH0sCmdp
+TzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLnoKcmV0dXJuIHQ9PW51bGw/dGhpcy56PUMueEIuZ2lPKHRo
+aXMudygwKSk6dH0sCnNvNjpmdW5jdGlvbihhKXt0aGlzLng9dS5pLmIoYSl9LApzUkg6ZnVuY3Rpb24o
+YSl7dGhpcy5RPXUuZi5iKGEpfSwKJGlpRDoxLApnRmk6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfSwK
+Z0lpOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmV9fQpQLmUxLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
+KGEpe3Rocm93IEguYihQLnJyKCJJbnZhbGlkIHBvcnQiLHRoaXMuYSx0aGlzLmIrMSkpfSwKJFM6MTF9
+ClAuTlkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9IklsbGVnYWwgcGF0aCBjaGFyYWN0
+ZXIgIgpILnkoYSkKaWYoSi56bChhLCIvIikpaWYodGhpcy5hKXRocm93IEguYihQLnhZKHQrYSkpCmVs
+c2UgdGhyb3cgSC5iKFAuTDQodCthKSl9LAokUzoxMX0KUC5SWi5wcm90b3R5cGU9ewokMTpmdW5jdGlv
+bihhKXtyZXR1cm4gUC5lUChDLlpKLGEsQy54TSwhMSl9LAokUzo2fQpQLlBFLnByb3RvdHlwZT17Cmds
+UjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcyxvPW51bGwsbj1wLmMKaWYobiE9bnVsbClyZXR1
+cm4gbgpuPXAuYgppZigwPj1uLmxlbmd0aClyZXR1cm4gSC5PSChuLDApCnQ9cC5hCm49blswXSsxCnM9
+Qy54Qi5YVSh0LCI/IixuKQpyPXQubGVuZ3RoCmlmKHM+PTApe3E9UC51Tyh0LHMrMSxyLEMuVkMsITEp
+CnI9c31lbHNlIHE9bwpyZXR1cm4gcC5jPW5ldyBQLnFlKCJkYXRhIixvLG8sbyxQLnVPKHQsbixyLEMu
+V2QsITEpLHEsbyl9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5iCmlmKDA+PXMubGVuZ3RoKXJl
+dHVybiBILk9IKHMsMCkKdD10aGlzLmEKcmV0dXJuIHNbMF09PT0tMT8iZGF0YToiK3Q6dH19ClAucTMu
+cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBVaW50OEFycmF5KDk2KX0sCiRTOjI0
+fQpQLnlJLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hCmlmKGE+PXQubGVu
+Z3RoKXJldHVybiBILk9IKHQsYSkKdD10W2FdCkouQ00odCwwLDk2LGIpCnJldHVybiB0fSwKJFM6NDB9
+ClAuYzYucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmZvcih0PWIubGVu
+Z3RoLHM9YS5sZW5ndGgscj0wO3I8dDsrK3Ipe3E9Qy54Qi5XKGIscileOTYKaWYocT49cylyZXR1cm4g
+SC5PSChhLHEpCmFbcV09Y319fQpQLnFkLnByb3RvdHlwZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzLHIscQpmb3IodD1DLnhCLlcoYiwwKSxzPUMueEIuVyhiLDEpLHI9YS5sZW5ndGg7dDw9czsrK3Qp
+e3E9KHReOTYpPj4+MAppZihxPj1yKXJldHVybiBILk9IKGEscSkKYVtxXT1jfX19ClAuVWYucHJvdG90
+eXBlPXsKZ2NqOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYz4wfSwKZ3hBOmZ1bmN0aW9uKCl7dmFyIHQs
+cwppZih0aGlzLmM+MCl7dD10aGlzLmQKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5oKCkK
+cz10aGlzLmUKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShzKQpzPXQrMTxzCnQ9c31l
+bHNlIHQ9ITEKcmV0dXJuIHR9LApnUUQ6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYKaWYodHlwZW9mIHQh
+PT0ibnVtYmVyIilyZXR1cm4gdC5KKCkKcmV0dXJuIHQ8dGhpcy5yfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0
+dXJuIHRoaXMucjx0aGlzLmEubGVuZ3RofSwKZ053OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQm
+JkMueEIubih0aGlzLmEsImZpbGUiKX0sCmd2aDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZD
+LnhCLm4odGhpcy5hLCJodHRwIil9LApncUI6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NSYmQy54
+Qi5uKHRoaXMuYSwiaHR0cHMiKX0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLlFpKHRoaXMuYSwi
+LyIsdGhpcy5lKX0sCmdGaTpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPSJwYWNrYWdlIixxPXMuYgpp
+ZihxPD0wKXJldHVybiIiCnQ9cy54CmlmKHQhPW51bGwpcmV0dXJuIHQKaWYocy5ndmgoKSlxPXMueD0i
+aHR0cCIKZWxzZSBpZihzLmdxQigpKXtzLng9Imh0dHBzIgpxPSJodHRwcyJ9ZWxzZSBpZihzLmdOdygp
+KXtzLng9ImZpbGUiCnE9ImZpbGUifWVsc2UgaWYocT09PTcmJkMueEIubihzLmEscikpe3MueD1yCnE9
+cn1lbHNle3E9Qy54Qi5OaihzLmEsMCxxKQpzLng9cX1yZXR1cm4gcX0sCmdrdTpmdW5jdGlvbigpe3Zh
+ciB0PXRoaXMuYyxzPXRoaXMuYiszCnJldHVybiB0PnM/Qy54Qi5Oaih0aGlzLmEscyx0LTEpOiIifSwK
+Z0pmOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYwpyZXR1cm4gdD4wP0MueEIuTmoodGhpcy5hLHQsdGhp
+cy5kKToiIn0sCmd0cDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMKaWYocy5neEEoKSl7dD1zLmQKaWYo
+dHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5oKCkKcmV0dXJuIFAuUUEoQy54Qi5OaihzLmEsdCsx
+LHMuZSksbnVsbCxudWxsKX1pZihzLmd2aCgpKXJldHVybiA4MAppZihzLmdxQigpKXJldHVybiA0NDMK
+cmV0dXJuIDB9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIuTmoodGhpcy5hLHRoaXMuZSx0aGlz
+LmYpfSwKZ3RQOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5mLHM9dGhpcy5yCmlmKHR5cGVvZiB0IT09Im51
+bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0PHM/Qy54Qi5Oaih0aGlzLmEsdCsxLHMpOiIifSwKZ0th
+OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yLHM9dGhpcy5hCnJldHVybiB0PHMubGVuZ3RoP0MueEIuRyhz
+LHQrMSk6IiJ9LApnRmo6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcy5lLHE9dGhpcy5mLHA9dGhpcy5h
+CmlmKEMueEIuUWkocCwiLyIscikpe2lmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuaCgpOysr
+cn1pZihyPT1xKXJldHVybiBDLnhECnQ9SC5WTShbXSx1LnMpCnM9cgp3aGlsZSghMCl7aWYodHlwZW9m
+IHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5w
+WShxKQppZighKHM8cSkpYnJlYWsKaWYoQy54Qi5tKHAscyk9PT00Nyl7Qy5ObS5pKHQsQy54Qi5Oaihw
+LHIscykpCnI9cysxfSsrc31DLk5tLmkodCxDLnhCLk5qKHAscixxKSkKcmV0dXJuIFAuT1codCx1Lk4p
+fSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJu
+IHQuSigpCmlmKHQ+PXRoaXMucilyZXR1cm4gQy5XTwpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0aGlzLmd0
+UCgpKSx1LlcpfSwKa1g6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmQKaWYodHlwZW9mIHMhPT0ibnVt
+YmVyIilyZXR1cm4gcy5oKCkKdD1zKzEKcmV0dXJuIHQrYS5sZW5ndGg9PT10aGlzLmUmJkMueEIuUWko
+dGhpcy5hLGEsdCl9LApOOTpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LnIscj10LmEKaWYocz49ci5s
+ZW5ndGgpcmV0dXJuIHQKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmoociwwLHMpLHQuYix0LmMsdC5kLHQu
+ZSx0LmYscyx0LngpfSwKWkk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpm
+dW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2YgUC5VZilyZXR1cm4gdGhpcy51MSh0aGlzLGEpCnJldHVy
+biB0aGlzLlJlKCkubVMoYSl9LAp1MTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxr
+LGosaSxoLGcsZixlPWIuYgppZihlPjApcmV0dXJuIGIKdD1iLmMKaWYodD4wKXtzPWEuYgppZihzPD0w
+KXJldHVybiBiCmlmKGEuZ053KCkpcj1iLmUhPWIuZgplbHNlIGlmKGEuZ3ZoKCkpcj0hYi5rWCgiODAi
+KQplbHNlIHI9IWEuZ3FCKCl8fCFiLmtYKCI0NDMiKQppZihyKXtxPXMrMQpwPUMueEIuTmooYS5hLDAs
+cSkrQy54Qi5HKGIuYSxlKzEpCmU9Yi5kCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIGUuaCgp
+Cm89Yi5lCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8uaCgpCm49Yi5mCmlmKHR5cGVvZiBu
+IT09Im51bWJlciIpcmV0dXJuIG4uaCgpCnJldHVybiBuZXcgUC5VZihwLHMsdCtxLGUrcSxvK3Esbitx
+LGIucitxLGEueCl9ZWxzZSByZXR1cm4gdGhpcy5SZSgpLm1TKGIpfW09Yi5lCmU9Yi5mCmlmKG09PWUp
+e3Q9Yi5yCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIGUuSigpCmlmKGU8dCl7cz1hLmYKaWYo
+dHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCnE9cy1lCnJldHVybiBuZXcgUC5VZihDLnhC
+Lk5qKGEuYSwwLHMpK0MueEIuRyhiLmEsZSksYS5iLGEuYyxhLmQsYS5lLGUrcSx0K3EsYS54KX1lPWIu
+YQppZih0PGUubGVuZ3RoKXtzPWEucgpyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihhLmEsMCxzKStDLnhC
+LkcoZSx0KSxhLmIsYS5jLGEuZCxhLmUsYS5mLHQrKHMtdCksYS54KX1yZXR1cm4gYS5OOSgpfXQ9Yi5h
+CmlmKEMueEIuUWkodCwiLyIsbSkpe3M9YS5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMu
+SE4oKQppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBILnBZKG0pCnE9cy1tCnA9Qy54Qi5Oaihh
+LmEsMCxzKStDLnhCLkcodCxtKQppZih0eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBlLmgoKQpyZXR1
+cm4gbmV3IFAuVWYocCxhLmIsYS5jLGEuZCxzLGUrcSxiLnIrcSxhLngpfWw9YS5lCms9YS5mCmlmKGw9
+PWsmJmEuYz4wKXtmb3IoO0MueEIuUWkodCwiLi4vIixtKTspe2lmKHR5cGVvZiBtIT09Im51bWJlciIp
+cmV0dXJuIG0uaCgpCm0rPTN9aWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5ITigpCmlmKHR5
+cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkKcT1sLW0rMQpwPUMueEIuTmooYS5hLDAsbCkr
+Ii8iK0MueEIuRyh0LG0pCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIGUuaCgpCnJldHVybiBu
+ZXcgUC5VZihwLGEuYixhLmMsYS5kLGwsZStxLGIucitxLGEueCl9aj1hLmEKZm9yKGk9bDtDLnhCLlFp
+KGosIi4uLyIsaSk7KXtpZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBpLmgoKQppKz0zfWg9MAp3
+aGlsZSghMCl7aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5oKCkKZz1tKzMKaWYodHlwZW9m
+IGUhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShlKQppZighKGc8PWUmJkMueEIuUWkodCwiLi4vIixtKSkp
+YnJlYWs7KytoCm09Z31mPSIiCndoaWxlKCEwKXtpZih0eXBlb2YgayE9PSJudW1iZXIiKXJldHVybiBr
+Lm9zKCkKaWYodHlwZW9mIGkhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShpKQppZighKGs+aSkpYnJlYWs7
+LS1rCmlmKEMueEIubShqLGspPT09NDcpe2lmKGg9PT0wKXtmPSIvIgpicmVha30tLWgKZj0iLyJ9fWlm
+KGs9PT1pJiZhLmI8PTAmJiFDLnhCLlFpKGosIi8iLGwpKXttLT1oKjMKZj0iIn1xPWstbStmLmxlbmd0
+aApyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihqLDAsaykrZitDLnhCLkcodCxtKSxhLmIsYS5jLGEuZCxs
+LGUrcSxiLnIrcSxhLngpfSwKdDQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC5iPj0w
+JiYhcC5nTncoKSl0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBh
+ICIrSC5kKHAuZ0ZpKCkpKyIgVVJJIikpCnQ9cC5mCnM9cC5hCmlmKHR5cGVvZiB0IT09Im51bWJlciIp
+cmV0dXJuIHQuSigpCmlmKHQ8cy5sZW5ndGgpe2lmKHQ8cC5yKXRocm93IEguYihQLkw0KCJDYW5ub3Qg
+ZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiKSkKdGhy
+b3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIGZy
+YWdtZW50IGNvbXBvbmVudCIpKX1yPSQud1EoKQppZihILm9UKHIpKXQ9UC5tbihwKQplbHNle3E9cC5k
+CmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKaWYocC5jPHEpSC52aChQLkw0KCJD
+YW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5kb3dzIGZpbGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBh
+biBhdXRob3JpdHkiKSkKdD1DLnhCLk5qKHMscC5lLHQpfXJldHVybiB0fSwKZ2lPOmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMueQpyZXR1cm4gdD09bnVsbD90aGlzLnk9Qy54Qi5naU8odGhpcy5hKTp0fSwKRE46
+ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCmlmKHRoaXM9PT1iKXJldHVybiEwCnJldHVy
+biB1LnUuYyhiKSYmdGhpcy5hPT09Yi53KDApfSwKUmU6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9bnVs
+bCxyPXQuZ0ZpKCkscT10LmdrdSgpLHA9dC5jPjA/dC5nSmYodCk6cyxvPXQuZ3hBKCk/dC5ndHAodCk6
+cyxuPXQuYSxtPXQuZixsPUMueEIuTmoobix0LmUsbSksaz10LnIKaWYodHlwZW9mIG0hPT0ibnVtYmVy
+IilyZXR1cm4gbS5KKCkKbT1tPGs/dC5ndFAoKTpzCnJldHVybiBuZXcgUC5EbihyLHEscCxvLGwsbSxr
+PG4ubGVuZ3RoP3QuZ0thKCk6cyl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAokaWlEOjF9
+ClAucWUucHJvdG90eXBlPXt9ClcucUUucHJvdG90eXBlPXt9ClcuR2gucHJvdG90eXBlPXsKdzpmdW5j
+dGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGlHaDoxfQpXLmZZLnByb3RvdHlwZT17Cnc6ZnVuY3Rp
+b24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcubkIucHJvdG90eXBlPXskaW5COjF9ClcuQXoucHJvdG90
+eXBlPXskaUF6OjF9ClcuUVAucHJvdG90eXBlPXskaVFQOjF9ClcubngucHJvdG90eXBlPXsKZ0E6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5vSi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXty
+ZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17fQpXLlFGLnByb3RvdHlwZT17fQpXLk5oLnBy
+b3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcuSUIucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgiK0guZChhLmxlZnQpKyIsICIrSC5kKGEudG9w
+KSsiKSAiK0guZChhLndpZHRoKSsiIHggIitILmQoYS5oZWlnaHQpfSwKRE46ZnVuY3Rpb24oYSxiKXtp
+ZihiPT1udWxsKXJldHVybiExCnJldHVybiB1LnEuYyhiKSYmYS5sZWZ0PT09Yi5sZWZ0JiZhLnRvcD09
+PWIudG9wJiZhLndpZHRoPT09Yi53aWR0aCYmYS5oZWlnaHQ9PT1iLmhlaWdodH0sCmdpTzpmdW5jdGlv
+bihhKXtyZXR1cm4gVy5yRShDLkNELmdpTyhhLmxlZnQpLEMuQ0QuZ2lPKGEudG9wKSxDLkNELmdpTyhh
+LndpZHRoKSxDLkNELmdpTyhhLmhlaWdodCkpfSwKJGl0bjoxfQpXLm43LnByb3RvdHlwZT17CmdBOmZ1
+bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcud3oucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC5TYyhiKQp0PXRoaXMu
+YQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0dXJuIHRoaXMuJHRpLmQuYih0
+W2JdKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuJHRpLmQuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fu
+bm90IG1vZGlmeSBsaXN0IikpfX0KVy5jdi5wcm90b3R5cGU9ewpnUWc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IG5ldyBXLmk3KGEpfSwKZ0Q6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLkk0KGEpfSwKdzpmdW5jdGlv
+bihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LAp0bjpmdW5jdGlvbihhKXt2YXIgdD0hIWEuc2Nyb2xsSW50
+b1ZpZXdJZk5lZWRlZAppZih0KWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpCmVsc2UgYS5zY3JvbGxJ
+bnRvVmlldygpfSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoYz09bnVsbCl7aWYo
+ZD09bnVsbCl7dD0kLmx0CmlmKHQ9PW51bGwpe3Q9SC5WTShbXSx1LlEpCnM9bmV3IFcudkQodCkKQy5O
+bS5pKHQsVy5UdyhudWxsKSkKQy5ObS5pKHQsVy5CbCgpKQokLmx0PXMKZD1zfWVsc2UgZD10fXQ9JC5F
+VQppZih0PT1udWxsKXt0PW5ldyBXLktvKGQpCiQuRVU9dApjPXR9ZWxzZXt0LmE9ZApjPXR9fWVsc2Ug
+aWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9yIGNhbiBvbmx5IGJlIHBhc3NlZCBpZiB0
+cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVsbCl7dD1kb2N1bWVudApzPXQuaW1wbGVt
+ZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCIiKQokLnhvPXMKJC5CTz1zLmNyZWF0ZVJhbmdlKCkK
+cz0kLnhvLmNyZWF0ZUVsZW1lbnQoImJhc2UiKQp1LkQuYihzKQpzLmhyZWY9dC5iYXNlVVJJCiQueG8u
+aGVhZC5hcHBlbmRDaGlsZChzKX10PSQueG8KaWYodC5ib2R5PT1udWxsKXtzPXQuY3JlYXRlRWxlbWVu
+dCgiYm9keSIpCnQuYm9keT11LlguYihzKX10PSQueG8KaWYodS5YLmMoYSkpcj10LmJvZHkKZWxzZXty
+PXQuY3JlYXRlRWxlbWVudChhLnRhZ05hbWUpCiQueG8uYm9keS5hcHBlbmRDaGlsZChyKX1pZigiY3Jl
+YXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlJiYhQy5ObS50ZyhD
+LlNxLGEudGFnTmFtZSkpeyQuQk8uc2VsZWN0Tm9kZUNvbnRlbnRzKHIpCnE9JC5CTy5jcmVhdGVDb250
+ZXh0dWFsRnJhZ21lbnQoYil9ZWxzZXtyLmlubmVySFRNTD1iCnE9JC54by5jcmVhdGVEb2N1bWVudEZy
+YWdtZW50KCkKZm9yKDt0PXIuZmlyc3RDaGlsZCx0IT1udWxsOylxLmFwcGVuZENoaWxkKHQpfXQ9JC54
+by5ib2R5CmlmKHI9PW51bGw/dCE9bnVsbDpyIT09dClKLkx0KHIpCmMuUG4ocSkKZG9jdW1lbnQuYWRv
+cHROb2RlKHEpCnJldHVybiBxfSwKQUg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLnI2KGEsYixj
+LG51bGwpfSwKc2hmOmZ1bmN0aW9uKGEsYil7dGhpcy5ZQyhhLGIpfSwKcGs6ZnVuY3Rpb24oYSxiLGMp
+e2EudGV4dENvbnRlbnQ9bnVsbAphLmFwcGVuZENoaWxkKHRoaXMucjYoYSxiLG51bGwsYykpfSwKWUM6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LApnVmw6ZnVuY3Rpb24oYSl7cmV0
+dXJuIG5ldyBXLkNxKGEsImNsaWNrIiwhMSx1LkMpfSwKJGljdjoxLApnbnM6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEudGFnTmFtZX19ClcuQ3YucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuaC5j
+KHUuQS5iKGEpKX0sCiRTOjI2fQpXLmVhLnByb3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17
+Ck9uOmZ1bmN0aW9uKGEsYixjLGQpe3UuVS5iKGMpCmlmKGMhPW51bGwpdGhpcy52KGEsYixjLGQpfSwK
+QjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMuT24oYSxiLGMsbnVsbCl9LAp2OmZ1bmN0aW9uKGEs
+YixjLGQpe3JldHVybiBhLmFkZEV2ZW50TGlzdGVuZXIoYixILnRSKHUuVS5iKGMpLDEpLGQpfSwKJGlE
+MDoxfQpXLlQ1LnByb3RvdHlwZT17JGlUNToxfQpXLmg0LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
+e3JldHVybiBhLmxlbmd0aH19ClcuYnIucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+bGVuZ3RofX0KVy5WYi5wcm90b3R5cGU9e30KVy5PNy5wcm90b3R5cGU9ewplbzpmdW5jdGlvbihhLGIs
+YyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaU83OjF9ClcuYlUucHJvdG90eXBlPXsKJDI6ZnVu
+Y3Rpb24oYSxiKXt0aGlzLmEuc2V0UmVxdWVzdEhlYWRlcihILnkoYSksSC55KGIpKX0sCiRTOjl9Clcu
+aEgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscAp1LnAuYihhKQp0PXRoaXMu
+YQpzPXQuc3RhdHVzCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMudEIoKQpyPXM+PTIwMCYm
+czwzMDAKcT1zPjMwNyYmczw0MDAKcz1yfHxzPT09MHx8cz09PTMwNHx8cQpwPXRoaXMuYgppZihzKXtw
+LiR0aS5DKCIxLyIpLmIodCkKcz1wLmEKaWYocy5hIT09MClILnZoKFAuUFYoIkZ1dHVyZSBhbHJlYWR5
+IGNvbXBsZXRlZCIpKQpzLlhmKHQpfWVsc2UgcC5wbShhKX0sCiRTOjI3fQpXLndhLnByb3RvdHlwZT17
+fQpXLlNnLnByb3RvdHlwZT17JGlTZzoxfQpXLnU4LnByb3RvdHlwZT17CmdEcjpmdW5jdGlvbihhKXtp
+Zigib3JpZ2luIiBpbiBhKXJldHVybiBhLm9yaWdpbgpyZXR1cm4gSC5kKGEucHJvdG9jb2wpKyIvLyIr
+SC5kKGEuaG9zdCl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaXU4OjF9ClcuQWou
+cHJvdG90eXBlPXskaUFqOjF9ClcuZTcucHJvdG90eXBlPXsKZ3I4OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMuYSxzPXQuY2hpbGROb2Rlcy5sZW5ndGgKaWYocz09PTApdGhyb3cgSC5iKFAuUFYoIk5vIGVsZW1l
+bnRzIikpCmlmKHM+MSl0aHJvdyBILmIoUC5QVigiTW9yZSB0aGFuIG9uZSBlbGVtZW50IikpCnJldHVy
+biB0LmZpcnN0Q2hpbGR9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUuZWguYihiKQp0PWIu
+YQpzPXRoaXMuYQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3RoLHE9MDtxPHI7KytxKXMu
+YXBwZW5kQ2hpbGQodC5maXJzdENoaWxkKQpyZXR1cm59LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+CnUuQS5iKGMpCnQ9dGhpcy5hCnM9dC5jaGlsZE5vZGVzCmlmKGI8MHx8Yj49cy5sZW5ndGgpcmV0dXJu
+IEguT0gocyxiKQp0LnJlcGxhY2VDaGlsZChjLHNbYl0pfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMuYS5jaGlsZE5vZGVzCnJldHVybiBuZXcgVy5XOSh0LHQubGVuZ3RoLEgueksodCkuQygiVzk8R20u
+RT4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNoaWxkTm9kZXMubGVuZ3RofSwKcTpm
+dW5jdGlvbihhLGIpe3ZhciB0CkguU2MoYikKdD10aGlzLmEuY2hpbGROb2RlcwppZihiPDB8fGI+PXQu
+bGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0dXJuIHRbYl19fQpXLnVILnByb3RvdHlwZT17CndnOmZ1
+bmN0aW9uKGEpe3ZhciB0PWEucGFyZW50Tm9kZQppZih0IT1udWxsKXQucmVtb3ZlQ2hpbGQoYSl9LApE
+NDpmdW5jdGlvbihhKXt2YXIgdApmb3IoO3Q9YS5maXJzdENoaWxkLHQhPW51bGw7KWEucmVtb3ZlQ2hp
+bGQodCl9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PWEubm9kZVZhbHVlCnJldHVybiB0PT1udWxsP3RoaXMu
+VShhKTp0fSwKJGl1SDoxfQpXLkJILnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
+bmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhy
+b3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEs
+YixjKXt1LkEuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0
+YWJsZSBMaXN0LiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBI
+Lk9IKGEsYikKcmV0dXJuIGFbYl19LAokaVhqOjEsCiRpY1g6MSwKJGl6TToxfQpXLmV3LnByb3RvdHlw
+ZT17JGlldzoxfQpXLmxwLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19
+ClcuVGIucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZigiY3JlYXRlQ29u
+dGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEs
+YixjLGQpCnQ9Vy5VOSgiPHRhYmxlPiIrSC5kKGIpKyI8L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50LmNy
+ZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzLnRvU3RyaW5nCnQudG9TdHJpbmcKbmV3IFcuZTcocykuRlYo
+MCxuZXcgVy5lNyh0KSkKcmV0dXJuIHN9fQpXLkl2LnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixj
+LGQpe3ZhciB0LHMscixxCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5n
+ZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9j
+dW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQu
+dG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQpCnIudG9TdHJpbmcKdD1uZXcgVy5lNyhyKQpx
+PXQuZ3I4KHQpCnMudG9TdHJpbmcKcS50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHEp
+KQpyZXR1cm4gc319ClcuQlQucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxy
+CmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0
+dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgp
+CnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcg
+Vy5lNyh0KQpyPXQuZ3I4KHQpCnMudG9TdHJpbmcKci50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5l
+dyBXLmU3KHIpKQpyZXR1cm4gc319ClcueVkucHJvdG90eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHMKYS50ZXh0Q29udGVudD1udWxsCnQ9YS5jb250ZW50CnQudG9TdHJpbmcKSi5iVCh0KQpzPXRo
+aXMucjYoYSxiLG51bGwsYykKYS5jb250ZW50LmFwcGVuZENoaWxkKHMpfSwKWUM6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LAokaXlZOjF9ClcudzYucHJvdG90eXBlPXt9ClcuSzUu
+cHJvdG90eXBlPXskaUs1OjEsJGl2NjoxfQpXLkNtLnByb3RvdHlwZT17JGlDbToxfQpXLkNRLnByb3Rv
+dHlwZT17JGlDUToxfQpXLnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlY3Rhbmds
+ZSAoIitILmQoYS5sZWZ0KSsiLCAiK0guZChhLnRvcCkrIikgIitILmQoYS53aWR0aCkrIiB4ICIrSC5k
+KGEuaGVpZ2h0KX0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gdS5x
+LmMoYikmJmEubGVmdD09PWIubGVmdCYmYS50b3A9PT1iLnRvcCYmYS53aWR0aD09PWIud2lkdGgmJmEu
+aGVpZ2h0PT09Yi5oZWlnaHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoQy5DRC5naU8oYS5s
+ZWZ0KSxDLkNELmdpTyhhLnRvcCksQy5DRC5naU8oYS53aWR0aCksQy5DRC5naU8oYS5oZWlnaHQpKX19
+ClcucmgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlv
+bihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEs
+bnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe3UuQS5iKGMpCnRo
+cm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwK
+RTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4g
+YVtiXX0sCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuRDkucHJvdG90eXBlPXsKSzpmdW5jdGlvbihh
+LGIpe3ZhciB0LHMscixxLHAKdS52LmIoYikKZm9yKHQ9dGhpcy5nVigpLHM9dC5sZW5ndGgscj10aGlz
+LmEscT0wO3E8dC5sZW5ndGg7dC5sZW5ndGg9PT1zfHwoMCxILmxrKSh0KSwrK3Epe3A9dFtxXQpiLiQy
+KHAsci5nZXRBdHRyaWJ1dGUocCkpfX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzLmEu
+YXR0cmlidXRlcyxvPUguVk0oW10sdS5zKQpmb3IodD1wLmxlbmd0aCxzPXUuaDkscj0wO3I8dDsrK3Ip
+e2lmKHI+PXAubGVuZ3RoKXJldHVybiBILk9IKHAscikKcT1zLmIocFtyXSkKaWYocS5uYW1lc3BhY2VV
+Ukk9PW51bGwpQy5ObS5pKG8scS5uYW1lKX1yZXR1cm4gb319ClcuaTcucHJvdG90eXBlPXsKcTpmdW5j
+dGlvbihhLGIpe3JldHVybiB0aGlzLmEuZ2V0QXR0cmlidXRlKEgueShiKSl9LApZOmZ1bmN0aW9uKGEs
+YixjKXt0aGlzLmEuc2V0QXR0cmlidXRlKGIsYyl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5n
+VigpLmxlbmd0aH19ClcuU3kucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEu
+YS5nZXRBdHRyaWJ1dGUoImRhdGEtIit0aGlzLk8oSC55KGIpKSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0
+aGlzLmEuYS5zZXRBdHRyaWJ1dGUoImRhdGEtIit0aGlzLk8oYiksYyl9LApLOmZ1bmN0aW9uKGEsYil7
+dGhpcy5hLksoMCxuZXcgVy5LUyh0aGlzLHUudi5iKGIpKSl9LApnVjpmdW5jdGlvbigpe3ZhciB0PUgu
+Vk0oW10sdS5zKQp0aGlzLmEuSygwLG5ldyBXLkEzKHRoaXMsdCkpCnJldHVybiB0fSwKZ0E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuZ1YoKS5sZW5ndGh9LAprOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1ILlZN
+KGEuc3BsaXQoIi0iKSx1LnMpCmZvcih0PTE7dDxyLmxlbmd0aDsrK3Qpe3M9clt0XQppZihzLmxlbmd0
+aD4wKUMuTm0uWShyLHQsc1swXS50b1VwcGVyQ2FzZSgpK0ouS1YocywxKSl9cmV0dXJuIEMuTm0uSChy
+LCIiKX0sCk86ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscApmb3IodD1hLmxlbmd0aCxzPTAscj0iIjtz
+PHQ7KytzKXtxPWFbc10KcD1xLnRvTG93ZXJDYXNlKCkKcj0ocSE9PXAmJnM+MD9yKyItIjpyKStwfXJl
+dHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfX0KVy5LUy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
+LGIpe2lmKEouclkoYSkubihhLCJkYXRhLSIpKXRoaXMuYi4kMih0aGlzLmEuayhDLnhCLkcoYSw1KSks
+Yil9LAokUzo5fQpXLkEzLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7aWYoSi5yWShhKS5uKGEs
+ImRhdGEtIikpQy5ObS5pKHRoaXMuYix0aGlzLmEuayhDLnhCLkcoYSw1KSkpfSwKJFM6OX0KVy5JNC5w
+cm90b3R5cGU9ewpQOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD1QLkxzKHUuTikKZm9yKHQ9dGhpcy5h
+LmNsYXNzTmFtZS5zcGxpdCgiICIpLHM9dC5sZW5ndGgscj0wO3I8czsrK3Ipe3E9Si5UMCh0W3JdKQpp
+ZihxLmxlbmd0aCE9PTApcC5pKDAscSl9cmV0dXJuIHB9LApYOmZ1bmN0aW9uKGEpe3RoaXMuYS5jbGFz
+c05hbWU9dS5ULmIoYSkuSCgwLCIgIil9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNsYXNz
+TGlzdC5sZW5ndGh9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xpc3QuY29udGFp
+bnMoYikKcmV0dXJuIHR9LAppOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQu
+Y29udGFpbnMoYikKdC5hZGQoYikKcmV0dXJuIXN9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5h
+LmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5yZW1vdmUoYikKcmV0dXJuIHN9fQpXLkZrLnByb3Rv
+dHlwZT17fQpXLlJPLnByb3RvdHlwZT17fQpXLkNxLnByb3RvdHlwZT17fQpXLnhDLnByb3RvdHlwZT17
+fQpXLnZOLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodS5CLmIoYSkp
+fSwKJFM6Mjh9ClcuSlEucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoJC5vci5hPT09
+MCl7Zm9yKHQ9MDt0PDI2MjsrK3QpJC5vci5ZKDAsQy5jbVt0XSxXLnBTKCkpCmZvcih0PTA7dDwxMjsr
+K3QpJC5vci5ZKDAsQy5CSVt0XSxXLlY0KCkpfX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiAkLkFOKCku
+dGcoMCxXLnJTKGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0kLm9yLnEoMCxILmQoVy5yUyhh
+KSkrIjo6IitiKQppZih0PT1udWxsKXQ9JC5vci5xKDAsIio6OiIrYikKaWYodD09bnVsbClyZXR1cm4h
+MQpyZXR1cm4gSC54ZCh0LiQ0KGEsYixjLHRoaXMpKX0sCiRpa0Y6MX0KVy5HbS5wcm90b3R5cGU9ewpn
+a3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLlc5KGEsdGhpcy5nQShhKSxILnpLKGEpLkMoIlc5PEdt
+LkU+IikpfX0KVy52RC5wcm90b3R5cGU9ewppMDpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS5Wcih0aGlz
+LmEsbmV3IFcuVXYoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBDLk5tLlZyKHRoaXMuYSxu
+ZXcgVy5FZyhhLGIsYykpfSwKJGlrRjoxfQpXLlV2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB1LmUuYihhKS5pMCh0aGlzLmEpfSwKJFM6MTN9ClcuRWcucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHUuZS5iKGEpLkViKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjEzfQpXLm02
+LnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgp0aGlzLmEuRlYoMCxjKQp0
+PWIuZXYoMCxuZXcgVy5FbygpKQpzPWIuZXYoMCxuZXcgVy5XaygpKQp0aGlzLmIuRlYoMCx0KQpyPXRo
+aXMuYwpyLkZWKDAsQy54RCkKci5GVigwLHMpfSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS50
+ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PXRoaXMscz1XLnJTKGEpLHI9dC5j
+CmlmKHIudGcoMCxILmQocykrIjo6IitiKSlyZXR1cm4gdC5kLkR0KGMpCmVsc2UgaWYoci50ZygwLCIq
+OjoiK2IpKXJldHVybiB0LmQuRHQoYykKZWxzZXtyPXQuYgppZihyLnRnKDAsSC5kKHMpKyI6OiIrYikp
+cmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OiIrYikpcmV0dXJuITAKZWxzZSBpZihyLnRnKDAsSC5k
+KHMpKyI6OioiKSlyZXR1cm4hMAplbHNlIGlmKHIudGcoMCwiKjo6KiIpKXJldHVybiEwfXJldHVybiEx
+fSwKJGlrRjoxfQpXLkVvLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiFDLk5tLnRnKEMu
+QkksSC55KGEpKX0sCiRTOjd9ClcuV2sucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEMu
+Tm0udGcoQy5CSSxILnkoYSkpfSwKJFM6N30KVy5jdC5wcm90b3R5cGU9ewpFYjpmdW5jdGlvbihhLGIs
+Yyl7aWYodGhpcy5qRihhLGIsYykpcmV0dXJuITAKaWYoYj09PSJ0ZW1wbGF0ZSImJmM9PT0iIilyZXR1
+cm4hMAppZihhLmdldEF0dHJpYnV0ZSgidGVtcGxhdGUiKT09PSIiKXJldHVybiB0aGlzLmUudGcoMCxi
+KQpyZXR1cm4hMX19ClcuSUEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIlRFTVBMQVRF
+OjoiK0guZChILnkoYSkpfSwKJFM6Nn0KVy5Pdy5wcm90b3R5cGU9ewppMDpmdW5jdGlvbihhKXt2YXIg
+dAppZih1LmV3LmMoYSkpcmV0dXJuITEKdD11Lmc3LmMoYSkKaWYodCYmVy5yUyhhKT09PSJmb3JlaWdu
+T2JqZWN0IilyZXR1cm4hMQppZih0KXJldHVybiEwCnJldHVybiExfSwKRWI6ZnVuY3Rpb24oYSxiLGMp
+e2lmKGI9PT0iaXMifHxDLnhCLm4oYiwib24iKSlyZXR1cm4hMQpyZXR1cm4gdGhpcy5pMChhKX0sCiRp
+a0Y6MX0KVy5XOS5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYysxLHI9dC5i
+CmlmKHM8cil7dC5zcChKLncyKHQuYSxzKSkKdC5jPXMKcmV0dXJuITB9dC5zcChudWxsKQp0LmM9cgpy
+ZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCnNwOmZ1bmN0aW9uKGEpe3RoaXMu
+ZD10aGlzLiR0aS5kLmIoYSl9LAokaUFuOjF9ClcuZFcucHJvdG90eXBlPXskaUQwOjEsJGl2NjoxfQpX
+LmtGLnByb3RvdHlwZT17fQpXLm1rLnByb3RvdHlwZT17JGl5MDoxfQpXLktvLnByb3RvdHlwZT17ClBu
+OmZ1bmN0aW9uKGEpe25ldyBXLmZtKHRoaXMpLiQyKGEsbnVsbCl9LApFUDpmdW5jdGlvbihhLGIpe2lm
+KGI9PW51bGwpSi5MdChhKQplbHNlIGIucmVtb3ZlQ2hpbGQoYSl9LApJNDpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscixxLHAsbz0hMCxuPW51bGwsbT1udWxsCnRyeXtuPUouaWcoYSkKbT1uLmEuZ2V0QXR0cmli
+dXRlKCJpcyIpCnUuaC5iKGEpCnQ9ZnVuY3Rpb24oYyl7aWYoIShjLmF0dHJpYnV0ZXMgaW5zdGFuY2Vv
+ZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVlCnZhciBsPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGls
+ZCYmYy5sYXN0Q2hpbGQhPT1sW2wubGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYo
+IShjLmNoaWxkcmVuIGluc3RhbmNlb2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2Vv
+ZiBOb2RlTGlzdCkpcmV0dXJuIHRydWUKdmFyIGs9MAppZihjLmNoaWxkcmVuKWs9Yy5jaGlsZHJlbi5s
+ZW5ndGgKZm9yKHZhciBqPTA7ajxrO2orKyl7dmFyIGk9Yy5jaGlsZHJlbltqXQppZihpLmlkPT0nYXR0
+cmlidXRlcyd8fGkubmFtZT09J2F0dHJpYnV0ZXMnfHxpLmlkPT0nbGFzdENoaWxkJ3x8aS5uYW1lPT0n
+bGFzdENoaWxkJ3x8aS5pZD09J2NoaWxkcmVuJ3x8aS5uYW1lPT0nY2hpbGRyZW4nKXJldHVybiB0cnVl
+fXJldHVybiBmYWxzZX0oYSkKbz1ILm9UKHQpPyEwOiEoYS5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFt
+ZWROb2RlTWFwKX1jYXRjaChxKXtILlJ1KHEpfXM9ImVsZW1lbnQgdW5wcmludGFibGUiCnRyeXtzPUou
+aihhKX1jYXRjaChxKXtILlJ1KHEpfXRyeXtyPVcuclMoYSkKdGhpcy5rUih1LmguYihhKSxiLG8scyxy
+LHUuRy5iKG4pLEgueShtKSl9Y2F0Y2gocSl7aWYoSC5SdShxKSBpbnN0YW5jZW9mIFAudSl0aHJvdyBx
+CmVsc2V7dGhpcy5FUChhLGIpCndpbmRvdwpwPSJSZW1vdmluZyBjb3JydXB0ZWQgZWxlbWVudCAiK0gu
+ZChzKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKX19
+fSwKa1I6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG49dGhpcwppZihjKXtu
+LkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1
+dGVzIG9uIDwiK2QrIj4iCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29s
+ZS53YXJuKHQpCnJldHVybn1pZighbi5hLmkwKGEpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5n
+IGRpc2FsbG93ZWQgZWxlbWVudCA8IitILmQoZSkrIj4gZnJvbSAiK0guZChiKQppZih0eXBlb2YgY29u
+c29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59aWYoZyE9bnVsbClp
+Zighbi5hLkViKGEsImlzIixnKSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2Vk
+IHR5cGUgZXh0ZW5zaW9uIDwiK0guZChlKSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9
+InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59dD1mLmdWKCkKcz1ILlZNKHQu
+c2xpY2UoMCksSC50Nih0KS5DKCJqZDwxPiIpKQpmb3Iocj1mLmdWKCkubGVuZ3RoLTEsdD1mLmE7cj49
+MDstLXIpe2lmKHI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscikKcT1zW3JdCnA9bi5hCm89Si5jSChx
+KQpILnkocSkKaWYoIXAuRWIoYSxvLHQuZ2V0QXR0cmlidXRlKHEpKSl7d2luZG93CnA9IlJlbW92aW5n
+IGRpc2FsbG93ZWQgYXR0cmlidXRlIDwiK0guZChlKSsiICIrcSsnPSInK0guZCh0LmdldEF0dHJpYnV0
+ZShxKSkrJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fy
+bihwKQp0LnJlbW92ZUF0dHJpYnV0ZShxKX19aWYodS5hVy5jKGEpKW4uUG4oYS5jb250ZW50KX0sCiRp
+b246MX0KVy5mbS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhpcy5h
+CnN3aXRjaChhLm5vZGVUeXBlKXtjYXNlIDE6cC5JNChhLGIpCmJyZWFrCmNhc2UgODpjYXNlIDExOmNh
+c2UgMzpjYXNlIDQ6YnJlYWsKZGVmYXVsdDpwLkVQKGEsYil9dD1hLmxhc3RDaGlsZApmb3IocD11LkE7
+bnVsbCE9dDspe3M9bnVsbAp0cnl7cz10LnByZXZpb3VzU2libGluZ31jYXRjaChyKXtILlJ1KHIpCnE9
+cC5iKHQpCmEucmVtb3ZlQ2hpbGQocSkKdD1udWxsCnM9YS5sYXN0Q2hpbGR9aWYodCE9bnVsbCl0aGlz
+LiQyKHQsYSkKdD1wLmIocyl9fSwKJFM6Mzl9ClcuTGUucHJvdG90eXBlPXt9ClcuSzcucHJvdG90eXBl
+PXt9ClcuckIucHJvdG90eXBlPXt9ClcuWFcucHJvdG90eXBlPXt9Clcub2EucHJvdG90eXBlPXt9ClAu
+aUoucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmEscj1zLmxlbmd0aApmb3Io
+dD0wO3Q8cjsrK3QpaWYoc1t0XT09PWEpcmV0dXJuIHQKQy5ObS5pKHMsYSkKQy5ObS5pKHRoaXMuYixu
+dWxsKQpyZXR1cm4gcn0sClB2OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPXRoaXMscD17fQppZihhPT1u
+dWxsKXJldHVybiBhCmlmKEgubChhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJu
+IGEKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVy
+biBuZXcgRGF0ZShhLmEpCmlmKHUuZnYuYyhhKSl0aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9u
+ZSBvZiBSZWdFeHAiKSkKaWYodS5jOC5jKGEpKXJldHVybiBhCmlmKHUuZC5jKGEpKXJldHVybiBhCmlm
+KHUuSS5jKGEpKXJldHVybiBhCnQ9dS5kRC5jKGEpfHwhMQppZih0KXJldHVybiBhCmlmKHUuRy5jKGEp
+KXtzPXEuVkgoYSkKdD1xLmIKaWYocz49dC5sZW5ndGgpcmV0dXJuIEguT0godCxzKQpyPXAuYT10W3Nd
+CmlmKHIhPW51bGwpcmV0dXJuIHIKcj17fQpwLmE9cgpDLk5tLlkodCxzLHIpCmEuSygwLG5ldyBQLmxS
+KHAscSkpCnJldHVybiBwLmF9aWYodS5qLmMoYSkpe3M9cS5WSChhKQpwPXEuYgppZihzPj1wLmxlbmd0
+aClyZXR1cm4gSC5PSChwLHMpCnI9cFtzXQppZihyIT1udWxsKXJldHVybiByCnJldHVybiBxLmVrKGEs
+cyl9aWYodS5lSC5jKGEpKXtzPXEuVkgoYSkKdD1xLmIKaWYocz49dC5sZW5ndGgpcmV0dXJuIEguT0go
+dCxzKQpyPXAuYj10W3NdCmlmKHIhPW51bGwpcmV0dXJuIHIKcj17fQpwLmI9cgpDLk5tLlkodCxzLHIp
+CnEuaW0oYSxuZXcgUC5qZyhwLHEpKQpyZXR1cm4gcC5ifXRocm93IEguYihQLlNZKCJzdHJ1Y3R1cmVk
+IGNsb25lIG9mIG90aGVyIHR5cGUiKSl9LAplazpmdW5jdGlvbihhLGIpe3ZhciB0LHM9Si5VNihhKSxy
+PXMuZ0EoYSkscT1uZXcgQXJyYXkocikKQy5ObS5ZKHRoaXMuYixiLHEpCmZvcih0PTA7dDxyOysrdClD
+Lk5tLlkocSx0LHRoaXMuUHYocy5xKGEsdCkpKQpyZXR1cm4gcX19ClAubFIucHJvdG90eXBlPXsKJDI6
+ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYVthXT10aGlzLmIuUHYoYil9LAokUzoxfQpQLmpnLnByb3RvdHlw
+ZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmJbYV09dGhpcy5iLlB2KGIpfSwKJFM6MX0KUC5CZi5w
+cm90b3R5cGU9ewppbTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUuYjguYihiKQpmb3IodD1PYmpl
+Y3Qua2V5cyhhKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPXRbcl0KYi4kMihxLGFbcV0pfX19ClAu
+QXMucHJvdG90eXBlPXsKVDpmdW5jdGlvbihhKXt2YXIgdD0kLmhHKCkuYgppZih0LnRlc3QoYSkpcmV0
+dXJuIGEKdGhyb3cgSC5iKFAuTDMoYSwidmFsdWUiLCJOb3QgYSB2YWxpZCBjbGFzcyB0b2tlbiIpKX0s
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuUCgpLkgoMCwiICIpfSwKZ2t6OmZ1bmN0aW9uKGEpe3Zh
+ciB0PXRoaXMuUCgpCnJldHVybiBQLnJqKHQsdC5yLEguTGgodCkuZCl9LApnQTpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5QKCkuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dGhpcy5UKGIpCnJldHVybiB0aGlzLlAo
+KS50ZygwLGIpfSwKaTpmdW5jdGlvbihhLGIpe3RoaXMuVChiKQpyZXR1cm4gSC54ZCh0aGlzLk9TKG5l
+dyBQLkdFKGIpKSl9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp0aGlzLlQoYikKdD10aGlzLlAoKQpz
+PXQuUigwLGIpCnRoaXMuWCh0KQpyZXR1cm4gc30sCk9TOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdS5jaC5i
+KGEpCnQ9dGhpcy5QKCkKcz1hLiQxKHQpCnRoaXMuWCh0KQpyZXR1cm4gc319ClAuR0UucHJvdG90eXBl
+PXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuVC5iKGEpLmkoMCx0aGlzLmEpfSwKJFM6MzB9ClAuaEYu
+cHJvdG90eXBlPXskaWhGOjF9ClAuUEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5a
+LmIoYSkKdD1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGIoYyxkLHRoaXMs
+QXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykpfX0oUC5SNCxhLCExKQpQLkRtKHQs
+JC53KCksYSkKcmV0dXJuIHR9LAokUzo0fQpQLlltLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAucjcoYSl9LAokUzozMX0KUC5RUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjMyfQpQLm5wLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjMzfQpQLkU0LnByb3RvdHlwZT17CnE6ZnVuY3Rpb24o
+YSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVtYmVyIil0aHJvdyBILmIoUC54
+WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpyZXR1cm4gUC5MNyh0aGlzLmFbYl0p
+fSwKWTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJpbmciJiZ0eXBlb2YgYiE9Im51bWJl
+ciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0cmluZyBvciBudW0iKSkKdGhpcy5h
+W2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIg
+aW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9
+U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKQp0PXRoaXMueGIoMCkKcmV0dXJu
+IHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZihiPT1udWxsKXQ9bnVsbAplbHNl
+e3Q9SC50NihiKQp0PVAuQ0gobmV3IEguQTgoYix0LkMoIkAoMSkiKS5iKFAuaUcoKSksdC5DKCJBODwx
+LEA+IikpLCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShzLHQpKX0sCmdpTzpmdW5jdGlvbihh
+KXtyZXR1cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBlPXsKY1A6ZnVuY3Rpb24o
+YSl7dmFyIHQ9dGhpcyxzPWE8MHx8YT49dC5nQSh0KQppZihzKXRocm93IEguYihQLlRFKGEsMCx0LmdB
+KHQpLG51bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT0ibnVtYmVyIiYmYj09
+PUMuam4ueXUoYikpdGhpcy5jUChILlNjKGIpKQpyZXR1cm4gdGhpcy4kdGkuZC5iKHRoaXMuVXIoMCxi
+KSl9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0aGlzLiR0aS5kLmIoYykKdD1DLmpuLnl1KGIpCmlm
+KGI9PT10KXRoaXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEubGVuZ3RoCmlmKHR5cGVvZiB0PT09Im51bWJlciImJnQ+Pj4wPT09dClyZXR1cm4gdAp0aHJvdyBI
+LmIoUC5QVigiQmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGljWDoxLAokaXpNOjF9ClAuY28ucHJvdG90
+eXBlPXt9ClAubmQucHJvdG90eXBlPXskaW5kOjF9ClAuS2UucHJvdG90eXBlPXsKUDpmdW5jdGlvbigp
+e3ZhciB0LHMscixxLHA9dGhpcy5hLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSxvPVAuTHModS5OKQppZihw
+PT1udWxsKXJldHVybiBvCmZvcih0PXAuc3BsaXQoIiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtx
+PUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0wKW8uaSgwLHEpfXJldHVybiBvfSwKWDpmdW5jdGlvbihh
+KXt0aGlzLmEuc2V0QXR0cmlidXRlKCJjbGFzcyIsYS5IKDAsIiAiKSl9fQpQLmQ1LnByb3RvdHlwZT17
+CmdEOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5LZShhKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMu
+WUMoYSxiKX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbwppZihkPT1udWxsKXt0
+PUguVk0oW10sdS5RKQpkPW5ldyBXLnZEKHQpCkMuTm0uaSh0LFcuVHcobnVsbCkpCkMuTm0uaSh0LFcu
+QmwoKSkKQy5ObS5pKHQsbmV3IFcuT3coKSl9Yz1uZXcgVy5LbyhkKQpzPSc8c3ZnIHZlcnNpb249IjEu
+MSI+JytILmQoYikrIjwvc3ZnPiIKdD1kb2N1bWVudApyPXQuYm9keQpxPShyJiZDLlJZKS5BSChyLHMs
+YykKcD10LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpxLnRvU3RyaW5nCnQ9bmV3IFcuZTcocSkKbz10
+LmdyOCh0KQpmb3IoO3Q9by5maXJzdENoaWxkLHQhPW51bGw7KXAuYXBwZW5kQ2hpbGQodCkKcmV0dXJu
+IHB9LApnVmw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLkNxKGEsImNsaWNrIiwhMSx1LkMpfSwKJGlk
+NToxfQpQLm42LnByb3RvdHlwZT17JGljWDoxLCRpek06MSwkaUFTOjF9ClQuR1YucHJvdG90eXBlPXt9
+CkwuZS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5CLmIoYSkKdD13aW5kb3cu
+bG9jYXRpb24ucGF0aG5hbWUKcz1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpyPUwuYUsod2luZG93
+LmxvY2F0aW9uLmhyZWYpCkwuR2UoKQppZih0IT09Ii8iJiZ0IT09Si5UMChkb2N1bWVudC5xdWVyeVNl
+bGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSlMLkc3KHQscyxyLG5ldyBMLlZXKHQscyxyKSl9LAok
+UzoxNX0KTC5WVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLHRoaXMuYix0aGlz
+LmMpfSwKJFM6MH0KTC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxCnUuQi5i
+KGEpCnQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5HNih3aW5kb3cubG9jYXRpb24uaHJlZikK
+cj1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQppZih0Lmxlbmd0aD4xKUwuRzcodCxzLHIsbnVsbCkK
+ZWxzZXtxPXUuTgpMLkJFKFAuRUYoWyJyZWdpb25zIiwiIiwibmF2Q29udGVudCIsIiJdLHEscSkpCkwu
+QlgoIiZuYnNwOyIsbnVsbCl9fSwKJFM6MTV9CkwuZVMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
+dmFyIHQscwp1LlYuYihhKQp0PXRoaXMuYQpzPXRoaXMuYgpMLmFmKHdpbmRvdy5sb2NhdGlvbi5wYXRo
+bmFtZSx0LHMsbmV3IEwuRmgodCxzKSkKTC5NVih0aGlzLmMpfSwKJFM6MTB9CkwuRmgucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSx0aGlzLmEsdGhpcy5i
+KX0sCiRTOjB9CkwueXUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMKdS5y
+LmIoYSkKdD1hLnN0YXR1cwppZih0PT09MjAwKXtMLkJFKEMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxu
+dWxsKSkKdD1yLmEKTC5mRyh0LHIuYikKcz1yLmMKTC5CWChDLnhCLnRnKHMsIj8iKT9DLnhCLk5qKHMs
+MCxDLnhCLk9ZKHMsIj8iKSk6cyx0KQp0PXIuZAppZih0IT1udWxsKXQuJDAoKX1lbHNlIHdpbmRvdy5h
+bGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo1fQpMLnpELnByb3Rv
+dHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZEZpbGU6ICIrSC5kKGEpLGIpCndpbmRvdy5h
+bGVydCgiQ291bGQgbm90IGxvYWQgIit0aGlzLmErIiAoIitILmQoYSkrIikuIil9LAokQzoiJDIiLAok
+UjoyLAokUzoxfQpMLlZTLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHM9InNlbGVjdGVk
+LWZpbGUiCnUuaC5iKGEpCmEudG9TdHJpbmcKdD1KLlJFKGEpCmlmKGEuZ2V0QXR0cmlidXRlKCJkYXRh
+LSIrbmV3IFcuU3kobmV3IFcuaTcoYSkpLk8oIm5hbWUiKSk9PT10aGlzLmEuYSl0LmdEKGEpLmkoMCxz
+KQplbHNlIHQuZ0QoYSkuUigwLHMpfSwKJFM6M30KTC5HSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt1LmguYihhKQokLnpCKCkudG9TdHJpbmcKdS5tLmIoJC5vdygpLnEoMCwiaGxqcyIpKS5WNygiaGln
+aGxpZ2h0QmxvY2siLFthXSl9LAokUzozfQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHMscixxPSJjb2xsYXBzZWQiCnUuVi5iKGEpCnQ9dGhpcy5hCnM9Si5SRSh0KQpyPXRoaXMuYgpp
+Zighcy5nRCh0KS50ZygwLHEpKXtzLmdEKHQpLmkoMCxxKQpKLmRSKHIpLmkoMCxxKX1lbHNle3MuZ0Qo
+dCkuUigwLHEpCkouZFIocikuUigwLHEpfX0sCiRTOjEwfQpMLm5ULnByb3RvdHlwZT17CiQwOmZ1bmN0
+aW9uKCl7TC5Gcih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLkJaLnByb3RvdHlwZT17CiQw
+OmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEsbnVsbCxudWxsKX0sCiRTOjB9CkwuRlEucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5yLmIoYSkuc3RhdHVzCmlmKHQhPT0yMDApd2luZG93LmFsZXJ0
+KCJSZXF1ZXN0IGZhaWxlZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0sCiRTOjV9CkwudFkucHJvdG90eXBl
+PXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJoYW5kbGVQb3N0TGlua0NsaWNrOiAiK0guZChhKSxiKQp3
+aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrSC5kKHRoaXMuYS5hKSsiICgiK0guZChhKSsiKS4i
+KX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9CkwuQU8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
+IHQ9Si5xRih1LmguYihhKSkscz10LiR0aQpzLkMoIn4oMSkiKS5iKEwuWE4oKSkKdS5NLmIobnVsbCkK
+Vy5KRSh0LmEsdC5iLEwuWE4oKSwhMSxzLmQpfSwKJFM6M30KTC5Iby5wcm90b3R5cGU9ewokMTpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIKdS5oLmIoYSkKdD1KLnFGKGEpCnM9dC4kdGkKcj1zLkMoIn4oMSkiKS5i
+KG5ldyBMLnh6KGEpKQp1Lk0uYihudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmQpfSwKJFM6M30KTC54
+ei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LlYuYihhKQpMLk1WKHUuYS5iKHRoaXMuYSkpfSwK
+JFM6MTB9CkwuSUMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYihhKSks
+cz10LiR0aQpzLkMoIn4oMSkiKS5iKEwuSDAoKSkKdS5NLmIobnVsbCkKVy5KRSh0LmEsdC5iLEwuSDAo
+KSwhMSxzLmQpfSwKJFM6M30KTC5UVy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIK
+dS5yLmIoYSkKdD1hLnN0YXR1cwppZih0PT09MjAwKXtzPUMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxu
+dWxsKQpyPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIpCkoubDUociwiIikKTC50WChy
+LHMpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0s
+CiRTOjV9CkwueHIucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJsb2FkTmF2aWdhdGlv
+blRyZWU6ICIrSC5kKGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIit0aGlzLmErIiAo
+IitILmQoYSkrIikuIil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLlF2LnByb3RvdHlwZT17CiQxOmZ1
+bmN0aW9uKGEpe3ZhciB0CnUuci5iKGEpCnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7TC5BRihDLkN0LnBX
+KDAsYS5yZXNwb25zZVRleHQsbnVsbCkpCkwueVgoIi5lZGl0LXBhbmVsIC5wYW5lbC1jb250ZW50Iil9
+ZWxzZSB3aW5kb3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQodCkpfSwKJFM6
+NX0KTC5uNC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxvYWRSZWdpb25FeHBsYW5h
+dGlvbjogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK0guZCh0aGlzLmEp
+KyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC5YQS5wcm90b3R5cGU9ewpF
+YjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCiRpa0Y6
+MX0KTS5sSS5wcm90b3R5cGU9ewpXTzpmdW5jdGlvbihhLGIpe3ZhciB0LHM9bnVsbApNLllGKCJhYnNv
+bHV0ZSIsSC5WTShbYixudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbF0sdS5zKSkKdD10aGlzLmEK
+dD10LllyKGIpPjAmJiF0LmhLKGIpCmlmKHQpcmV0dXJuIGIKdD1ELlJYKCkKcmV0dXJuIHRoaXMucTco
+MCx0LGIscyxzLHMscyxzLHMpfSwKdE06ZnVuY3Rpb24oYSl7dmFyIHQscyxyPVguQ0woYSx0aGlzLmEp
+CnIuSVYoKQp0PXIuZApzPXQubGVuZ3RoCmlmKHM9PT0wKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6
+dH1pZihzPT09MSl7dD1yLmIKcmV0dXJuIHQ9PW51bGw/Ii4iOnR9aWYoMD49cylyZXR1cm4gSC5PSCh0
+LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKQpyLklWKCkKcmV0dXJuIHIudygwKX0sCnE3OmZ1bmN0aW9u
+KGEsYixjLGQsZSxmLGcsaCxpKXt2YXIgdD1ILlZNKFtiLGMsZCxlLGYsZyxoLGldLHUucykKTS5ZRigi
+am9pbiIsdCkKcmV0dXJuIHRoaXMuSVAobmV3IEguVTUodCx1LmJCLmIobmV3IE0uTWkoKSksdS5jYykp
+fSwKSVA6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsCnUuY3MuYihhKQpmb3IodD1hLiR0
+aSxzPXQuQygiYTIoY1guRSkiKS5iKG5ldyBNLnE3KCkpLHI9YS5na3ooYSksdD1uZXcgSC5TTyhyLHMs
+dC5DKCJTTzxjWC5FPiIpKSxzPXRoaXMuYSxxPSExLHA9ITEsbz0iIjt0LkYoKTspe249ci5nbCgpCmlm
+KHMuaEsobikmJnApe209WC5DTChuLHMpCmw9by5jaGFyQ29kZUF0KDApPT0wP286bwpvPUMueEIuTmoo
+bCwwLHMuU3AobCwhMCkpCm0uYj1vCmlmKHMuZHMobykpQy5ObS5ZKG0uZSwwLHMuZ21JKCkpCm89bS53
+KDApfWVsc2UgaWYocy5ZcihuKT4wKXtwPSFzLmhLKG4pCm89SC5kKG4pfWVsc2V7aWYoIShuLmxlbmd0
+aD4wJiZzLlVkKG5bMF0pKSlpZihxKW8rPXMuZ21JKCkKbys9SC5kKG4pfXE9cy5kcyhuKX1yZXR1cm4g
+by5jaGFyQ29kZUF0KDApPT0wP286b30sCm81OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCF0aGlzLnkzKGEp
+KXJldHVybiBhCnQ9WC5DTChhLHRoaXMuYSkKdC5yUigpCnJldHVybiB0LncoMCl9LAp5MzpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsawphLnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQpp
+ZihzIT09MCl7aWYodD09PSQuS2soKSlmb3Iocj0wO3I8czsrK3IpaWYoQy54Qi5XKGEscik9PT00Nyly
+ZXR1cm4hMApxPXMKcD00N31lbHNle3E9MApwPW51bGx9Zm9yKG89bmV3IEgucWooYSkuYSxuPW8ubGVu
+Z3RoLHI9cSxtPW51bGw7cjxuOysrcixtPXAscD1sKXtsPUMueEIubShvLHIpCmlmKHQucjQobCkpe2lm
+KHQ9PT0kLktrKCkmJmw9PT00NylyZXR1cm4hMAppZihwIT1udWxsJiZ0LnI0KHApKXJldHVybiEwCmlm
+KHA9PT00NilrPW09PW51bGx8fG09PT00Nnx8dC5yNChtKQplbHNlIGs9ITEKaWYoaylyZXR1cm4hMH19
+aWYocD09bnVsbClyZXR1cm4hMAppZih0LnI0KHApKXJldHVybiEwCmlmKHA9PT00Nil0PW09PW51bGx8
+fHQucjQobSl8fG09PT00NgplbHNlIHQ9ITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkhQOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyLHEscCxvPXRoaXMsbj0nVW5hYmxlIHRvIGZpbmQgYSBwYXRoIHRvICIn
+CmI9by5XTygwLGIpCnQ9by5hCmlmKHQuWXIoYik8PTAmJnQuWXIoYSk+MClyZXR1cm4gby5vNShhKQpp
+Zih0LllyKGEpPD0wfHx0LmhLKGEpKWE9by5XTygwLGEpCmlmKHQuWXIoYSk8PTAmJnQuWXIoYik+MCl0
+aHJvdyBILmIoWC5KVChuK0guZChhKSsnIiBmcm9tICInK0guZChiKSsnIi4nKSkKcz1YLkNMKGIsdCkK
+cy5yUigpCnI9WC5DTChhLHQpCnIuclIoKQpxPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4i
+KSlyZXR1cm4gci53KDApCnE9cy5iCnA9ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwhdC5O
+YyhxLHApCmVsc2UgcT0hMQppZihxKXJldHVybiByLncoMCkKd2hpbGUoITApe3E9cy5kCmlmKHEubGVu
+Z3RoPjApe3A9ci5kCnE9cC5sZW5ndGg+MCYmdC5OYyhxWzBdLHBbMF0pfWVsc2UgcT0hMQppZighcSli
+cmVhawpDLk5tLlc0KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0KHIu
+ZSwxKX1xPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4uIikpdGhyb3cgSC5iKFguSlQobitI
+LmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnE9dS5OCkMuTm0uVUcoci5kLDAsUC5POChzLmQu
+bGVuZ3RoLCIuLiIscSkpCkMuTm0uWShyLmUsMCwiIikKQy5ObS5VRyhyLmUsMSxQLk84KHMuZC5sZW5n
+dGgsdC5nbUkoKSxxKSkKdD1yLmQKcT10Lmxlbmd0aAppZihxPT09MClyZXR1cm4iLiIKaWYocT4xJiZK
+LlJNKEMuTm0uZ3JaKHQpLCIuIikpe3Q9ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsLTEp
+CnQucG9wKCkKdD1yLmUKQy5ObS5tdih0KQpDLk5tLm12KHQpCkMuTm0uaSh0LCIiKX1yLmI9IiIKci5J
+VigpCnJldHVybiByLncoMCl9fQpNLk1pLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBI
+LnkoYSkhPW51bGx9LAokUzo3fQpNLnE3LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBI
+LnkoYSkhPT0iIn0sCiRTOjd9Ck0uTm8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC55KGEpCnJl
+dHVybiBhPT1udWxsPyJudWxsIjonIicrYSsnIid9LAokUzo2fQpCLkx1LnByb3RvdHlwZT17CnhaOmZ1
+bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5ZcihhKQppZihzPjApcmV0dXJuIEoubGQoYSwwLHMpCmlmKHRo
+aXMuaEsoYSkpe2lmKDA+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsMCkKdD1hWzBdfWVsc2UgdD1udWxs
+CnJldHVybiB0fSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsK
+SVY6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcwp3aGlsZSghMCl7dD1yLmQKaWYoISh0Lmxlbmd0aCE9
+PTAmJkouUk0oQy5ObS5ncloodCksIiIpKSlicmVhawp0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1cm4g
+SC5PSCh0LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKX10PXIuZQpzPXQubGVuZ3RoCmlmKHM+MClDLk5t
+LlkodCxzLTEsIiIpfSwKclI6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMsbD1ILlZN
+KFtdLHUucykKZm9yKHQ9bS5kLHM9dC5sZW5ndGgscj0wLHE9MDtxPHQubGVuZ3RoO3QubGVuZ3RoPT09
+c3x8KDAsSC5saykodCksKytxKXtwPXRbcV0Kbz1KLmlhKHApCmlmKCEoby5ETihwLCIuIil8fG8uRE4o
+cCwiIikpKWlmKG8uRE4ocCwiLi4iKSlpZihsLmxlbmd0aD4wKWwucG9wKCkKZWxzZSArK3IKZWxzZSBD
+Lk5tLmkobCxwKX1pZihtLmI9PW51bGwpQy5ObS5VRyhsLDAsUC5POChyLCIuLiIsdS5OKSkKaWYobC5s
+ZW5ndGg9PT0wJiZtLmI9PW51bGwpQy5ObS5pKGwsIi4iKQpuPVAuZEgobC5sZW5ndGgsbmV3IFgucVIo
+bSksITAsdS5OKQp0PW0uYgp0PXQhPW51bGwmJmwubGVuZ3RoPjAmJm0uYS5kcyh0KT9tLmEuZ21JKCk6
+IiIKSC50NihuKS5kLmIodCkKaWYoISFuLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoImluc2VydCIpKQpu
+LnNwbGljZSgwLDAsdCkKbS5zbkoobCkKbS5zUGgobikKdD1tLmIKaWYodCE9bnVsbCYmbS5hPT09JC5L
+aygpKXt0LnRvU3RyaW5nCm0uYj1ILnlzKHQsIi8iLCJcXCIpfW0uSVYoKX0sCnc6ZnVuY3Rpb24oYSl7
+dmFyIHQscyxyPXRoaXMscT1yLmIKcT1xIT1udWxsP3E6IiIKZm9yKHQ9MDt0PHIuZC5sZW5ndGg7Kyt0
+KXtzPXIuZQppZih0Pj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLHQpCnM9cStILmQoc1t0XSkKcT1yLmQK
+aWYodD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSx0KQpxPXMrSC5kKHFbdF0pfXErPUguZChDLk5tLmdy
+WihyLmUpKQpyZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCnNuSjpmdW5jdGlvbihhKXt0aGlz
+LmQ9dS5pLmIoYSl9LApzUGg6ZnVuY3Rpb24oYSl7dGhpcy5lPXUuaS5iKGEpfX0KWC5xUi5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmEuZ21JKCl9LAokUzozN30KWC5kdi5wcm90
+b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhjZXB0aW9uOiAiK3RoaXMuYX19Ck8uekwu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nb2ModGhpcyl9fQpFLk9GLnByb3Rv
+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
+biJcXCJ9fTsoZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUoudkIucHJvdG90eXBlCnQuVT10LncKdC5T
+aj10LmU3CnQ9Si5NRi5wcm90b3R5cGUKdC50PXQudwp0PVAuY1gucHJvdG90eXBlCnQuR0c9dC5ldgp0
+PVAuay5wcm90b3R5cGUKdC54Yj10LncKdD1XLmN2LnByb3RvdHlwZQp0LkRXPXQucjYKdD1XLm02LnBy
+b3RvdHlwZQp0LmpGPXQuRWIKdD1QLkU0LnByb3RvdHlwZQp0LlVyPXQucQp0LmU0PXQuWX0pKCk7KGZ1
+bmN0aW9uIGluc3RhbGxUZWFyT2Zmcygpe3ZhciB0PWh1bmtIZWxwZXJzLl9zdGF0aWNfMSxzPWh1bmtI
+ZWxwZXJzLl9zdGF0aWNfMCxyPWh1bmtIZWxwZXJzLmluc3RhbGxJbnN0YW5jZVRlYXJPZmYscT1odW5r
+SGVscGVycy5pbnN0YWxsU3RhdGljVGVhck9mZgp0KFAsIkVYIiwiWlYiLDgpCnQoUCwieXQiLCJvQSIs
+OCkKdChQLCJxVyIsIkJ6Iiw4KQpzKFAsIlVJIiwiZU4iLDIpCnIoUC5QZi5wcm90b3R5cGUsImdZSiIs
+MCwxLG51bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0sMjMsMCkKdChQLCJQSCIsIk10Iiw2KQpxKFcs
+InBTIiw0LG51bGwsWyIkNCJdLFsieVciXSwxNiwwKQpxKFcsIlY0Iiw0LG51bGwsWyIkNCJdLFsiUVci
+XSwxNiwwKQp0KFAsImlHIiwid1kiLDQpCnQoUCwidzAiLCJMNyIsMjkpCnQoTCwiWE4iLCJ0MiIsMTQp
+CnQoTCwiSDAiLCJ1bSIsMTQpfSkoKTsoZnVuY3Rpb24gaW5oZXJpdGFuY2UoKXt2YXIgdD1odW5rSGVs
+cGVycy5taXhpbixzPWh1bmtIZWxwZXJzLmluaGVyaXQscj1odW5rSGVscGVycy5pbmhlcml0TWFueQpz
+KFAuayxudWxsKQpyKFAuayxbSC5lbyxKLnZCLEoubTEsUC5uWSxQLmNYLEguYTcsUC5BbixILlNVLEgu
+UmUsSC53dixQLlBuLEguV1UsSC5MSSxILlRwLEguWnIsUC5YUyxILlhPLFAuWWssSC5kYixILk42LEgu
+VlIsSC5FSyxILlBiLEgudFEsSC5TZCxILkpjLEguRyxQLlczLFAuUGYsUC5GZSxQLnZzLFAuT00sUC5x
+aCxQLk1PLFAua1QsUC5DdyxQLm0wLFAuWHYsUC5ibixQLmxtLFAubEQsUC5LUCxQLmxmLFAuV1ksUC5V
+ayxQLlJ3LFAuYnosUC5hMixQLmlQLFAuRkssUC5rNSxQLktZLFAuQ0QsUC5hRSxQLkVILFAuek0sUC5a
+MCxQLmM4LFAuT2QsUC5pYixQLkd6LFAucVUsUC5SbixQLkdELFAuRG4sUC5QRSxQLlVmLFcuaWQsVy5G
+ayxXLkpRLFcuR20sVy52RCxXLm02LFcuT3csVy5XOSxXLmRXLFcua0YsVy5tayxXLktvLFAuaUosUC5F
+NCxQLm42LFQuR1YsTC5YQSxNLmxJLE8uekwsWC5XRCxYLmR2XSkKcihKLnZCLFtKLnlFLEouWUUsSi5N
+RixKLmpkLEoucUksSi5EcixILkVULFcuRDAsVy5BeixXLkxlLFcuTmgsVy5JQixXLm43LFcuZWEsVy5i
+cixXLlNnLFcudTgsVy5LNyxXLlhXLFAuaEZdKQpyKEouTUYsW0ouaUMsSi5rZCxKLmM1XSkKcyhKLlBv
+LEouamQpCnIoSi5xSSxbSi51cixKLlZBXSkKcyhQLkxVLFAublkpCnIoUC5MVSxbSC5YQyxXLnd6LFcu
+ZTddKQpzKEgucWosSC5YQykKcihQLmNYLFtILmJRLEguVTUsUC5tVyxILnVuXSkKcihILmJRLFtILmFM
+LEguaTUsUC54dV0pCnIoSC5hTCxbSC5uSCxILkE4LFAuaThdKQpzKEguU08sUC5BbikKcyhQLlJVLFAu
+UG4pCnMoUC5HaixQLlJVKQpzKEguUEQsUC5HaikKcyhILkxQLEguV1UpCnIoSC5UcCxbSC5DaixILkFt
+LEgubGMsSC5kQyxILndOLEguVlgsUC50aCxQLmhhLFAuVnMsUC5GdCxQLnlILFAuZGEsUC5vUSxQLnBW
+LFAuVTcsUC52cixQLnJILFAuS0YsUC5aTCxQLlJULFAualosUC5ycSxQLlJXLFAuQjUsUC5QSSxQLnBL
+LFAuaGosUC5WcCxQLk9SLFAucmEsUC5XRixQLm4xLFAuY1MsUC5WQyxQLnRwLFAuZTEsUC5OWSxQLlJa
+LFAucTMsUC55SSxQLmM2LFAucWQsVy5DdixXLmJVLFcuaEgsVy5LUyxXLkEzLFcudk4sVy5VdixXLkVn
+LFcuRW8sVy5XayxXLklBLFcuZm0sUC5sUixQLmpnLFAuR0UsUC5QQyxQLlltLFAuTnosUC5RUyxQLm5w
+LEwuZSxMLlZXLEwuTCxMLmVTLEwuRmgsTC55dSxMLnpELEwuVlMsTC5HSCxMLld4LEwublQsTC5CWixM
+LkZRLEwudFksTC5BTyxMLkhvLEwueHosTC5JQyxMLlRXLEwueHIsTC5RdixMLm40LE0uTWksTS5xNyxN
+Lk5vLFgucVJdKQpyKFAuWFMsW0guVzAsSC5heixILnZWLEguRXEsUC5DNixILnU5LFAubixQLnUsUC5t
+cCxQLnViLFAuZHMsUC5saixQLlVWLFAuY10pCnIoSC5sYyxbSC56eCxILnJUXSkKcyhILmtZLFAuQzYp
+CnMoUC5pbCxQLllrKQpyKFAuaWwsW0guTjUsUC51dyxXLkQ5LFcuU3ldKQpzKEguS1csUC5tVykKcyhI
+LmIwLEguRVQpCnIoSC5iMCxbSC5SRyxILldCXSkKcyhILlZQLEguUkcpCnMoSC5EZyxILlZQKQpzKEgu
+WkcsSC5XQikKcyhILlBnLEguWkcpCnIoSC5QZyxbSC54aixILmRFLEguWkEsSC53ZixILlBxLEguZUUs
+SC5WNl0pCnIoSC51OSxbSC5oeixILmlNXSkKcyhQLlpmLFAuUGYpCnMoUC5KaSxQLm0wKQpzKFAuYjYs
+UC5YdikKcyhQLlZqLFAuV1kpCnIoUC5VayxbUC5DVixQLlppLFAuYnldKQpzKFAud0ksUC5rVCkKcihQ
+LndJLFtQLlU4LFAuTXgsUC5FMyxQLkdZXSkKcyhQLnU1LFAuWmkpCnIoUC5GSyxbUC5DUCxQLktOXSkK
+cihQLnUsW1AuYkosUC5lWV0pCnMoUC5xZSxQLkRuKQpyKFcuRDAsW1cudUgsVy53YSxXLks1LFcuQ21d
+KQpyKFcudUgsW1cuY3YsVy5ueCxXLlFGLFcuQ1FdKQpyKFcuY3YsW1cucUUsUC5kNV0pCnIoVy5xRSxb
+Vy5HaCxXLmZZLFcubkIsVy5RUCxXLmg0LFcubHAsVy5UYixXLkl2LFcuQlQsVy55WV0pCnMoVy5vSixX
+LkxlKQpzKFcuVDUsVy5BeikKcyhXLlZiLFcuUUYpCnMoVy5PNyxXLndhKQpyKFcuZWEsW1cudzYsVy5l
+d10pCnMoVy5BaixXLnc2KQpzKFcuckIsVy5LNykKcyhXLkJILFcuckIpCnMoVy53NCxXLklCKQpzKFcu
+b2EsVy5YVykKcyhXLnJoLFcub2EpCnMoVy5pNyxXLkQ5KQpzKFAuQXMsUC5WaikKcihQLkFzLFtXLkk0
+LFAuS2VdKQpzKFcuUk8sUC5xaCkKcyhXLkNxLFcuUk8pCnMoVy54QyxQLk1PKQpzKFcuY3QsVy5tNikK
+cyhQLkJmLFAuaUopCnIoUC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28pCnMoUC5uZCxQLmQ1KQpz
+KEIuTHUsTy56TCkKcihCLkx1LFtFLk9GLEYucnUsTC5JVl0pCnQoSC5YQyxILlJlKQp0KEguUkcsUC5s
+RCkKdChILlZQLEguU1UpCnQoSC5XQixQLmxEKQp0KEguWkcsSC5TVSkKdChQLm5ZLFAubEQpCnQoUC5X
+WSxQLmxmKQp0KFAuUlUsUC5LUCkKdChXLkxlLFcuaWQpCnQoVy5LNyxQLmxEKQp0KFcuckIsVy5HbSkK
+dChXLlhXLFAubEQpCnQoVy5vYSxXLkdtKQp0KFAuY28sUC5sRCl9KSgpCnZhciB2PXt0eXBlVW5pdmVy
+c2U6e2VDOm5ldyBNYXAoKSx0Ujp7fSxlVDp7fSx0UFY6e30sc0VBOltdfSxtYW5nbGVkR2xvYmFsTmFt
+ZXM6e0tOOiJpbnQiLENQOiJkb3VibGUiLEZLOiJudW0iLHFVOiJTdHJpbmciLGEyOiJib29sIixjODoi
+TnVsbCIsek06Ikxpc3QifSxtYW5nbGVkTmFtZXM6e30sZ2V0VHlwZUZyb21OYW1lOmdldEdsb2JhbEZy
+b21OYW1lLG1ldGFkYXRhOltdLHR5cGVzOlsiYzgoKSIsImM4KEAsQCkiLCJ+KCkiLCJjOChjdikiLCJA
+KEApIiwiYzgoTzcpIiwicVUocVUpIiwiYTIocVUpIiwifih+KCkpIiwiYzgocVUscVUpIiwiYzgoQWop
+IiwiYzgocVUpIiwiYzgoQCkiLCJhMihrRikiLCJ+KEFqKSIsImM4KGVhKSIsImEyKGN2LHFVLHFVLEpR
+KSIsImM4KEdELEApIiwiWjA8cVUscVU+KFowPHFVLHFVPixxVSkiLCJjOChxVSxAKSIsIn4ocVVbQF0p
+IiwiS04oS04sS04pIiwiQChALHFVKSIsIn4oa1tHel0pIiwibjYoS04pIiwiYzgoQFtHel0pIiwiYTIo
+dUgpIiwiYzgoZXcpIiwiQChlYSkiLCJrKEApIiwiYTIoeHU8cVU+KSIsInI3KEApIiwiVHo8QD4oQCki
+LCJFNChAKSIsInZzPEA+KEApIiwifihxVSxLTikiLCJjOCh+KCkpIiwicVUoS04pIiwiQChxVSkiLCJ+
+KHVILHVIKSIsIm42KEAsQCkiXSxpbnRlcmNlcHRvcnNCeVRhZzpudWxsLGxlYWZUYWdzOm51bGx9Ckgu
+eGIodi50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJjNSI6Ik1GIiwiaUMiOiJNRiIsImtkIjoiTUYi
+LCJyeCI6ImVhIiwiZTUiOiJlYSIsIlkwIjoiZDUiLCJXdCI6ImQ1IiwidjAiOiJldyIsIk1yIjoicUUi
+LCJlTCI6InFFIiwiSTAiOiJ1SCIsImhzIjoidUgiLCJYZyI6IlFGIiwibnIiOiJBaiIsInk0IjoidzYi
+LCJkTiI6IkNtIiwianIiOiJueCIsImtKIjoibngiLCJ6VSI6IkRnIiwiZGYiOiJFVCIsInlFIjp7ImEy
+IjpbXX0sIllFIjp7ImM4IjpbXX0sIk1GIjp7InZtIjpbXSwiRUgiOltdfSwiamQiOnsiek0iOlsiMSJd
+LCJjWCI6WyIxIl19LCJQbyI6eyJqZCI6WyIxIl0sInpNIjpbIjEiXSwiY1giOlsiMSJdfSwibTEiOnsi
+QW4iOlsiMSJdfSwicUkiOnsiQ1AiOltdLCJGSyI6W119LCJ1ciI6eyJLTiI6W10sIkNQIjpbXSwiRksi
+OltdfSwiVkEiOnsiQ1AiOltdLCJGSyI6W119LCJEciI6eyJxVSI6W10sInZYIjpbXX0sInFqIjp7IlJl
+IjpbIktOIl0sImxEIjpbIktOIl0sInpNIjpbIktOIl0sImNYIjpbIktOIl0sImxELkUiOiJLTiIsIlJl
+LkUiOiJLTiJ9LCJiUSI6eyJjWCI6WyIxIl19LCJhTCI6eyJjWCI6WyIxIl19LCJuSCI6eyJhTCI6WyIx
+Il0sImNYIjpbIjEiXSwiYUwuRSI6IjEiLCJjWC5FIjoiMSJ9LCJhNyI6eyJBbiI6WyIxIl19LCJBOCI6
+eyJhTCI6WyIyIl0sImNYIjpbIjIiXSwiYUwuRSI6IjIiLCJjWC5FIjoiMiJ9LCJVNSI6eyJjWCI6WyIx
+Il0sImNYLkUiOiIxIn0sIlNPIjp7IkFuIjpbIjEiXX0sIlhDIjp7IlJlIjpbIjEiXSwibEQiOlsiMSJd
+LCJ6TSI6WyIxIl0sImNYIjpbIjEiXX0sInd2Ijp7IkdEIjpbXX0sIlBEIjp7IkdqIjpbIjEiLCIyIl0s
+IlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19
+LCJXVSI6eyJaMCI6WyIxIiwiMiJdfSwiTFAiOnsiV1UiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0s
+IkxJIjp7InZRIjpbXX0sIlcwIjp7IlhTIjpbXX0sImF6Ijp7IlhTIjpbXX0sInZWIjp7IlhTIjpbXX0s
+IlhPIjp7Ikd6IjpbXX0sIlRwIjp7IkVIIjpbXX0sImxjIjp7IkVIIjpbXX0sInp4Ijp7IkVIIjpbXX0s
+InJUIjp7IkVIIjpbXX0sIkVxIjp7IlhTIjpbXX0sImtZIjp7IlhTIjpbXX0sIk41Ijp7IkZvIjpbIjEi
+LCIyIl0sIllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl0sIllrLksiOiIxIiwiWWsuViI6IjIifSwi
+aTUiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJONiI6eyJBbiI6WyIxIl19LCJWUiI6eyJ3TCI6W10s
+InZYIjpbXX0sIkVLIjp7ImliIjpbXSwiT2QiOltdfSwiS1ciOnsiY1giOlsiaWIiXSwiY1guRSI6Imli
+In0sIlBiIjp7IkFuIjpbImliIl19LCJ0USI6eyJPZCI6W119LCJ1biI6eyJjWCI6WyJPZCJdLCJjWC5F
+IjoiT2QifSwiU2QiOnsiQW4iOlsiT2QiXX0sIkVUIjp7IkFTIjpbXX0sImIwIjp7IlhqIjpbIkAiXSwi
+RVQiOltdLCJBUyI6W119LCJEZyI6eyJsRCI6WyJDUCJdLCJYaiI6WyJAIl0sInpNIjpbIkNQIl0sIkVU
+IjpbXSwiU1UiOlsiQ1AiXSwiQVMiOltdLCJjWCI6WyJDUCJdLCJsRC5FIjoiQ1AifSwiUGciOnsibEQi
+OlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwi
+Y1giOlsiS04iXX0sInhqIjp7ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltd
+LCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJkRSI6eyJsRCI6WyJL
+TiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwiQVMiOltdLCJjWCI6
+WyJLTiJdLCJsRC5FIjoiS04ifSwiWkEiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJd
+LCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sIndmIjp7
+ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6
+W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJQcSI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJY
+aiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04i
+fSwiZUUiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktO
+Il0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sIlY2Ijp7Im42IjpbXSwibEQiOlsiS04i
+XSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1giOlsi
+S04iXSwibEQuRSI6IktOIn0sInU5Ijp7IlhTIjpbXX0sImh6Ijp7IlhTIjpbXX0sImlNIjp7IlhTIjpb
+XX0sIlpmIjp7IlBmIjpbIjEiXX0sInZzIjp7ImI4IjpbIjEiXX0sIkN3Ijp7IlhTIjpbXX0sIm0wIjp7
+IkpCIjpbXX0sIkppIjp7IkpCIjpbXX0sImI2Ijp7Ilh2IjpbIjEiXSwieHUiOlsiMSJdLCJjWCI6WyIx
+Il19LCJsbSI6eyJBbiI6WyIxIl19LCJtVyI6eyJjWCI6WyIxIl19LCJMVSI6eyJsRCI6WyIxIl0sInpN
+IjpbIjEiXSwiY1giOlsiMSJdfSwiaWwiOnsiWWsiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIllr
+Ijp7IlowIjpbIjEiLCIyIl19LCJQbiI6eyJaMCI6WyIxIiwiMiJdfSwiR2oiOnsiUlUiOlsiMSIsIjIi
+XSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIlZqIjp7ImxmIjpb
+IjEiXSwieHUiOlsiMSJdLCJjWCI6WyIxIl19LCJYdiI6eyJ4dSI6WyIxIl0sImNYIjpbIjEiXX0sInV3
+Ijp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6IkAifSwi
+aTgiOnsiYUwiOlsicVUiXSwiY1giOlsicVUiXSwiYUwuRSI6InFVIiwiY1guRSI6InFVIn0sIkNWIjp7
+IlVrIjpbInpNPEtOPiIsInFVIl0sIlVrLlMiOiJ6TTxLTj4ifSwiVTgiOnsid0kiOlsiek08S04+Iiwi
+cVUiXX0sIlppIjp7IlVrIjpbInFVIiwiek08S04+Il19LCJieSI6eyJVayI6WyJrIiwicVUiXSwiVWsu
+UyI6ImsifSwiTXgiOnsid0kiOlsicVUiLCJrIl19LCJ1NSI6eyJVayI6WyJxVSIsInpNPEtOPiJdLCJV
+ay5TIjoicVUifSwiRTMiOnsid0kiOlsicVUiLCJ6TTxLTj4iXX0sIkdZIjp7IndJIjpbInpNPEtOPiIs
+InFVIl19LCJDUCI6eyJGSyI6W119LCJDNiI6eyJYUyI6W119LCJuIjp7IlhTIjpbXX0sInUiOnsiWFMi
+OltdfSwiYkoiOnsiWFMiOltdfSwiZVkiOnsiWFMiOltdfSwibXAiOnsiWFMiOltdfSwidWIiOnsiWFMi
+OltdfSwiZHMiOnsiWFMiOltdfSwibGoiOnsiWFMiOltdfSwiVVYiOnsiWFMiOltdfSwiazUiOnsiWFMi
+OltdfSwiS1kiOnsiWFMiOltdfSwiYyI6eyJYUyI6W119LCJLTiI6eyJGSyI6W119LCJ6TSI6eyJjWCI6
+WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4dSI6eyJjWCI6WyIxIl19LCJxVSI6eyJ2WCI6W119LCJSbiI6
+eyJCTCI6W119LCJEbiI6eyJpRCI6W119LCJVZiI6eyJpRCI6W119LCJxZSI6eyJpRCI6W119LCJxRSI6
+eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiR2giOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImZZ
+Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJuQiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwi
+UVAiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm54Ijp7InVIIjpbXSwiRDAiOltdfSwiUUYiOnsi
+dUgiOltdLCJEMCI6W119LCJJQiI6eyJ0biI6WyJGSyJdfSwid3oiOnsibEQiOlsiMSJdLCJ6TSI6WyIx
+Il0sImNYIjpbIjEiXSwibEQuRSI6IjEifSwiY3YiOnsidUgiOltdLCJEMCI6W119LCJUNSI6eyJBeiI6
+W119LCJoNCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiVmIiOnsidUgiOltdLCJEMCI6W119LCJP
+NyI6eyJEMCI6W119LCJ3YSI6eyJEMCI6W119LCJBaiI6eyJlYSI6W119LCJlNyI6eyJsRCI6WyJ1SCJd
+LCJ6TSI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJsRC5FIjoidUgifSwidUgiOnsiRDAiOltdfSwiQkgiOnsi
+R20iOlsidUgiXSwibEQiOlsidUgiXSwiek0iOlsidUgiXSwiWGoiOlsidUgiXSwiY1giOlsidUgiXSwi
+bEQuRSI6InVIIiwiR20uRSI6InVIIn0sImV3Ijp7ImVhIjpbXX0sImxwIjp7ImN2IjpbXSwidUgiOltd
+LCJEMCI6W119LCJUYiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiSXYiOnsiY3YiOltdLCJ1SCI6
+W10sIkQwIjpbXX0sIkJUIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJ5WSI6eyJjdiI6W10sInVI
+IjpbXSwiRDAiOltdfSwidzYiOnsiZWEiOltdfSwiSzUiOnsidjYiOltdLCJEMCI6W119LCJDbSI6eyJE
+MCI6W119LCJDUSI6eyJ1SCI6W10sIkQwIjpbXX0sInc0Ijp7InRuIjpbIkZLIl19LCJyaCI6eyJHbSI6
+WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJsRC5F
+IjoidUgiLCJHbS5FIjoidUgifSwiRDkiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl19
+LCJpNyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsuViI6
+InFVIn0sIlN5Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZ
+ay5WIjoicVUifSwiSTQiOnsibGYiOlsicVUiXSwieHUiOlsicVUiXSwiY1giOlsicVUiXX0sIlJPIjp7
+InFoIjpbIjEiXX0sIkNxIjp7IlJPIjpbIjEiXSwicWgiOlsiMSJdfSwiSlEiOnsia0YiOltdfSwidkQi
+Onsia0YiOltdfSwibTYiOnsia0YiOltdfSwiY3QiOnsia0YiOltdfSwiT3ciOnsia0YiOltdfSwiVzki
+OnsiQW4iOlsiMSJdfSwiZFciOnsidjYiOltdLCJEMCI6W119LCJtayI6eyJ5MCI6W119LCJLbyI6eyJv
+biI6W119LCJBcyI6eyJsZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwicjciOnsiRTQi
+OltdfSwiVHoiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sIkU0IjpbXSwiY1giOlsiMSJdLCJsRC5FIjoi
+MSJ9LCJuZCI6eyJkNSI6W10sImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJLZSI6eyJsZiI6WyJxVSJd
+LCJ4dSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwiZDUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm42
+Ijp7InpNIjpbIktOIl0sIkFTIjpbXSwiY1giOlsiS04iXX0sIlhBIjp7ImtGIjpbXX0sIk9GIjp7Ikx1
+IjpbXX0sInJ1Ijp7Ikx1IjpbXX0sIklWIjp7Ikx1IjpbXX19JykpCkguRkYodi50eXBlVW5pdmVyc2Us
+SlNPTi5wYXJzZSgneyJiUSI6MSwiWEMiOjEsIk1PIjoxLCJrVCI6MiwibVciOjEsIkxVIjoxLCJpbCI6
+MiwiVmoiOjEsIm5ZIjoxLCJXWSI6MSwiY28iOjF9JykpCnZhciB1PShmdW5jdGlvbiBydGlpKCl7dmFy
+IHQ9SC5OMApyZXR1cm57YTp0KCJHaCIpLG46dCgiQ3ciKSxEOnQoIm5CIiksZDp0KCJBeiIpLFg6dCgi
+UVAiKSxGOnQoIlBEPEdELEA+IiksaDp0KCJjdiIpLGJVOnQoIlhTIiksQjp0KCJlYSIpLGFTOnQoIkQw
+IiksYzg6dCgiVDUiKSxaOnQoIkVIIiksYzp0KCJiODxAPiIpLHI6dCgiTzciKSxJOnQoIlNnIiksbzp0
+KCJ2USIpLGVoOnQoImNYPHVIPiIpLGNzOnQoImNYPHFVPiIpLFI6dCgiY1g8QD4iKSxROnQoImpkPGtG
+PiIpLHM6dCgiamQ8cVU+IiksYjp0KCJqZDxAPiIpLHQ6dCgiamQ8S04+IiksZUg6dCgidm0iKSxnOnQo
+ImM1IiksYVU6dCgiWGo8QD4iKSxhbTp0KCJUejxAPiIpLGVvOnQoIk41PEdELEA+IiksbTp0KCJFNCIp
+LHc6dCgiaEYiKSxpOnQoInpNPHFVPiIpLGo6dCgiek08QD4iKSxMOnQoInpNPEtOPiIpLGY6dCgiWjA8
+cVUscVU+IiksRzp0KCJaMDxALEA+IiksZHY6dCgiQTg8cVUscVU+IiksZG86dCgiQTg8cVUsQD4iKSxW
+OnQoIkFqIiksZEQ6dCgiRVQiKSxibTp0KCJWNiIpLEE6dCgidUgiKSxlOnQoImtGIiksUDp0KCJjOCIp
+LEs6dCgiayIpLHA6dCgiZXciKSxxOnQoInRuPEZLPiIpLGZ2OnQoIndMIiksYXY6dCgiSmMiKSxldzp0
+KCJuZCIpLFQ6dCgieHU8cVU+IiksbDp0KCJHeiIpLE46dCgicVUiKSxkRzp0KCJxVShxVSkiKSxnNzp0
+KCJkNSIpLGZvOnQoIkdEIiksYVc6dCgieVkiKSxrOnQoIkFTIiksZ2M6dCgibjYiKSxhazp0KCJrZCIp
+LFc6dCgiR2o8cVUscVU+IiksdTp0KCJpRCIpLGNjOnQoIlU1PHFVPiIpLGc0OnQoIks1IiksY2k6dCgi
+djYiKSxnMjp0KCJDbSIpLEU6dCgiWmY8Tzc+IiksaDk6dCgiQ1EiKSxhYzp0KCJlNyIpLEM6dCgiQ3E8
+QWo+IiksUzp0KCJ3ejxjdj4iKSx4OnQoIkZlPEAsQD4iKSxhbzp0KCJ2czxPNz4iKSxfOnQoInZzPEA+
+IiksZko6dCgidnM8S04+IiksTzp0KCJKUSIpLEo6dCgiYm4iKSxjSjp0KCJhMiIpLGFsOnQoImEyKGsp
+IiksYkI6dCgiYTIocVUpIiksYmY6dCgiYTIoQCkiKSx6OnQoIkAiKSxmTzp0KCJAKCkiKSxVOnQoIkAo
+ZWEpIikseTp0KCJAKGspIiksZXA6dCgiQChrLGspIiksWTp0KCJAKGssR3opIiksY2g6dCgiQCh4dTxx
+VT4pIiksZE86dCgiQChxVSkiKSxiODp0KCJAKEAsQCkiKSxIOnQoIn4iKSxNOnQoIn4oKSIpLGFuOnQo
+In4oZXcpIiksdjp0KCJ+KHFVLHFVKSIpLGNBOnQoIn4ocVUsQCkiKX19KSgpOyhmdW5jdGlvbiBjb25z
+dGFudHMoKXt2YXIgdD1odW5rSGVscGVycy5tYWtlQ29uc3RMaXN0CkMuUlk9Vy5RUC5wcm90b3R5cGUK
+Qy5CWj1XLlZiLnByb3RvdHlwZQpDLkR0PVcuTzcucHJvdG90eXBlCkMuT2s9Si52Qi5wcm90b3R5cGUK
+Qy5ObT1KLmpkLnByb3RvdHlwZQpDLmpuPUoudXIucHJvdG90eXBlCkMuak49Si5ZRS5wcm90b3R5cGUK
+Qy5DRD1KLnFJLnByb3RvdHlwZQpDLnhCPUouRHIucHJvdG90eXBlCkMuREc9Si5jNS5wcm90b3R5cGUK
+Qy5FeD1XLnU4LnByb3RvdHlwZQpDLk5BPUguVjYucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUK
+Qy5JZT1XLlRiLnByb3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5LNS5wcm90b3R5cGUK
+Qy55OD1uZXcgUC5VOCgpCkMuaDk9bmV3IFAuQ1YoKQpDLk80PWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNr
+KG8pIHsKICB2YXIgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4g
+cy5zdWJzdHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKfQpDLllxPWZ1bmN0aW9uKCkgewogIHZhciB0b1N0
+cmluZ0Z1bmN0aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWco
+bykgewogICAgdmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJz
+dHJpbmcoOCwgcy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3Qs
+IHRhZykgewogICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZh
+ciBuYW1lID0gdG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJb
+b2JqZWN0IE9iamVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAg
+ICB9CiAgfQogIGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykg
+ewogICAgaWYgKHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQp
+IHJldHVybiAiSFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcp
+OwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRv
+dyA9PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09
+ICJ1bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWdd
+OwogICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAg
+IHJldHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3Io
+dGFnKSB7IHJldHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0g
+Im9iamVjdCI7CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzog
+aXNCcm93c2VyID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAg
+IHByb3RvdHlwZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3Jp
+bWluYXRvciB9Owp9CkMud2I9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rp
+b24oaG9va3MpIHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9v
+a3M7CiAgICB2YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1
+bXBSZW5kZXJUcmVlIikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9t
+ZSIpID49IDApIHsKICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVv
+ZiB3aW5kb3cgPT0gIm9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAg
+ICAgIH0KICAgICAgaWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50Iikp
+IHJldHVybiBob29rczsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07
+Cn0KQy5LVT1mdW5jdGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVw
+R2V0VGFnICE9ICJmdW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhw
+ZXJpbWVudGFsRml4dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLmZRPWZ1bmN0aW9uKGhvb2tzKSB7
+CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3Mu
+cHJvdG90eXBlRm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBn
+ZXRUYWcobyk7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJz
+aW9uKSByZXR1cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9
+CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsK
+ICAgIGlmICh0YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBl
+Rm9yVGFnKHRhZyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3Rv
+dHlwZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMuZGs9ZnVuY3Rpb24oaG9va3MpIHsK
+ICB2YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51
+c2VyQWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0
+dXJuIGhvb2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewog
+ICAgIkJlZm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJv
+YXJkIiwKICAgICJHZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAi
+IUxvY2F0aW9uIiwKICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJY
+TUxEb2N1bWVudCI6ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAg
+IHZhciB0YWcgPSBnZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQog
+IGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy54aT1mdW5jdGlvbihob29rcykgewogIHZh
+ciB1c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJB
+Z2VudCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJu
+IGhvb2tzOwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAg
+IkJlZm9yZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJk
+IiwKICAgICJIVE1MRERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50Ijog
+IkhUTUxFbGVtZW50IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAi
+UG9zaXRpb24iOiAiR2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2
+YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAo
+bmV3VGFnKSByZXR1cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAo
+d2luZG93LkRhdGFWaWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJE
+YXRhVmlldyI7CiAgICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JU
+YWdJRSh0YWcpIHsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0
+cnVjdG9yID09IG51bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlw
+ZTsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0g
+cHJvdG90eXBlRm9yVGFnSUU7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0K
+CkMuQ3Q9bmV3IFAuYnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAu
+RTMoKQpDLk5VPW5ldyBQLkppKCkKQy5BMz1uZXcgUC5NeChudWxsKQpDLkdiPUguVk0odChbMTI3LDIw
+NDcsNjU1MzUsMTExNDExMV0pLHUudCkKQy5haz1ILlZNKHQoWzAsMCwzMjc3NiwzMzc5MiwxLDEwMjQw
+LDAsMF0pLHUudCkKQy5jbT1ILlZNKHQoWyIqOjpjbGFzcyIsIio6OmRpciIsIio6OmRyYWdnYWJsZSIs
+Iio6OmhpZGRlbiIsIio6OmlkIiwiKjo6aW5lcnQiLCIqOjppdGVtcHJvcCIsIio6Oml0ZW1yZWYiLCIq
+OjppdGVtc2NvcGUiLCIqOjpsYW5nIiwiKjo6c3BlbGxjaGVjayIsIio6OnRpdGxlIiwiKjo6dHJhbnNs
+YXRlIiwiQTo6YWNjZXNza2V5IiwiQTo6Y29vcmRzIiwiQTo6aHJlZmxhbmciLCJBOjpuYW1lIiwiQTo6
+c2hhcGUiLCJBOjp0YWJpbmRleCIsIkE6OnRhcmdldCIsIkE6OnR5cGUiLCJBUkVBOjphY2Nlc3NrZXki
+LCJBUkVBOjphbHQiLCJBUkVBOjpjb29yZHMiLCJBUkVBOjpub2hyZWYiLCJBUkVBOjpzaGFwZSIsIkFS
+RUE6OnRhYmluZGV4IiwiQVJFQTo6dGFyZ2V0IiwiQVVESU86OmNvbnRyb2xzIiwiQVVESU86Omxvb3Ai
+LCJBVURJTzo6bWVkaWFncm91cCIsIkFVRElPOjptdXRlZCIsIkFVRElPOjpwcmVsb2FkIiwiQkRPOjpk
+aXIiLCJCT0RZOjphbGluayIsIkJPRFk6OmJnY29sb3IiLCJCT0RZOjpsaW5rIiwiQk9EWTo6dGV4dCIs
+IkJPRFk6OnZsaW5rIiwiQlI6OmNsZWFyIiwiQlVUVE9OOjphY2Nlc3NrZXkiLCJCVVRUT046OmRpc2Fi
+bGVkIiwiQlVUVE9OOjpuYW1lIiwiQlVUVE9OOjp0YWJpbmRleCIsIkJVVFRPTjo6dHlwZSIsIkJVVFRP
+Tjo6dmFsdWUiLCJDQU5WQVM6OmhlaWdodCIsIkNBTlZBUzo6d2lkdGgiLCJDQVBUSU9OOjphbGlnbiIs
+IkNPTDo6YWxpZ24iLCJDT0w6OmNoYXIiLCJDT0w6OmNoYXJvZmYiLCJDT0w6OnNwYW4iLCJDT0w6OnZh
+bGlnbiIsIkNPTDo6d2lkdGgiLCJDT0xHUk9VUDo6YWxpZ24iLCJDT0xHUk9VUDo6Y2hhciIsIkNPTEdS
+T1VQOjpjaGFyb2ZmIiwiQ09MR1JPVVA6OnNwYW4iLCJDT0xHUk9VUDo6dmFsaWduIiwiQ09MR1JPVVA6
+OndpZHRoIiwiQ09NTUFORDo6Y2hlY2tlZCIsIkNPTU1BTkQ6OmNvbW1hbmQiLCJDT01NQU5EOjpkaXNh
+YmxlZCIsIkNPTU1BTkQ6OmxhYmVsIiwiQ09NTUFORDo6cmFkaW9ncm91cCIsIkNPTU1BTkQ6OnR5cGUi
+LCJEQVRBOjp2YWx1ZSIsIkRFTDo6ZGF0ZXRpbWUiLCJERVRBSUxTOjpvcGVuIiwiRElSOjpjb21wYWN0
+IiwiRElWOjphbGlnbiIsIkRMOjpjb21wYWN0IiwiRklFTERTRVQ6OmRpc2FibGVkIiwiRk9OVDo6Y29s
+b3IiLCJGT05UOjpmYWNlIiwiRk9OVDo6c2l6ZSIsIkZPUk06OmFjY2VwdCIsIkZPUk06OmF1dG9jb21w
+bGV0ZSIsIkZPUk06OmVuY3R5cGUiLCJGT1JNOjptZXRob2QiLCJGT1JNOjpuYW1lIiwiRk9STTo6bm92
+YWxpZGF0ZSIsIkZPUk06OnRhcmdldCIsIkZSQU1FOjpuYW1lIiwiSDE6OmFsaWduIiwiSDI6OmFsaWdu
+IiwiSDM6OmFsaWduIiwiSDQ6OmFsaWduIiwiSDU6OmFsaWduIiwiSDY6OmFsaWduIiwiSFI6OmFsaWdu
+IiwiSFI6Om5vc2hhZGUiLCJIUjo6c2l6ZSIsIkhSOjp3aWR0aCIsIkhUTUw6OnZlcnNpb24iLCJJRlJB
+TUU6OmFsaWduIiwiSUZSQU1FOjpmcmFtZWJvcmRlciIsIklGUkFNRTo6aGVpZ2h0IiwiSUZSQU1FOjpt
+YXJnaW5oZWlnaHQiLCJJRlJBTUU6Om1hcmdpbndpZHRoIiwiSUZSQU1FOjp3aWR0aCIsIklNRzo6YWxp
+Z24iLCJJTUc6OmFsdCIsIklNRzo6Ym9yZGVyIiwiSU1HOjpoZWlnaHQiLCJJTUc6OmhzcGFjZSIsIklN
+Rzo6aXNtYXAiLCJJTUc6Om5hbWUiLCJJTUc6OnVzZW1hcCIsIklNRzo6dnNwYWNlIiwiSU1HOjp3aWR0
+aCIsIklOUFVUOjphY2NlcHQiLCJJTlBVVDo6YWNjZXNza2V5IiwiSU5QVVQ6OmFsaWduIiwiSU5QVVQ6
+OmFsdCIsIklOUFVUOjphdXRvY29tcGxldGUiLCJJTlBVVDo6YXV0b2ZvY3VzIiwiSU5QVVQ6OmNoZWNr
+ZWQiLCJJTlBVVDo6ZGlzYWJsZWQiLCJJTlBVVDo6aW5wdXRtb2RlIiwiSU5QVVQ6OmlzbWFwIiwiSU5Q
+VVQ6Omxpc3QiLCJJTlBVVDo6bWF4IiwiSU5QVVQ6Om1heGxlbmd0aCIsIklOUFVUOjptaW4iLCJJTlBV
+VDo6bXVsdGlwbGUiLCJJTlBVVDo6bmFtZSIsIklOUFVUOjpwbGFjZWhvbGRlciIsIklOUFVUOjpyZWFk
+b25seSIsIklOUFVUOjpyZXF1aXJlZCIsIklOUFVUOjpzaXplIiwiSU5QVVQ6OnN0ZXAiLCJJTlBVVDo6
+dGFiaW5kZXgiLCJJTlBVVDo6dHlwZSIsIklOUFVUOjp1c2VtYXAiLCJJTlBVVDo6dmFsdWUiLCJJTlM6
+OmRhdGV0aW1lIiwiS0VZR0VOOjpkaXNhYmxlZCIsIktFWUdFTjo6a2V5dHlwZSIsIktFWUdFTjo6bmFt
+ZSIsIkxBQkVMOjphY2Nlc3NrZXkiLCJMQUJFTDo6Zm9yIiwiTEVHRU5EOjphY2Nlc3NrZXkiLCJMRUdF
+TkQ6OmFsaWduIiwiTEk6OnR5cGUiLCJMSTo6dmFsdWUiLCJMSU5LOjpzaXplcyIsIk1BUDo6bmFtZSIs
+Ik1FTlU6OmNvbXBhY3QiLCJNRU5VOjpsYWJlbCIsIk1FTlU6OnR5cGUiLCJNRVRFUjo6aGlnaCIsIk1F
+VEVSOjpsb3ciLCJNRVRFUjo6bWF4IiwiTUVURVI6Om1pbiIsIk1FVEVSOjp2YWx1ZSIsIk9CSkVDVDo6
+dHlwZW11c3RtYXRjaCIsIk9MOjpjb21wYWN0IiwiT0w6OnJldmVyc2VkIiwiT0w6OnN0YXJ0IiwiT0w6
+OnR5cGUiLCJPUFRHUk9VUDo6ZGlzYWJsZWQiLCJPUFRHUk9VUDo6bGFiZWwiLCJPUFRJT046OmRpc2Fi
+bGVkIiwiT1BUSU9OOjpsYWJlbCIsIk9QVElPTjo6c2VsZWN0ZWQiLCJPUFRJT046OnZhbHVlIiwiT1VU
+UFVUOjpmb3IiLCJPVVRQVVQ6Om5hbWUiLCJQOjphbGlnbiIsIlBSRTo6d2lkdGgiLCJQUk9HUkVTUzo6
+bWF4IiwiUFJPR1JFU1M6Om1pbiIsIlBST0dSRVNTOjp2YWx1ZSIsIlNFTEVDVDo6YXV0b2NvbXBsZXRl
+IiwiU0VMRUNUOjpkaXNhYmxlZCIsIlNFTEVDVDo6bXVsdGlwbGUiLCJTRUxFQ1Q6Om5hbWUiLCJTRUxF
+Q1Q6OnJlcXVpcmVkIiwiU0VMRUNUOjpzaXplIiwiU0VMRUNUOjp0YWJpbmRleCIsIlNPVVJDRTo6dHlw
+ZSIsIlRBQkxFOjphbGlnbiIsIlRBQkxFOjpiZ2NvbG9yIiwiVEFCTEU6OmJvcmRlciIsIlRBQkxFOjpj
+ZWxscGFkZGluZyIsIlRBQkxFOjpjZWxsc3BhY2luZyIsIlRBQkxFOjpmcmFtZSIsIlRBQkxFOjpydWxl
+cyIsIlRBQkxFOjpzdW1tYXJ5IiwiVEFCTEU6OndpZHRoIiwiVEJPRFk6OmFsaWduIiwiVEJPRFk6OmNo
+YXIiLCJUQk9EWTo6Y2hhcm9mZiIsIlRCT0RZOjp2YWxpZ24iLCJURDo6YWJiciIsIlREOjphbGlnbiIs
+IlREOjpheGlzIiwiVEQ6OmJnY29sb3IiLCJURDo6Y2hhciIsIlREOjpjaGFyb2ZmIiwiVEQ6OmNvbHNw
+YW4iLCJURDo6aGVhZGVycyIsIlREOjpoZWlnaHQiLCJURDo6bm93cmFwIiwiVEQ6OnJvd3NwYW4iLCJU
+RDo6c2NvcGUiLCJURDo6dmFsaWduIiwiVEQ6OndpZHRoIiwiVEVYVEFSRUE6OmFjY2Vzc2tleSIsIlRF
+WFRBUkVBOjphdXRvY29tcGxldGUiLCJURVhUQVJFQTo6Y29scyIsIlRFWFRBUkVBOjpkaXNhYmxlZCIs
+IlRFWFRBUkVBOjppbnB1dG1vZGUiLCJURVhUQVJFQTo6bmFtZSIsIlRFWFRBUkVBOjpwbGFjZWhvbGRl
+ciIsIlRFWFRBUkVBOjpyZWFkb25seSIsIlRFWFRBUkVBOjpyZXF1aXJlZCIsIlRFWFRBUkVBOjpyb3dz
+IiwiVEVYVEFSRUE6OnRhYmluZGV4IiwiVEVYVEFSRUE6OndyYXAiLCJURk9PVDo6YWxpZ24iLCJURk9P
+VDo6Y2hhciIsIlRGT09UOjpjaGFyb2ZmIiwiVEZPT1Q6OnZhbGlnbiIsIlRIOjphYmJyIiwiVEg6OmFs
+aWduIiwiVEg6OmF4aXMiLCJUSDo6Ymdjb2xvciIsIlRIOjpjaGFyIiwiVEg6OmNoYXJvZmYiLCJUSDo6
+Y29sc3BhbiIsIlRIOjpoZWFkZXJzIiwiVEg6OmhlaWdodCIsIlRIOjpub3dyYXAiLCJUSDo6cm93c3Bh
+biIsIlRIOjpzY29wZSIsIlRIOjp2YWxpZ24iLCJUSDo6d2lkdGgiLCJUSEVBRDo6YWxpZ24iLCJUSEVB
+RDo6Y2hhciIsIlRIRUFEOjpjaGFyb2ZmIiwiVEhFQUQ6OnZhbGlnbiIsIlRSOjphbGlnbiIsIlRSOjpi
+Z2NvbG9yIiwiVFI6OmNoYXIiLCJUUjo6Y2hhcm9mZiIsIlRSOjp2YWxpZ24iLCJUUkFDSzo6ZGVmYXVs
+dCIsIlRSQUNLOjpraW5kIiwiVFJBQ0s6OmxhYmVsIiwiVFJBQ0s6OnNyY2xhbmciLCJVTDo6Y29tcGFj
+dCIsIlVMOjp0eXBlIiwiVklERU86OmNvbnRyb2xzIiwiVklERU86OmhlaWdodCIsIlZJREVPOjpsb29w
+IiwiVklERU86Om1lZGlhZ3JvdXAiLCJWSURFTzo6bXV0ZWQiLCJWSURFTzo6cHJlbG9hZCIsIlZJREVP
+Ojp3aWR0aCJdKSx1LnMpCkMuVkM9SC5WTSh0KFswLDAsNjU0OTAsNDUwNTUsNjU1MzUsMzQ4MTUsNjU1
+MzQsMTg0MzFdKSx1LnQpCkMubUs9SC5WTSh0KFswLDAsMjY2MjQsMTAyMyw2NTUzNCwyMDQ3LDY1NTM0
+LDIwNDddKSx1LnQpCkMuU3E9SC5WTSh0KFsiSEVBRCIsIkFSRUEiLCJCQVNFIiwiQkFTRUZPTlQiLCJC
+UiIsIkNPTCIsIkNPTEdST1VQIiwiRU1CRUQiLCJGUkFNRSIsIkZSQU1FU0VUIiwiSFIiLCJJTUFHRSIs
+IklNRyIsIklOUFVUIiwiSVNJTkRFWCIsIkxJTksiLCJNRVRBIiwiUEFSQU0iLCJTT1VSQ0UiLCJTVFlM
+RSIsIlRJVExFIiwiV0JSIl0pLHUucykKQy54RD1ILlZNKHQoW10pLHUucykKQy5kbj1ILlZNKHQoW10p
+LHUuYikKQy50bz1ILlZNKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0p
+LHUudCkKQy5GMz1ILlZNKHQoWzAsMCwyNDU3NiwxMDIzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSks
+dS50KQpDLmVhPUguVk0odChbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSks
+dS50KQpDLlpKPUguVk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSks
+dS50KQpDLldkPUguVk0odChbMCwwLDY1NDkwLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSks
+dS50KQpDLlF4PUguVk0odChbImJpbmQiLCJpZiIsInJlZiIsInJlcGVhdCIsInN5bnRheCJdKSx1LnMp
+CkMuQkk9SC5WTSh0KFsiQTo6aHJlZiIsIkFSRUE6OmhyZWYiLCJCTE9DS1FVT1RFOjpjaXRlIiwiQk9E
+WTo6YmFja2dyb3VuZCIsIkNPTU1BTkQ6Omljb24iLCJERUw6OmNpdGUiLCJGT1JNOjphY3Rpb24iLCJJ
+TUc6OnNyYyIsIklOUFVUOjpzcmMiLCJJTlM6OmNpdGUiLCJROjpjaXRlIiwiVklERU86OnBvc3RlciJd
+KSx1LnMpCkMuV089bmV3IEguTFAoMCx7fSxDLnhELEguTjAoIkxQPHFVLHFVPiIpKQpDLmhVPUguVk0o
+dChbXSksSC5OMCgiamQ8R0Q+IikpCkMuQ009bmV3IEguTFAoMCx7fSxDLmhVLEguTjAoIkxQPEdELEA+
+IikpCkMuVGU9bmV3IEgud3YoImNhbGwiKX0pKCk7KGZ1bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQueWo9
+MAokLm1KPW51bGwKJC5QND1udWxsCiQuTkY9bnVsbAokLlRYPW51bGwKJC54Nz1udWxsCiQubnc9bnVs
+bAokLnZ2PW51bGwKJC5Cdj1udWxsCiQuUzY9bnVsbAokLms4PW51bGwKJC5tZz1udWxsCiQuVUQ9ITEK
+JC5YMz1DLk5VCiQueGc9W10KJC54bz1udWxsCiQuQk89bnVsbAokLmx0PW51bGwKJC5FVT1udWxsCiQu
+b3I9UC5GbCh1Lk4sdS5aKQokLkk2PW51bGwKJC5GZj1udWxsfSkoKTsoZnVuY3Rpb24gbGF6eUluaXRp
+YWxpemVycygpe3ZhciB0PWh1bmtIZWxwZXJzLmxhenkKdCgkLCJmYSIsInciLGZ1bmN0aW9uKCl7cmV0
+dXJuIEguWWcoIl8kZGFydF9kYXJ0Q2xvc3VyZSIpfSkKdCgkLCJZZiIsIlVOIixmdW5jdGlvbigpe3Jl
+dHVybiBILllnKCJfJGRhcnRfanMiKX0pCnQoJCwiVTIiLCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5j
+TShILlM3KHsKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgkLCJ4
+cSIsImxxIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcoeyRtZXRob2QkOm51bGwsCnRvU3RyaW5n
+OmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnQoJCwiUjEiLCJOOSIsZnVuY3Rpb24o
+KXtyZXR1cm4gSC5jTShILlM3KG51bGwpKX0pCnQoJCwiZk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1cm4g
+SC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7bnVsbC4k
+bWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQo
+JCwicWkiLCJLZiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHZvaWQgMCkpfSkKdCgkLCJyWiIs
+IlpoIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0n
+JGFyZ3VtZW50cyQnCnRyeXsodm9pZCAwKS4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMp
+e3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwia3EiLCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5j
+TShILk1qKG51bGwpKX0pCnQoJCwidHQiLCJjMyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlv
+bigpe3RyeXtudWxsLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwi
+ZHQiLCJISyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKHZvaWQgMCkpfSkKdCgkLCJBNyIsInIx
+IixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dHJ5eyh2b2lkIDApLiRtZXRob2QkfWNh
+dGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXtyZXR1
+cm4gUC5PaigpfSkKdCgkLCJraCIsInJmIixmdW5jdGlvbigpe3JldHVybiBQLldJKCl9KQp0KCQsImJ0
+IiwiVjciLGZ1bmN0aW9uKCl7cmV0dXJuIEguRFEoSC5YRihILlZNKFstMiwtMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMSwtMiwtMiwtMiwtMiwtMiw2MiwtMiw2Miwt
+Miw2Myw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSwtMiwtMiwtMiwtMSwtMiwtMiwtMiwwLDEs
+MiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIzLDI0
+LDI1LC0yLC0yLC0yLC0yLDYzLC0yLDI2LDI3LDI4LDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4
+LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLC0yLC0yLC0yLC0yLC0yXSx1LnQp
+KSl9KQp0KCQsIk01Iiwid1EiLGZ1bmN0aW9uKCl7cmV0dXJuIHR5cGVvZiBwcm9jZXNzIT0idW5kZWZp
+bmVkIiYmT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHByb2Nlc3MpPT0iW29iamVjdCBwcm9j
+ZXNzXSImJnByb2Nlc3MucGxhdGZvcm09PSJ3aW4zMiJ9KQp0KCQsIm1mIiwiejQiLGZ1bmN0aW9uKCl7
+cmV0dXJuIFAubnUoIl5bXFwtXFwuMC05QS1aX2Eten5dKiQiKX0pCnQoJCwiSkciLCJ2WiIsZnVuY3Rp
+b24oKXtyZXR1cm4gUC51eCgpfSkKdCgkLCJTQyIsIkFOIixmdW5jdGlvbigpe3JldHVybiBQLnRNKFsi
+QSIsIkFCQlIiLCJBQ1JPTllNIiwiQUREUkVTUyIsIkFSRUEiLCJBUlRJQ0xFIiwiQVNJREUiLCJBVURJ
+TyIsIkIiLCJCREkiLCJCRE8iLCJCSUciLCJCTE9DS1FVT1RFIiwiQlIiLCJCVVRUT04iLCJDQU5WQVMi
+LCJDQVBUSU9OIiwiQ0VOVEVSIiwiQ0lURSIsIkNPREUiLCJDT0wiLCJDT0xHUk9VUCIsIkNPTU1BTkQi
+LCJEQVRBIiwiREFUQUxJU1QiLCJERCIsIkRFTCIsIkRFVEFJTFMiLCJERk4iLCJESVIiLCJESVYiLCJE
+TCIsIkRUIiwiRU0iLCJGSUVMRFNFVCIsIkZJR0NBUFRJT04iLCJGSUdVUkUiLCJGT05UIiwiRk9PVEVS
+IiwiRk9STSIsIkgxIiwiSDIiLCJIMyIsIkg0IiwiSDUiLCJINiIsIkhFQURFUiIsIkhHUk9VUCIsIkhS
+IiwiSSIsIklGUkFNRSIsIklNRyIsIklOUFVUIiwiSU5TIiwiS0JEIiwiTEFCRUwiLCJMRUdFTkQiLCJM
+SSIsIk1BUCIsIk1BUksiLCJNRU5VIiwiTUVURVIiLCJOQVYiLCJOT0JSIiwiT0wiLCJPUFRHUk9VUCIs
+Ik9QVElPTiIsIk9VVFBVVCIsIlAiLCJQUkUiLCJQUk9HUkVTUyIsIlEiLCJTIiwiU0FNUCIsIlNFQ1RJ
+T04iLCJTRUxFQ1QiLCJTTUFMTCIsIlNPVVJDRSIsIlNQQU4iLCJTVFJJS0UiLCJTVFJPTkciLCJTVUIi
+LCJTVU1NQVJZIiwiU1VQIiwiVEFCTEUiLCJUQk9EWSIsIlREIiwiVEVYVEFSRUEiLCJURk9PVCIsIlRI
+IiwiVEhFQUQiLCJUSU1FIiwiVFIiLCJUUkFDSyIsIlRUIiwiVSIsIlVMIiwiVkFSIiwiVklERU8iLCJX
+QlIiXSx1Lk4pfSkKdCgkLCJYNCIsImhHIixmdW5jdGlvbigpe3JldHVybiBQLm51KCJeXFxTKyQiKX0p
+CnQoJCwid08iLCJvdyIsZnVuY3Rpb24oKXtyZXR1cm4gdS5tLmIoUC5ORChzZWxmKSl9KQp0KCQsImt0
+IiwiUjgiLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8kZGFydF9kYXJ0T2JqZWN0Iil9KQp0KCQsIkpl
+Iiwia0kiLGZ1bmN0aW9uKCl7cmV0dXJuIGZ1bmN0aW9uIERhcnRPYmplY3QoYSl7dGhpcy5vPWF9fSkK
+dCgkLCJxdCIsInpCIixmdW5jdGlvbigpe3JldHVybiBuZXcgVC5HVigpfSkKdCgkLCJmZSIsIktHIixm
+dW5jdGlvbigpe3JldHVybiBuZXcgTC5YQSgpfSkKdCgkLCJtTSIsIm5VIixmdW5jdGlvbigpe3JldHVy
+biBuZXcgTS5sSSgkLkhrKCkpfSkKdCgkLCJ5ciIsImJEIixmdW5jdGlvbigpe3JldHVybiBuZXcgRS5P
+RihQLm51KCIvIiksUC5udSgiW14vXSQiKSxQLm51KCJeLyIpKX0pCnQoJCwiTWsiLCJLayIsZnVuY3Rp
+b24oKXtyZXR1cm4gbmV3IEwuSVYoUC5udSgiWy9cXFxcXSIpLFAubnUoIlteL1xcXFxdJCIpLFAubnUo
+Il4oXFxcXFxcXFxbXlxcXFxdK1xcXFxbXlxcXFwvXSt8W2EtekEtWl06Wy9cXFxcXSkiKSxQLm51KCJe
+Wy9cXFxcXSg/IVsvXFxcXF0pIikpfSkKdCgkLCJhayIsIkViIixmdW5jdGlvbigpe3JldHVybiBuZXcg
+Ri5ydShQLm51KCIvIiksUC5udSgiKF5bYS16QS1aXVstKy5hLXpBLVpcXGRdKjovL3xbXi9dKSQiKSxQ
+Lm51KCJbYS16QS1aXVstKy5hLXpBLVpcXGRdKjovL1teL10qIiksUC5udSgiXi8iKSl9KQp0KCQsImxz
+IiwiSGsiLGZ1bmN0aW9uKCl7cmV0dXJuIE8uUmgoKX0pfSkoKTsoZnVuY3Rpb24gbmF0aXZlU3VwcG9y
+dCgpeyFmdW5jdGlvbigpe3ZhciB0PWZ1bmN0aW9uKGEpe3ZhciBuPXt9Cm5bYV09MQpyZXR1cm4gT2Jq
+ZWN0LmtleXMoaHVua0hlbHBlcnMuY29udmVydFRvRmFzdE9iamVjdChuKSlbMF19CnYuZ2V0SXNvbGF0
+ZVRhZz1mdW5jdGlvbihhKXtyZXR1cm4gdCgiX19fZGFydF8iK2Erdi5pc29sYXRlVGFnKX0KdmFyIHM9
+Il9fX2RhcnRfaXNvbGF0ZV90YWdzXyIKdmFyIHI9T2JqZWN0W3NdfHwoT2JqZWN0W3NdPU9iamVjdC5j
+cmVhdGUobnVsbCkpCnZhciBxPSJfWnhZeFgiCmZvcih2YXIgcD0wOztwKyspe3ZhciBvPXQocSsiXyIr
+cCsiXyIpCmlmKCEobyBpbiByKSl7cltvXT0xCnYuaXNvbGF0ZVRhZz1vCmJyZWFrfX12LmRpc3BhdGNo
+UHJvcGVydHlOYW1lPXYuZ2V0SXNvbGF0ZVRhZygiZGlzcGF0Y2hfcmVjb3JkIil9KCkKaHVua0hlbHBl
+cnMuc2V0T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZyh7RE9NRXJyb3I6Si52QixET01JbXBsZW1lbnRh
+dGlvbjpKLnZCLE1lZGlhRXJyb3I6Si52QixOYXZpZ2F0b3I6Si52QixOYXZpZ2F0b3JDb25jdXJyZW50
+SGFyZHdhcmU6Si52QixOYXZpZ2F0b3JVc2VyTWVkaWFFcnJvcjpKLnZCLE92ZXJjb25zdHJhaW5lZEVy
+cm9yOkoudkIsUG9zaXRpb25FcnJvcjpKLnZCLFJhbmdlOkoudkIsU1FMRXJyb3I6Si52QixEYXRhVmll
+dzpILkVULEFycmF5QnVmZmVyVmlldzpILkVULEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRBcnJheTpI
+LkRnLEludDE2QXJyYXk6SC54aixJbnQzMkFycmF5OkguZEUsSW50OEFycmF5OkguWkEsVWludDE2QXJy
+YXk6SC53ZixVaW50MzJBcnJheTpILlBxLFVpbnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFzUGl4ZWxB
+cnJheTpILmVFLFVpbnQ4QXJyYXk6SC5WNixIVE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJSRWxlbWVu
+dDpXLnFFLEhUTUxCdXR0b25FbGVtZW50OlcucUUsSFRNTENhbnZhc0VsZW1lbnQ6Vy5xRSxIVE1MQ29u
+dGVudEVsZW1lbnQ6Vy5xRSxIVE1MRExpc3RFbGVtZW50OlcucUUsSFRNTERhdGFFbGVtZW50OlcucUUs
+SFRNTERhdGFMaXN0RWxlbWVudDpXLnFFLEhUTUxEZXRhaWxzRWxlbWVudDpXLnFFLEhUTUxEaWFsb2dF
+bGVtZW50OlcucUUsSFRNTERpdkVsZW1lbnQ6Vy5xRSxIVE1MRW1iZWRFbGVtZW50OlcucUUsSFRNTEZp
+ZWxkU2V0RWxlbWVudDpXLnFFLEhUTUxIUkVsZW1lbnQ6Vy5xRSxIVE1MSGVhZEVsZW1lbnQ6Vy5xRSxI
+VE1MSGVhZGluZ0VsZW1lbnQ6Vy5xRSxIVE1MSHRtbEVsZW1lbnQ6Vy5xRSxIVE1MSUZyYW1lRWxlbWVu
+dDpXLnFFLEhUTUxJbWFnZUVsZW1lbnQ6Vy5xRSxIVE1MSW5wdXRFbGVtZW50OlcucUUsSFRNTExJRWxl
+bWVudDpXLnFFLEhUTUxMYWJlbEVsZW1lbnQ6Vy5xRSxIVE1MTGVnZW5kRWxlbWVudDpXLnFFLEhUTUxM
+aW5rRWxlbWVudDpXLnFFLEhUTUxNYXBFbGVtZW50OlcucUUsSFRNTE1lZGlhRWxlbWVudDpXLnFFLEhU
+TUxNZW51RWxlbWVudDpXLnFFLEhUTUxNZXRhRWxlbWVudDpXLnFFLEhUTUxNZXRlckVsZW1lbnQ6Vy5x
+RSxIVE1MTW9kRWxlbWVudDpXLnFFLEhUTUxPTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MT2JqZWN0RWxlbWVu
+dDpXLnFFLEhUTUxPcHRHcm91cEVsZW1lbnQ6Vy5xRSxIVE1MT3B0aW9uRWxlbWVudDpXLnFFLEhUTUxP
+dXRwdXRFbGVtZW50OlcucUUsSFRNTFBhcmFncmFwaEVsZW1lbnQ6Vy5xRSxIVE1MUGFyYW1FbGVtZW50
+OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFByZUVsZW1lbnQ6Vy5xRSxIVE1MUHJvZ3Jl
+c3NFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVudDpXLnFFLEhUTUxTY3JpcHRFbGVtZW50OlcucUUs
+SFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xvdEVsZW1lbnQ6Vy5xRSxIVE1MU291cmNlRWxlbWVu
+dDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhUTUxTdHlsZUVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVD
+YXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlRGF0YUNl
+bGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDb2xF
+bGVtZW50OlcucUUsSFRNTFRleHRBcmVhRWxlbWVudDpXLnFFLEhUTUxUaW1lRWxlbWVudDpXLnFFLEhU
+TUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1MVHJhY2tFbGVtZW50OlcucUUsSFRNTFVMaXN0RWxlbWVudDpX
+LnFFLEhUTUxVbmtub3duRWxlbWVudDpXLnFFLEhUTUxWaWRlb0VsZW1lbnQ6Vy5xRSxIVE1MRGlyZWN0
+b3J5RWxlbWVudDpXLnFFLEhUTUxGb250RWxlbWVudDpXLnFFLEhUTUxGcmFtZUVsZW1lbnQ6Vy5xRSxI
+VE1MRnJhbWVTZXRFbGVtZW50OlcucUUsSFRNTE1hcnF1ZWVFbGVtZW50OlcucUUsSFRNTEVsZW1lbnQ6
+Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpXLkdoLEhUTUxBcmVhRWxlbWVudDpXLmZZLEhUTUxCYXNlRWxl
+bWVudDpXLm5CLEJsb2I6Vy5BeixIVE1MQm9keUVsZW1lbnQ6Vy5RUCxDREFUQVNlY3Rpb246Vy5ueCxD
+aGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54LFByb2Nlc3NpbmdJbnN0cnVjdGlvbjpXLm54LFRl
+eHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6Vy5vSixD
+U1MyUHJvcGVydGllczpXLm9KLFhNTERvY3VtZW50OlcuUUYsRG9jdW1lbnQ6Vy5RRixET01FeGNlcHRp
+b246Vy5OaCxET01SZWN0UmVhZE9ubHk6Vy5JQixET01Ub2tlbkxpc3Q6Vy5uNyxFbGVtZW50OlcuY3Ys
+QWJvcnRQYXltZW50RXZlbnQ6Vy5lYSxBbmltYXRpb25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXliYWNr
+RXZlbnQ6Vy5lYSxBcHBsaWNhdGlvbkNhY2hlRXJyb3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaENs
+aWNrRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZhaWxF
+dmVudDpXLmVhLEJhY2tncm91bmRGZXRjaGVkRXZlbnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZl
+bnQ6Vy5lYSxCZWZvcmVVbmxvYWRFdmVudDpXLmVhLEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXltZW50
+RXZlbnQ6Vy5lYSxDbGlwYm9hcmRFdmVudDpXLmVhLENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVudDpX
+LmVhLERldmljZU1vdGlvbkV2ZW50OlcuZWEsRGV2aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVycm9y
+RXZlbnQ6Vy5lYSxFeHRlbmRhYmxlRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OlcuZWEs
+RmV0Y2hFdmVudDpXLmVhLEZvbnRGYWNlU2V0TG9hZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZlbnQ6
+Vy5lYSxHYW1lcGFkRXZlbnQ6Vy5lYSxIYXNoQ2hhbmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6Vy5l
+YSxNZWRpYUVuY3J5cHRlZEV2ZW50OlcuZWEsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRpYVF1
+ZXJ5TGlzdEV2ZW50OlcuZWEsTWVkaWFTdHJlYW1FdmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tFdmVu
+dDpXLmVhLE1lc3NhZ2VFdmVudDpXLmVhLE1JRElDb25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVzc2Fn
+ZUV2ZW50OlcuZWEsTXV0YXRpb25FdmVudDpXLmVhLE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFnZVRy
+YW5zaXRpb25FdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVzdFVw
+ZGF0ZUV2ZW50OlcuZWEsUG9wU3RhdGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFp
+bGFibGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJvbWlz
+ZVJlamVjdGlvbkV2ZW50OlcuZWEsUHVzaEV2ZW50OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpXLmVh
+LFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6Vy5lYSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OlcuZWEs
+UlRDVHJhY2tFdmVudDpXLmVhLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5zb3JF
+cnJvckV2ZW50OlcuZWEsU3BlZWNoUmVjb2duaXRpb25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0aW9u
+RXZlbnQ6Vy5lYSxTcGVlY2hTeW50aGVzaXNFdmVudDpXLmVhLFN0b3JhZ2VFdmVudDpXLmVhLFN5bmNF
+dmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5lYSxUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxXZWJLaXRUcmFuc2l0
+aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2ZW50OlcuZWEsVlJEaXNwbGF5RXZlbnQ6Vy5lYSxWUlNlc3Np
+b25FdmVudDpXLmVhLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6Vy5lYSxVU0JDb25uZWN0aW9uRXZl
+bnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6Vy5lYSxBdWRpb1Byb2Nlc3NpbmdFdmVudDpXLmVh
+LE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDpXLmVhLFdlYkdMQ29udGV4dEV2ZW50OlcuZWEsRXZl
+bnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEsRXZlbnRUYXJnZXQ6Vy5EMCxGaWxlOlcuVDUsSFRNTEZvcm1F
+bGVtZW50OlcuaDQsSGlzdG9yeTpXLmJyLEhUTUxEb2N1bWVudDpXLlZiLFhNTEh0dHBSZXF1ZXN0Olcu
+TzcsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpXLndhLEltYWdlRGF0YTpXLlNnLExvY2F0aW9uOlcu
+dTgsTW91c2VFdmVudDpXLkFqLERyYWdFdmVudDpXLkFqLFBvaW50ZXJFdmVudDpXLkFqLFdoZWVsRXZl
+bnQ6Vy5BaixEb2N1bWVudEZyYWdtZW50OlcudUgsU2hhZG93Um9vdDpXLnVILERvY3VtZW50VHlwZTpX
+LnVILE5vZGU6Vy51SCxOb2RlTGlzdDpXLkJILFJhZGlvTm9kZUxpc3Q6Vy5CSCxQcm9ncmVzc0V2ZW50
+OlcuZXcsUmVzb3VyY2VQcm9ncmVzc0V2ZW50OlcuZXcsSFRNTFNlbGVjdEVsZW1lbnQ6Vy5scCxIVE1M
+VGFibGVFbGVtZW50OlcuVGIsSFRNTFRhYmxlUm93RWxlbWVudDpXLkl2LEhUTUxUYWJsZVNlY3Rpb25F
+bGVtZW50OlcuQlQsSFRNTFRlbXBsYXRlRWxlbWVudDpXLnlZLENvbXBvc2l0aW9uRXZlbnQ6Vy53NixG
+b2N1c0V2ZW50OlcudzYsS2V5Ym9hcmRFdmVudDpXLnc2LFRleHRFdmVudDpXLnc2LFRvdWNoRXZlbnQ6
+Vy53NixVSUV2ZW50OlcudzYsV2luZG93OlcuSzUsRE9NV2luZG93OlcuSzUsRGVkaWNhdGVkV29ya2Vy
+R2xvYmFsU2NvcGU6Vy5DbSxTZXJ2aWNlV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxTaGFyZWRXb3JrZXJH
+bG9iYWxTY29wZTpXLkNtLFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sQXR0cjpXLkNRLENsaWVudFJlY3Q6
+Vy53NCxET01SZWN0OlcudzQsTmFtZWROb2RlTWFwOlcucmgsTW96TmFtZWRBdHRyTWFwOlcucmgsSURC
+S2V5UmFuZ2U6UC5oRixTVkdTY3JpcHRFbGVtZW50OlAubmQsU1ZHQUVsZW1lbnQ6UC5kNSxTVkdBbmlt
+YXRlRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVNb3Rpb25FbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZVRyYW5z
+Zm9ybUVsZW1lbnQ6UC5kNSxTVkdBbmltYXRpb25FbGVtZW50OlAuZDUsU1ZHQ2lyY2xlRWxlbWVudDpQ
+LmQ1LFNWR0NsaXBQYXRoRWxlbWVudDpQLmQ1LFNWR0RlZnNFbGVtZW50OlAuZDUsU1ZHRGVzY0VsZW1l
+bnQ6UC5kNSxTVkdEaXNjYXJkRWxlbWVudDpQLmQ1LFNWR0VsbGlwc2VFbGVtZW50OlAuZDUsU1ZHRkVC
+bGVuZEVsZW1lbnQ6UC5kNSxTVkdGRUNvbG9yTWF0cml4RWxlbWVudDpQLmQ1LFNWR0ZFQ29tcG9uZW50
+VHJhbnNmZXJFbGVtZW50OlAuZDUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OlAuZDUsU1ZHRkVDb252b2x2
+ZU1hdHJpeEVsZW1lbnQ6UC5kNSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6UC5kNSxTVkdGRURp
+c3BsYWNlbWVudE1hcEVsZW1lbnQ6UC5kNSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdG
+RUZsb29kRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0FFbGVtZW50OlAuZDUsU1ZHRkVGdW5jQkVsZW1lbnQ6
+UC5kNSxTVkdGRUZ1bmNHRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY1JFbGVtZW50OlAuZDUsU1ZHRkVHYXVz
+c2lhbkJsdXJFbGVtZW50OlAuZDUsU1ZHRkVJbWFnZUVsZW1lbnQ6UC5kNSxTVkdGRU1lcmdlRWxlbWVu
+dDpQLmQ1LFNWR0ZFTWVyZ2VOb2RlRWxlbWVudDpQLmQ1LFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6UC5k
+NSxTVkdGRU9mZnNldEVsZW1lbnQ6UC5kNSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVT
+cGVjdWxhckxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZFU3BvdExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZF
+VGlsZUVsZW1lbnQ6UC5kNSxTVkdGRVR1cmJ1bGVuY2VFbGVtZW50OlAuZDUsU1ZHRmlsdGVyRWxlbWVu
+dDpQLmQ1LFNWR0ZvcmVpZ25PYmplY3RFbGVtZW50OlAuZDUsU1ZHR0VsZW1lbnQ6UC5kNSxTVkdHZW9t
+ZXRyeUVsZW1lbnQ6UC5kNSxTVkdHcmFwaGljc0VsZW1lbnQ6UC5kNSxTVkdJbWFnZUVsZW1lbnQ6UC5k
+NSxTVkdMaW5lRWxlbWVudDpQLmQ1LFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDpQLmQ1LFNWR01hcmtl
+ckVsZW1lbnQ6UC5kNSxTVkdNYXNrRWxlbWVudDpQLmQ1LFNWR01ldGFkYXRhRWxlbWVudDpQLmQ1LFNW
+R1BhdGhFbGVtZW50OlAuZDUsU1ZHUGF0dGVybkVsZW1lbnQ6UC5kNSxTVkdQb2x5Z29uRWxlbWVudDpQ
+LmQ1LFNWR1BvbHlsaW5lRWxlbWVudDpQLmQ1LFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDpQLmQ1LFNW
+R1JlY3RFbGVtZW50OlAuZDUsU1ZHU2V0RWxlbWVudDpQLmQ1LFNWR1N0b3BFbGVtZW50OlAuZDUsU1ZH
+U3R5bGVFbGVtZW50OlAuZDUsU1ZHU1ZHRWxlbWVudDpQLmQ1LFNWR1N3aXRjaEVsZW1lbnQ6UC5kNSxT
+VkdTeW1ib2xFbGVtZW50OlAuZDUsU1ZHVFNwYW5FbGVtZW50OlAuZDUsU1ZHVGV4dENvbnRlbnRFbGVt
+ZW50OlAuZDUsU1ZHVGV4dEVsZW1lbnQ6UC5kNSxTVkdUZXh0UGF0aEVsZW1lbnQ6UC5kNSxTVkdUZXh0
+UG9zaXRpb25pbmdFbGVtZW50OlAuZDUsU1ZHVGl0bGVFbGVtZW50OlAuZDUsU1ZHVXNlRWxlbWVudDpQ
+LmQ1LFNWR1ZpZXdFbGVtZW50OlAuZDUsU1ZHR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHQ29tcG9uZW50
+VHJhbnNmZXJGdW5jdGlvbkVsZW1lbnQ6UC5kNSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OlAuZDUsU1ZH
+TVBhdGhFbGVtZW50OlAuZDUsU1ZHRWxlbWVudDpQLmQ1fSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVM
+ZWFmVGFncyh7RE9NRXJyb3I6dHJ1ZSxET01JbXBsZW1lbnRhdGlvbjp0cnVlLE1lZGlhRXJyb3I6dHJ1
+ZSxOYXZpZ2F0b3I6dHJ1ZSxOYXZpZ2F0b3JDb25jdXJyZW50SGFyZHdhcmU6dHJ1ZSxOYXZpZ2F0b3JV
+c2VyTWVkaWFFcnJvcjp0cnVlLE92ZXJjb25zdHJhaW5lZEVycm9yOnRydWUsUG9zaXRpb25FcnJvcjp0
+cnVlLFJhbmdlOnRydWUsU1FMRXJyb3I6dHJ1ZSxEYXRhVmlldzp0cnVlLEFycmF5QnVmZmVyVmlldzpm
+YWxzZSxGbG9hdDMyQXJyYXk6dHJ1ZSxGbG9hdDY0QXJyYXk6dHJ1ZSxJbnQxNkFycmF5OnRydWUsSW50
+MzJBcnJheTp0cnVlLEludDhBcnJheTp0cnVlLFVpbnQxNkFycmF5OnRydWUsVWludDMyQXJyYXk6dHJ1
+ZSxVaW50OENsYW1wZWRBcnJheTp0cnVlLENhbnZhc1BpeGVsQXJyYXk6dHJ1ZSxVaW50OEFycmF5OmZh
+bHNlLEhUTUxBdWRpb0VsZW1lbnQ6dHJ1ZSxIVE1MQlJFbGVtZW50OnRydWUsSFRNTEJ1dHRvbkVsZW1l
+bnQ6dHJ1ZSxIVE1MQ2FudmFzRWxlbWVudDp0cnVlLEhUTUxDb250ZW50RWxlbWVudDp0cnVlLEhUTUxE
+TGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUVsZW1lbnQ6dHJ1ZSxIVE1MRGF0YUxpc3RFbGVtZW50OnRy
+dWUsSFRNTERldGFpbHNFbGVtZW50OnRydWUsSFRNTERpYWxvZ0VsZW1lbnQ6dHJ1ZSxIVE1MRGl2RWxl
+bWVudDp0cnVlLEhUTUxFbWJlZEVsZW1lbnQ6dHJ1ZSxIVE1MRmllbGRTZXRFbGVtZW50OnRydWUsSFRN
+TEhSRWxlbWVudDp0cnVlLEhUTUxIZWFkRWxlbWVudDp0cnVlLEhUTUxIZWFkaW5nRWxlbWVudDp0cnVl
+LEhUTUxIdG1sRWxlbWVudDp0cnVlLEhUTUxJRnJhbWVFbGVtZW50OnRydWUsSFRNTEltYWdlRWxlbWVu
+dDp0cnVlLEhUTUxJbnB1dEVsZW1lbnQ6dHJ1ZSxIVE1MTElFbGVtZW50OnRydWUsSFRNTExhYmVsRWxl
+bWVudDp0cnVlLEhUTUxMZWdlbmRFbGVtZW50OnRydWUsSFRNTExpbmtFbGVtZW50OnRydWUsSFRNTE1h
+cEVsZW1lbnQ6dHJ1ZSxIVE1MTWVkaWFFbGVtZW50OnRydWUsSFRNTE1lbnVFbGVtZW50OnRydWUsSFRN
+TE1ldGFFbGVtZW50OnRydWUsSFRNTE1ldGVyRWxlbWVudDp0cnVlLEhUTUxNb2RFbGVtZW50OnRydWUs
+SFRNTE9MaXN0RWxlbWVudDp0cnVlLEhUTUxPYmplY3RFbGVtZW50OnRydWUsSFRNTE9wdEdyb3VwRWxl
+bWVudDp0cnVlLEhUTUxPcHRpb25FbGVtZW50OnRydWUsSFRNTE91dHB1dEVsZW1lbnQ6dHJ1ZSxIVE1M
+UGFyYWdyYXBoRWxlbWVudDp0cnVlLEhUTUxQYXJhbUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1l
+bnQ6dHJ1ZSxIVE1MUHJlRWxlbWVudDp0cnVlLEhUTUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVv
+dGVFbGVtZW50OnRydWUsSFRNTFNjcmlwdEVsZW1lbnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVl
+LEhUTUxTbG90RWxlbWVudDp0cnVlLEhUTUxTb3VyY2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50
+OnRydWUsSFRNTFN0eWxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRN
+TFRhYmxlQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFi
+bGVIZWFkZXJDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFy
+ZWFFbGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhU
+TUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50
+OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhUTUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZv
+bnRFbGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1
+ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVu
+dDp0cnVlLEhUTUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2Us
+SFRNTEJvZHlFbGVtZW50OnRydWUsQ0RBVEFTZWN0aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENv
+bW1lbnQ6dHJ1ZSxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNs
+YXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxY
+TUxEb2N1bWVudDp0cnVlLERvY3VtZW50OmZhbHNlLERPTUV4Y2VwdGlvbjp0cnVlLERPTVJlY3RSZWFk
+T25seTpmYWxzZSxET01Ub2tlbkxpc3Q6dHJ1ZSxFbGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50
+OnRydWUsQW5pbWF0aW9uRXZlbnQ6dHJ1ZSxBbmltYXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGlj
+YXRpb25DYWNoZUVycm9yRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFj
+a2dyb3VuZEZldGNoRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3Jv
+dW5kRmV0Y2hlZEV2ZW50OnRydWUsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5s
+b2FkRXZlbnQ6dHJ1ZSxCbG9iRXZlbnQ6dHJ1ZSxDYW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJv
+YXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2ZW50OnRydWUsQ3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25F
+dmVudDp0cnVlLERldmljZU9yaWVudGF0aW9uRXZlbnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5k
+YWJsZUV2ZW50OnRydWUsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxG
+b250RmFjZVNldExvYWRFdmVudDp0cnVlLEZvcmVpZ25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50
+OnRydWUsSGFzaENoYW5nZUV2ZW50OnRydWUsSW5zdGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRF
+dmVudDp0cnVlLE1lZGlhS2V5TWVzc2FnZUV2ZW50OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVl
+LE1lZGlhU3RyZWFtRXZlbnQ6dHJ1ZSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZl
+bnQ6dHJ1ZSxNSURJQ29ubmVjdGlvbkV2ZW50OnRydWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0
+aW9uRXZlbnQ6dHJ1ZSxOb3RpZmljYXRpb25FdmVudDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1
+ZSxQYXltZW50UmVxdWVzdEV2ZW50OnRydWUsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBv
+cFN0YXRlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQ
+cmVzZW50YXRpb25Db25uZWN0aW9uQ2xvc2VFdmVudDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0
+cnVlLFB1c2hFdmVudDp0cnVlLFJUQ0RhdGFDaGFubmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5n
+ZUV2ZW50OnRydWUsUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1
+ZSxTZWN1cml0eVBvbGljeVZpb2xhdGlvbkV2ZW50OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNw
+ZWVjaFJlY29nbml0aW9uRXJyb3I6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNo
+U3ludGhlc2lzRXZlbnQ6dHJ1ZSxTdG9yYWdlRXZlbnQ6dHJ1ZSxTeW5jRXZlbnQ6dHJ1ZSxUcmFja0V2
+ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50OnRydWUsV2ViS2l0VHJhbnNpdGlvbkV2ZW50OnRydWUsVlJE
+ZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxheUV2ZW50OnRydWUsVlJTZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pv
+SW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRydWUsVVNCQ29ubmVjdGlvbkV2ZW50OnRydWUsSURCVmVyc2lv
+bkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6dHJ1ZSxPZmZsaW5lQXVkaW9Db21w
+bGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENvbnRleHRFdmVudDp0cnVlLEV2ZW50OmZhbHNlLElucHV0RXZl
+bnQ6ZmFsc2UsRXZlbnRUYXJnZXQ6ZmFsc2UsRmlsZTp0cnVlLEhUTUxGb3JtRWxlbWVudDp0cnVlLEhp
+c3Rvcnk6dHJ1ZSxIVE1MRG9jdW1lbnQ6dHJ1ZSxYTUxIdHRwUmVxdWVzdDp0cnVlLFhNTEh0dHBSZXF1
+ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRhOnRydWUsTG9jYXRpb246dHJ1ZSxNb3VzZUV2ZW50
+OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9pbnRlckV2ZW50OnRydWUsV2hlZWxFdmVudDp0cnVlLERvY3Vt
+ZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dSb290OnRydWUsRG9jdW1lbnRUeXBlOnRydWUsTm9kZTpmYWxz
+ZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9kZUxpc3Q6dHJ1ZSxQcm9ncmVzc0V2ZW50OnRydWUsUmVzb3Vy
+Y2VQcm9ncmVzc0V2ZW50OnRydWUsSFRNTFNlbGVjdEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVFbGVtZW50
+OnRydWUsSFRNTFRhYmxlUm93RWxlbWVudDp0cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRydWUs
+SFRNTFRlbXBsYXRlRWxlbWVudDp0cnVlLENvbXBvc2l0aW9uRXZlbnQ6dHJ1ZSxGb2N1c0V2ZW50OnRy
+dWUsS2V5Ym9hcmRFdmVudDp0cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1ZSxVSUV2ZW50
+OmZhbHNlLFdpbmRvdzp0cnVlLERPTVdpbmRvdzp0cnVlLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3Bl
+OnRydWUsU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6
+dHJ1ZSxXb3JrZXJHbG9iYWxTY29wZTp0cnVlLEF0dHI6dHJ1ZSxDbGllbnRSZWN0OnRydWUsRE9NUmVj
+dDp0cnVlLE5hbWVkTm9kZU1hcDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLElEQktleVJhbmdlOnRy
+dWUsU1ZHU2NyaXB0RWxlbWVudDp0cnVlLFNWR0FFbGVtZW50OnRydWUsU1ZHQW5pbWF0ZUVsZW1lbnQ6
+dHJ1ZSxTVkdBbmltYXRlTW90aW9uRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50
+OnRydWUsU1ZHQW5pbWF0aW9uRWxlbWVudDp0cnVlLFNWR0NpcmNsZUVsZW1lbnQ6dHJ1ZSxTVkdDbGlw
+UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdEZWZzRWxlbWVudDp0cnVlLFNWR0Rlc2NFbGVtZW50OnRydWUsU1ZH
+RGlzY2FyZEVsZW1lbnQ6dHJ1ZSxTVkdFbGxpcHNlRWxlbWVudDp0cnVlLFNWR0ZFQmxlbmRFbGVtZW50
+OnRydWUsU1ZHRkVDb2xvck1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxl
+bWVudDp0cnVlLFNWR0ZFQ29tcG9zaXRlRWxlbWVudDp0cnVlLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVt
+ZW50OnRydWUsU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVEaXNwbGFjZW1lbnRN
+YXBFbGVtZW50OnRydWUsU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVGbG9vZEVsZW1l
+bnQ6dHJ1ZSxTVkdGRUZ1bmNBRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0JFbGVtZW50OnRydWUsU1ZHRkVG
+dW5jR0VsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNSRWxlbWVudDp0cnVlLFNWR0ZFR2F1c3NpYW5CbHVyRWxl
+bWVudDp0cnVlLFNWR0ZFSW1hZ2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZUVsZW1lbnQ6dHJ1ZSxTVkdG
+RU1lcmdlTm9kZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OnRydWUsU1ZHRkVPZmZz
+ZXRFbGVtZW50OnRydWUsU1ZHRkVQb2ludExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFU3BlY3VsYXJMaWdo
+dGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVRpbGVFbGVtZW50
+OnRydWUsU1ZHRkVUdXJidWxlbmNlRWxlbWVudDp0cnVlLFNWR0ZpbHRlckVsZW1lbnQ6dHJ1ZSxTVkdG
+b3JlaWduT2JqZWN0RWxlbWVudDp0cnVlLFNWR0dFbGVtZW50OnRydWUsU1ZHR2VvbWV0cnlFbGVtZW50
+OnRydWUsU1ZHR3JhcGhpY3NFbGVtZW50OnRydWUsU1ZHSW1hZ2VFbGVtZW50OnRydWUsU1ZHTGluZUVs
+ZW1lbnQ6dHJ1ZSxTVkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdNYXJrZXJFbGVtZW50OnRy
+dWUsU1ZHTWFza0VsZW1lbnQ6dHJ1ZSxTVkdNZXRhZGF0YUVsZW1lbnQ6dHJ1ZSxTVkdQYXRoRWxlbWVu
+dDp0cnVlLFNWR1BhdHRlcm5FbGVtZW50OnRydWUsU1ZHUG9seWdvbkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5
+bGluZUVsZW1lbnQ6dHJ1ZSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdSZWN0RWxlbWVu
+dDp0cnVlLFNWR1NldEVsZW1lbnQ6dHJ1ZSxTVkdTdG9wRWxlbWVudDp0cnVlLFNWR1N0eWxlRWxlbWVu
+dDp0cnVlLFNWR1NWR0VsZW1lbnQ6dHJ1ZSxTVkdTd2l0Y2hFbGVtZW50OnRydWUsU1ZHU3ltYm9sRWxl
+bWVudDp0cnVlLFNWR1RTcGFuRWxlbWVudDp0cnVlLFNWR1RleHRDb250ZW50RWxlbWVudDp0cnVlLFNW
+R1RleHRFbGVtZW50OnRydWUsU1ZHVGV4dFBhdGhFbGVtZW50OnRydWUsU1ZHVGV4dFBvc2l0aW9uaW5n
+RWxlbWVudDp0cnVlLFNWR1RpdGxlRWxlbWVudDp0cnVlLFNWR1VzZUVsZW1lbnQ6dHJ1ZSxTVkdWaWV3
+RWxlbWVudDp0cnVlLFNWR0dyYWRpZW50RWxlbWVudDp0cnVlLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVu
+Y3Rpb25FbGVtZW50OnRydWUsU1ZHRkVEcm9wU2hhZG93RWxlbWVudDp0cnVlLFNWR01QYXRoRWxlbWVu
+dDp0cnVlLFNWR0VsZW1lbnQ6ZmFsc2V9KQpILmIwLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1
+ZmZlclZpZXciCkguUkcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5WUC4k
+bmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILkRnLiRuYXRpdmVTdXBlcmNsYXNz
+VGFnPSJBcnJheUJ1ZmZlclZpZXciCkguV0IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVy
+VmlldyIKSC5aRy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlBnLiRuYXRp
+dmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXcifSkoKQpjb252ZXJ0QWxsVG9GYXN0T2JqZWN0
+KHcpCmNvbnZlcnRUb0Zhc3RPYmplY3QoJCk7KGZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBkb2N1bWVudD09
+PSJ1bmRlZmluZWQiKXthKG51bGwpCnJldHVybn1pZih0eXBlb2YgZG9jdW1lbnQuY3VycmVudFNjcmlw
+dCE9J3VuZGVmaW5lZCcpe2EoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkKcmV0dXJufXZhciB0PWRvY3Vt
+ZW50LnNjcmlwdHMKZnVuY3Rpb24gb25Mb2FkKGIpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7KytyKXRb
+cl0ucmVtb3ZlRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKQphKGIudGFyZ2V0KX1mb3Io
+dmFyIHM9MDtzPHQubGVuZ3RoOysrcyl0W3NdLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxm
+YWxzZSl9KShmdW5jdGlvbihhKXt2LmN1cnJlbnRTY3JpcHQ9YQppZih0eXBlb2YgZGFydE1haW5SdW5u
+ZXI9PT0iZnVuY3Rpb24iKWRhcnRNYWluUnVubmVyKEwuSXEsW10pCmVsc2UgTC5JcShbXSl9KX0pKCkK
+Ly8jIHNvdXJjZU1hcHBpbmdVUkw9bWlncmF0aW9uLmpzLm1hcAo=
 ''';
 
 String _migration_css;
-// migration_css md5 is 'f17223177bb502d5077cd5157c4d0b38'
+// migration_css md5 is '503fdb394c9ab5438c2ba2c12a0be0cb'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
 ZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgKi8KLyogQlNELXN0eWxlIGxpY2Vu
 c2UgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZS4gICAgICAgICAgICAgICAgICAg
-Ki8KCmJvZHkgewogIGJhY2tncm91bmQtY29sb3I6IGJsYWNrOwogIGNvbG9yOiB3aGl0ZTsKICBmb250
-LWZhbWlseTogJ09wZW4gU2FucycsIHNhbnMtc2VyaWY7CiAgbWFyZ2luOiAwOwogIHBhZGRpbmc6IDA7
-Cn0KCmgxIHsKICBmb250LXNpemU6IDIuNGVtOwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgbWFyZ2luOiA4
-cHggOHB4IDAgOHB4Owp9CgpoMiN1bml0LW5hbWUgewogIGZvbnQtc2l6ZTogMS4yZW07CiAgZm9udC13
-ZWlnaHQ6IDYwMDsKICBtYXJnaW46IDhweCA4cHggMCA4cHg7Cn0KCi5ob3Jpem9udGFsIHsKICBkaXNw
-bGF5OiBmbGV4Owp9CgoucGFuZWwtaGVhZGluZyB7CiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2Vp
-Z2h0OiA2MDA7CiAgbWFyZ2luLXRvcDogMDsKICBwYWRkaW5nOiA3cHggN3B4IDAgN3B4Owp9CgoubmF2
-LWxpbmssIC5yZWdpb24gewogIGN1cnNvcjogcG9pbnRlcjsKfQoKLm5hdi1wYW5lbCB7CiAgYmFja2dy
-b3VuZC1jb2xvcjogIzI4MmIyZTsKICBmbGV4OiAxIDEgMjcwcHg7CiAgZm9udC1zaXplOiAxNHB4Owog
-IC8qIDEwcHggdG8gbWF0Y2ggZXhhY3QgdG9wIG1hcmdpbiBvZiAuY29udGVudC4KICAgKiAwLjhlbSB0
-byBwYWlyIHdpdGggdGhlIC0wLjVlbSBtYXJnaW4gb2YgLmNvbnRlbnQsIHByb2R1Y2luZyBhIG5ldCBt
-YXJnaW4KICAgKiBiZXR3ZWVuIHRoZSB0d28gb2YgMC4zZW0uCiAgICovCiAgbWFyZ2luOiAxMHB4IDAu
-OGVtIDAgMDsKfQoKLm5hdi1pbm5lciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBvdmVy
-ZmxvdzogYXV0bzsKICBwYWRkaW5nOiAwIDAgN3B4IDdweDsKfQoKLmZpeGVkIHsKICBwb3NpdGlvbjog
-Zml4ZWQ7CiAgdG9wOiAwOwp9CgoubmF2LWlubmVyIC5yb290IHsKICBtYXJnaW46IDA7Cn0KCi5uYXYt
-aW5uZXIgdWwgewogIHBhZGRpbmctbGVmdDogMTJweDsKfQoubmF2LWlubmVyID4gdWwgewogIHBhZGRp
-bmctbGVmdDogMDsKICBtYXJnaW4tdG9wOiAwOwp9CgoubmF2LWlubmVyIGxpIHsKICBsaXN0LXN0eWxl
-LXR5cGU6IG5vbmU7Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIHsKICBtYXJnaW4tbGVmdDogNXB4Owp9Cgou
+Ki8KCmJvZHkgewogIGJhY2tncm91bmQtY29sb3I6ICMxMjIwMmY7CiAgY29sb3I6ICNjY2M7CiAgZm9u
+dC1mYW1pbHk6ICJSb2JvdG8iLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTRweDsKICBkaXNwbGF5
+OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgcG9zaXRpb246IGFic29sdXRlOwogIHRv
+cDogMDsKICByaWdodDogMDsKICBib3R0b206IDA7CiAgbGVmdDogMDsKICBtYXJnaW46IDA7CiAgcGFk
+ZGluZzogMDsKICBvdmVyZmxvdzogaGlkZGVuOwp9CgpoZWFkZXIgewogIGJhY2tncm91bmQtY29sb3I6
+ICMxYzI4MzQ7CiAgaGVpZ2h0OiA0OHB4OwogIHBhZGRpbmctbGVmdDogMjRweDsKICBhbGlnbi1pdGVt
+czogY2VudGVyOwogIHotaW5kZXg6IDQ7Cn0KCmhlYWRlciBoMSwKaGVhZGVyIGgyIHsKICBkaXNwbGF5
+OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1mYW1pbHk6ICJHb29nbGUgU2FucyIsIlJvYm90byIsc2Fucy1z
+ZXJpZjsKICBmb250LXdlaWdodDogNDAwOwogIG1hcmdpbi1yaWdodDogMjRweDsKfQoKaDEgewogIGZv
+bnQtc2l6ZTogMS41ZW07Cn0KCmhlYWRlciBoMiB7CiAgZm9udC1zaXplOiAxLjJlbTsKfQoKZm9vdGVy
+IHsKICBjb2xvcjogI2NjYzsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjczMjNhOwogIGRpc3BsYXk6IGZs
+ZXg7CiAgZmxleC1kaXJlY3Rpb246IHJvdzsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIHBhZGRpbmc6
+IDhweCAyNHB4Owp9Cgpmb290ZXIgLndpZGUgewogIGZsZXg6IDE7Cn0KCi5ob3Jpem9udGFsIHsKICBk
+aXNwbGF5OiBmbGV4Owp9CgoucGFuZWxzIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTIxYTI1OwogIGZs
+ZXg6IDE7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLnBhbmVsLWhlYWRpbmcgewogIGZvbnQtZmFtaWx5
+OiAiUm9ib3RvIE1vbm8iLCBtb25vc3BhY2U7CiAgZm9udC1zaXplOiAxMnB4OwogIGNvbG9yOiBncmF5
+OwogIG1hcmdpbjogOHB4Owp9CgoubmF2LWxpbmssCi5yZWdpb24gewogIGN1cnNvcjogcG9pbnRlcjsK
+fQoKLm5hdi1wYW5lbCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBmbGV4OiAxIDIwMHB4
+OwogIG1hcmdpbjogMDsKICBvdmVyZmxvdzogc2Nyb2xsOwp9CgoubmF2LWlubmVyIHsKICBwYWRkaW5n
+OiAwIDAgN3B4IDdweDsKfQoKLmZpeGVkIHsKICBwb3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAwOwp9Cgou
+cm9vdCB7CiAgbWFyZ2luOiAwOwogIGRpc3BsYXk6IG5vbmU7Cn0KCi5uYXYtdHJlZSA+IHVsIHsKICBw
+YWRkaW5nLWxlZnQ6IDZweDsKfQoKLm5hdi1pbm5lciB1bCB7CiAgcGFkZGluZy1sZWZ0OiAxMnB4Owog
+IG1hcmdpbjogMDsKfQoKLm5hdi1pbm5lciBsaSB7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwp9Cgou
 bmF2LWlubmVyIGxpOm5vdCguZGlyKSB7CiAgbWFyZ2luLWxlZnQ6IDIwcHg7CiAgbWFyZ2luLWJvdHRv
 bTogM3B4Owp9CgoubmF2LWlubmVyIGxpLmRpciAuYXJyb3cgewogIGN1cnNvcjogcG9pbnRlcjsKICBk
 aXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1zaXplOiAxMHB4OwogIG1hcmdpbi1yaWdodDogNHB4
@@ -3297,61 +3686,61 @@
 ciAuYXJyb3cuY29sbGFwc2VkIHsKICB0cmFuc2Zvcm06IHJvdGF0ZSgtOTBkZWcpOwp9CgoubmF2LWlu
 bmVyIHVsIHsKICBtYXgtaGVpZ2h0OiAyMDAwcHg7CiAgdHJhbnNpdGlvbjogbWF4LWhlaWdodCAwLjVz
 IGVhc2Utb3V0Owp9CgoubmF2LWlubmVyIHVsLmNvbGxhcHNlZCB7CiAgbWF4LWhlaWdodDogMCAhaW1w
-b3J0YW50OwogIG92ZXJmbG93OiBoaWRkZW47Cn0KCi5uYXYtaW5uZXIgLm5hdi1saW5rIHsKICBjb2xv
-cjogIzMzY2NmZjsKfQoKLm5hdi1pbm5lciAuc2VsZWN0ZWQtZmlsZSB7CiAgY29sb3I6IHdoaXRlOwog
-IGN1cnNvcjogaW5oZXJpdDsKICBmb250LXdlaWdodDogNjAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9u
-ZTsKfQoKLmVkaXQtY291bnQgewogIGJhY2tncm91bmQtY29sb3I6ICNjY2NjMDA7CiAgYm9yZGVyLXJh
-ZGl1czogMTVweDsKICBjb2xvcjogIzAwMDAwMDsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9u
-dC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgbWFyZ2luLWxlZnQ6IDVweDsKICBtaW4t
-d2lkdGg6IDI1cHg7CiAgcGFkZGluZzogNXB4IDA7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgouY29u
-dGVudCB7CiAgZmxleDogMCAxIGF1dG87CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICAvKioKICAg
-KiBMZWZ0IG1hcmdpbiBvZmZzZXRzIHRoZSBtYXJnaW4gaW50cm9kdWNlZCBieSB0aGUgYWJzb2x1dGVs
-eSBwb3NpdGlvbmVkCiAgICogY2hpbGQgZGl2LgogICAqLwogIG1hcmdpbjogMTBweCAxMHB4IDEwcHgg
-LTAuNWVtOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB3aGl0ZS1zcGFjZTogcHJlOwp9CgouY29kZSB7
-CiAgbGVmdDogMC41ZW07CiAgLyogSW5jcmVhc2UgbGluZSBoZWlnaHQgdG8gbWFrZSByb29tIGZvciBi
-b3JkZXJzIGluIG5vbi1udWxsYWJsZSB0eXBlCiAgICogcmVnaW9ucy4KICAgKi8KICBsaW5lLWhlaWdo
-dDogMS4zOwogIG1pbi1oZWlnaHQ6IDYwMHB4OwogIHBhZGRpbmctbGVmdDogNjJweDsKICBwb3NpdGlv
-bjogaW5oZXJpdDsKICB6LWluZGV4OiAxMDA7Cn0KCi5jb2RlLmhsanMgewogIGJhY2tncm91bmQtY29s
-b3I6IGluaGVyaXQ7Cn0KCi5jb2RlIC53ZWxjb21lIHsKICBmb250LWZhbWlseTogJ09wZW4gU2Fucycs
-IHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxOHB4OwogIG1hcmdpbi1yaWdodDogNjJweDsKfQoKLmNv
-ZGUgLm5hdi1saW5rIHsKICBjb2xvcjogaW5oZXJpdDsKICB0ZXh0LWRlY29yYXRpb24tbGluZTogbm9u
-ZTsKfQoKLmNvZGUgLm5hdi1saW5rOnZpc2l0ZWQgewogIGNvbG9yOiBpbmhlcml0OwogIHRleHQtZGVj
-b3JhdGlvbi1saW5lOiBub25lOwp9CgouY29kZSAubmF2LWxpbms6aG92ZXIgewogIHRleHQtZGVjb3Jh
-dGlvbi1saW5lOiB1bmRlcmxpbmU7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKLnJlZ2lvbnMgewogIGJh
-Y2tncm91bmQtY29sb3I6ICMyODJiMmU7CiAgcGFkZGluZzogMC41ZW0gMCAwLjVlbSAwLjVlbTsKICBw
-b3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMC41ZW07CiAgdG9wOiAwOwp9CgoucmVnaW9ucyB0YWJs
-ZSB7CiAgYm9yZGVyLXNwYWNpbmc6IDA7Cn0KCi5yZWdpb25zIHRkIHsKICBib3JkZXI6IG5vbmU7CiAg
-LyogVGhlIGNvbnRlbnQgb2YgdGhlIHJlZ2lvbnMgaXMgbm90IHZpc2libGU7IHRoZSB1c2VyIGluc3Rl
-YWQgd2lsbCBzZWUgdGhlCiAgICogaGlnaGxpZ2h0ZWQgY29weSBvZiB0aGUgY29udGVudC4gKi8KICBj
-b2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwKTsKICBsaW5lLWhlaWdodDogMS4zOwogIHBhZGRpbmc6
-IDA7CiAgd2hpdGUtc3BhY2U6IHByZTsKfQoKLnJlZ2lvbnMgdGQ6ZW1wdHk6YWZ0ZXIgewogIGNvbnRl
-bnQ6ICJcMDBhMCI7Cn0KCi5yZWdpb25zIHRyLmhpZ2hsaWdodCB0ZDpsYXN0LWNoaWxkIHsKICBiYWNr
-Z3JvdW5kLWNvbG9yOiAjNDQ0NDQ0Owp9CgoucmVnaW9ucyB0ZC5saW5lLW5vIHsKICBib3JkZXItcmln
-aHQ6IHNvbGlkICMyODJiMmUgMnB4OwogIGNvbG9yOiAjOTk5OTk5OwogIGRpc3BsYXk6IGlubGluZS1i
-bG9jazsKICBwYWRkaW5nLXJpZ2h0OiA0cHg7CiAgdGV4dC1hbGlnbjogcmlnaHQ7CiAgdmlzaWJpbGl0
-eTogdmlzaWJsZTsKICB3aWR0aDogNTBweDsKfQoKLnJlZ2lvbnMgdHIuaGlnaGxpZ2h0IHRkLmxpbmUt
-bm8gewogIGJvcmRlci1yaWdodDogc29saWQgI2NjY2NjYyAycHg7Cn0KCi5yZWdpb24gewogIGRpc3Bs
-YXk6IGlubGluZS1ibG9jazsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdmlzaWJpbGl0eTogdmlzaWJs
-ZTsKICB6LWluZGV4OiAyMDA7Cn0KCi5yZWdpb24uYWRkZWQtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNv
-bG9yOiAjY2NmZmNjOwogIGNvbG9yOiAjMDAzMzAwOwp9CgoucmVnaW9uLnJlbW92ZWQtcmVnaW9uIHsK
-ICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2NjY2OwogIGNvbG9yOiAjMDAxMTAwOwp9CgoucmVnaW9uLnVu
-Y2hhbmdlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC4zKTsKICBi
-b3JkZXItYm90dG9tOiBzb2xpZCAycHggI2NjY2NjYzsKICAvKiBJbnZpc2libGUgdGV4dDsgdXNlIHVu
-ZGVybHlpbmcgaGlnaGxpZ2h0aW5nLiAqLwogIGNvbG9yOiByZ2JhKDAsIDAsIDAsIDApOwogIC8qIFJl
-ZHVjZSBsaW5lIGhlaWdodCB0byBtYWtlIHJvb20gZm9yIGJvcmRlci4gKi8KICBsaW5lLWhlaWdodDog
-MTsKfQoKLnRhcmdldCB7CiAgYmFja2dyb3VuZC1jb2xvcjogI0ZGRkY5OTsKICBjb2xvcjogYmxhY2s7
-CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHZpc2liaWxpdHk6IHZpc2libGU7Cn0KCi5pbmZvLXBhbmVs
-IHsKICBmbGV4OiAxIDEgMjcwcHg7CiAgZm9udC1zaXplOiAxNHB4OwogIG1hcmdpbjogMTBweCAwOwp9
-CgouaW5mby1wYW5lbCAuZWRpdC1wYW5lbCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBv
-dmVyZmxvdzogYXV0bzsKfQoKLmluZm8tcGFuZWwgLnBhbmVsLWNvbnRlbnQgewogIGZvbnQtc2l6ZTog
-MTNweDsKICBwYWRkaW5nOiA3cHg7Cn0KCi5pbmZvLXBhbmVsIC5wYW5lbC1jb250ZW50ID4gOmZpcnN0
-LWNoaWxkIHsKICBtYXJnaW4tdG9wOiAwOwp9CgouaW5mby1wYW5lbCAucmVnaW9uLWxvY2F0aW9uIHsK
-ICBwYWRkaW5nLWxlZnQ6IDEycHg7CiAgdGV4dC1pbmRlbnQ6IC0xMnB4Owp9CgouaW5mby1wYW5lbCAu
-bm93cmFwIHsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwp9CgouaW5mby1wYW5lbCB1bCwKLmluZm8tcGFu
-ZWwgb2wgewogIHBhZGRpbmctbGVmdDogMjBweDsKfQoKLmluZm8tcGFuZWwgYSB7CiAgY29sb3I6ICMz
-M2NjZmY7Cn0KCi5pbmZvLXBhbmVsIC5lZGl0LWxpc3QgewogIGJhY2tncm91bmQtY29sb3I6ICMyODJi
-MmU7CiAgbWFyZ2luLXRvcDogMTJweDsKICBvdmVyZmxvdzogYXV0bzsKfQoKLmVkaXQtbGlzdCAuZWRp
-dCB7CiAgbWFyZ2luOiAzcHggMDsKICBwYWRkaW5nLWxlZnQ6IDIxcHg7CiAgdGV4dC1pbmRlbnQ6IC0y
-MXB4Owp9CgouZWRpdC1saXN0IC5lZGl0LWxpbmsgewogIGN1cnNvcjogcG9pbnRlcjsKfQoKLmZvb3Rl
-ciB7CiAgcGFkZGluZzogOHB4IDhweCAxMDBweCA4cHg7Cn0K
+b3J0YW50OwogIG92ZXJmbG93OiBoaWRkZW47Cn0KCi5uYXYtaW5uZXIgLnNlbGVjdGVkLWZpbGUgewog
+IGNvbG9yOiB3aGl0ZTsKICBjdXJzb3I6IGluaGVyaXQ7CiAgZm9udC13ZWlnaHQ6IDYwMDsKICB0ZXh0
+LWRlY29yYXRpb246IG5vbmU7Cn0KCi5lZGl0LWNvdW50IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzdh
+ZWRjOwogIGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgY29sb3I6ICMwMDAwMDA7CiAgZGlzcGxheTogaW5s
+aW5lLWJsb2NrOwogIGZvbnQtc2l6ZTogMTFweDsKICBmb250LXdlaWdodDogNjAwOwogIG1hcmdpbi1s
+ZWZ0OiA1cHg7CiAgbWluLXdpZHRoOiAyNXB4OwogIHBhZGRpbmc6IDRweCAwIDJweCAwOwogIHRleHQt
+YWxpZ246IGNlbnRlcjsKICBsaW5lLWhlaWdodDogMWVtOwp9CgouY29udGVudCB7CiAgZmxleDogNCAz
+MDBweDsKICBiYWNrZ3JvdW5kOiAjMjgyYjJlOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAgbWFy
+Z2luOiAwIDZweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgd2hpdGUtc3BhY2U6IHByZTsKICBvdmVy
+Zmxvdzogc2Nyb2xsOwp9CgouY29kZSB7CiAgcGFkZGluZzogMC41ZW07CiAgcG9zaXRpb246IGFic29s
+dXRlOwogIGxlZnQ6IDA7CiAgdG9wOiAwOwogIG1hcmdpbi1sZWZ0OiA1NnB4Owp9CgouaGxqcyB7CiAg
+YmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdy14OiBh
+dXRvOwogIHBhZGRpbmc6IDAuNWVtOwp9CgouY29kZSAud2VsY29tZSB7CiAgZm9udC1mYW1pbHk6ICdP
+cGVuIFNhbnMnLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tcmlnaHQ6IDYy
+cHg7Cn0KCi5jb2RlIC5uYXYtbGluayB7CiAgY29sb3I6IGluaGVyaXQ7CiAgdGV4dC1kZWNvcmF0aW9u
+LWxpbmU6IG5vbmU7Cn0KCi5jb2RlIC5uYXYtbGluazp2aXNpdGVkIHsKICBjb2xvcjogaW5oZXJpdDsK
+ICB0ZXh0LWRlY29yYXRpb24tbGluZTogbm9uZTsKfQoKLmNvZGUgLm5hdi1saW5rOmhvdmVyIHsKICB0
+ZXh0LWRlY29yYXRpb24tbGluZTogdW5kZXJsaW5lOwogIGZvbnQtd2VpZ2h0OiA2MDA7Cn0KCi5yZWdp
+b25zIHsKICBwYWRkaW5nOiAwLjVlbTsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMDsKICB0
+b3A6IDA7Cn0KCi5yZWdpb25zIHRhYmxlIHsKICBib3JkZXItc3BhY2luZzogMDsKICBmb250LXNpemU6
+IGluaGVyaXQ7Cn0KCi5yZWdpb25zIHRkIHsKICBib3JkZXI6IG5vbmU7CiAgLyogVGhlIGNvbnRlbnQg
+b2YgdGhlIHJlZ2lvbnMgaXMgbm90IHZpc2libGU7IHRoZSB1c2VyIGluc3RlYWQgd2lsbCBzZWUgdGhl
+CiAgICogaGlnaGxpZ2h0ZWQgY29weSBvZiB0aGUgY29udGVudC4gKi8KICBjb2xvcjogcmdiYSgyNTUs
+IDI1NSwgMjU1LCAwKTsKICBwYWRkaW5nOiAwOwogIHdoaXRlLXNwYWNlOiBwcmU7Cn0KCi5yZWdpb25z
+IHRkOmVtcHR5OmFmdGVyIHsKICBjb250ZW50OiAiXDAwYTAiOwp9CgoucmVnaW9ucyB0ci5oaWdobGln
+aHQgdGQ6bGFzdC1jaGlsZCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDQ0NDsKICBjb2xvcjogd2hp
+dGU7Cn0KCi5yZWdpb25zIHRkLmxpbmUtbm8gewogIGJvcmRlci1yaWdodDogc29saWQgIzI4MmIyZSAy
+cHg7CiAgY29sb3I6ICM5OTk5OTk7CiAgcGFkZGluZy1yaWdodDogNHB4OwogIHRleHQtYWxpZ246IHJp
+Z2h0OwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAgd2lkdGg6IDUwcHg7CiAgZGlzcGxheTogaW5saW5l
+LWJsb2NrOwp9CgoucmVnaW9ucyB0ci5oaWdobGlnaHQgdGQubGluZS1ubyB7CiAgYm9yZGVyLXJpZ2h0
+OiBzb2xpZCAjY2NjIDJweDsKfQoKLnJlZ2lvbiB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIHBv
+c2l0aW9uOiByZWxhdGl2ZTsKICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogIHotaW5kZXg6IDIwMDsKfQoK
+LnJlZ2lvbi5hZGRlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6ICNjY2ZmY2M7CiAgY29sb3I6
+ICMwMDMzMDA7Cn0KCi5yZWdpb24ucmVtb3ZlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6ICNm
+ZjY2NjY7CiAgY29sb3I6ICMwMDExMDA7Cn0KCi5yZWdpb24udW5jaGFuZ2VkLXJlZ2lvbiB7CiAgYmFj
+a2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjMpOwogIGJvcmRlci1ib3R0b206IHNvbGlkIDJw
+eCAjY2NjOwogIC8qIEludmlzaWJsZSB0ZXh0OyB1c2UgdW5kZXJseWluZyBoaWdobGlnaHRpbmcuICov
+CiAgY29sb3I6IHJnYmEoMCwgMCwgMCwgMCk7CiAgLyogUmVkdWNlIGxpbmUgaGVpZ2h0IHRvIG1ha2Ug
+cm9vbSBmb3IgYm9yZGVyLiAqLwogIGxpbmUtaGVpZ2h0OiAxOwp9CgoudGFyZ2V0IHsKICBiYWNrZ3Jv
+dW5kLWNvbG9yOiAjRkZGRjk5OwogIGNvbG9yOiBibGFjazsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAg
+dmlzaWJpbGl0eTogdmlzaWJsZTsKfQoKLmluZm8tcGFuZWwgewogIGZsZXg6IDEgMjAwcHg7CiAgbWFy
+Z2luOiAwOwogIGhlaWdodDogMTAwJTsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBj
+b2x1bW47Cn0KCi5pbmZvLXBhbmVsIC5lZGl0LXBhbmVsIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjgy
+YjJlOwogIG92ZXJmbG93OiBhdXRvOwp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudCB7CiAgcGFk
+ZGluZzogN3B4Owp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudD4gOmZpcnN0LWNoaWxkIHsKICBt
+YXJnaW4tdG9wOiAwOwp9CgouaW5mby1wYW5lbCAubm93cmFwIHsKICB3aGl0ZS1zcGFjZTogbm93cmFw
+Owp9CgouaW5mby1wYW5lbCB1bCwKLmluZm8tcGFuZWwgb2wgewogIHBhZGRpbmctbGVmdDogMjBweDsK
+fQoKLmluZm8tcGFuZWwgbGkgewogIG1hcmdpbjogMCAwIDVweCAwOwp9CgouaW5mby1wYW5lbCBhIHsK
+ICBjb2xvcjogIzMzY2NmZjsKfQoKLmluZm8tcGFuZWwgLmVkaXQtbGlzdCB7CiAgYmFja2dyb3VuZC1j
+b2xvcjogIzI4MmIyZTsKICBvdmVyZmxvdzogYXV0bzsKfQoKLmVkaXQtcGFuZWwgewogIG1hcmdpbi10
+b3A6IDZweDsKICBmbGV4OiAxIDEwMHB4Owp9CgouZWRpdC1saXN0IHsKICBmbGV4OiAyIDEwMHB4Owp9
+CgouZWRpdC1saXN0IC5lZGl0IHsKICBtYXJnaW46IDNweCAwOwp9CgouZWRpdC1saXN0IC5lZGl0LWxp
+bmsgewogIGN1cnNvcjogcG9pbnRlcjsKfQoKLmVsZXZhdGlvbi16NCB7CiAgYm94LXNoYWRvdzogMHB4
+IDJweCA0cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMiksIDBweCA0cHggNXB4IDBweCByZ2JhKDAsIDAs
+IDAsIDAuMTQpLCAwcHggMXB4IDEwcHggMHB4IHJnYmEoMCwgMCwgMCwgLjEyKTsKfQoKYSB7CiAgY29s
+b3I6ICNjY2M7CiAgZmlsbDogI2NjYzsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCmE6aG92ZXIg
+ewogIGNvbG9yOiAjZmZmOwogIGZpbGw6ICNmZmY7Cn0K
 ''';
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_link.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_link.dart
index 342e125..de80deb 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_link.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_link.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:path/path.dart' as path;
-
 /// Information about a link to a compilation unit.
 class UnitLink {
   /// The relative URL of this compilation unit on the preview server.
@@ -19,7 +17,5 @@
   UnitLink(this.url, this.pathParts, this.editCount)
       : depth = pathParts.length - 1;
 
-  String get relativePath => path.joinAll(pathParts);
-
   String get fileName => pathParts.last;
 }
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 fd4e92e..ec5f6c9 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
@@ -36,6 +36,9 @@
 
   /// Builds a JSON view of the instrumentation information in [unitInfo].
   String render() {
+    // TODO(devoncarew): Both _computeNavigationContent() and
+    // _computeRegionContent() send html back to the client; convert this to
+    // instead sending data back (instead of presentation).
     Map<String, dynamic> response = {
       'thisUnit': migrationInfo.computeName(unitInfo),
       'navContent': _computeNavigationContent(),
@@ -145,8 +148,11 @@
     StringBuffer regions = StringBuffer();
     int lineNumber = 1;
 
-    void writeSplitLines(String lines,
-        {String perLineOpeningTag = '', String perLineClosingTag = ''}) {
+    void writeSplitLines(
+      String lines, {
+      String perLineOpeningTag = '',
+      String perLineClosingTag = '',
+    }) {
       Iterator<String> lineIterator = LineSplitter.split(lines).iterator;
       lineIterator.moveNext();
 
@@ -165,6 +171,7 @@
           break;
         }
       }
+
       if (lines.endsWith('\n')) {
         lineNumber++;
         regions.write('</td></tr>'
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/highlight_js.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/highlight_js.dart
new file mode 100644
index 0000000..7e9901e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/highlight_js.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 'dart:js';
+
+final HighlightJs hljs = HighlightJs._();
+
+/// A small wrapper around the JavaScript highlight.js APIs.
+class HighlightJs {
+  static JsObject get _hljs => context['hljs'];
+
+  HighlightJs._();
+
+  void highlightBlock(Element block) {
+    _hljs.callMethod('highlightBlock', [block]);
+  }
+}
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 8d5c9f5..6ec89e1 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
@@ -2,19 +2,46 @@
 // for details. All 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:html';
-import 'dart:js';
 
-//  TODO(devoncarew): Remove this is a follow-up.
-// ignore_for_file: prefer_single_quotes
+import 'package:path/path.dart' as _p;
+
+import 'highlight_js.dart';
 
 // TODO(devoncarew): Fix the issue where we can't load source maps.
 
 // TODO(devoncarew): Include a favicon.
 
-String get rootPath => querySelector(".root").text.trim();
+String get rootPath => querySelector('.root').text.trim();
+
+void main() {
+  document.addEventListener('DOMContentLoaded', (event) {
+    String path = window.location.pathname;
+    int offset = getOffset(window.location.href);
+    int lineNumber = getLine(window.location.href);
+    loadNavigationTree();
+    if (path != '/' && path != rootPath) {
+      // TODO(srawlins): replaceState?
+      loadFile(path, offset, lineNumber, callback: () {
+        pushState(path, offset, lineNumber);
+      });
+    }
+  });
+
+  window.addEventListener('popstate', (event) {
+    var path = window.location.pathname;
+    int offset = getOffset(window.location.href);
+    var lineNumber = getLine(window.location.href);
+    if (path.length > 1) {
+      loadFile(path, offset, lineNumber);
+    } else {
+      // Blank out the page, for the index screen.
+      writeCodeAndRegions({'regions': '', 'navContent': ''});
+      updatePage('&nbsp;', null);
+    }
+  });
+}
 
 int getOffset(String location) {
   String str = Uri.parse(location).queryParameters['offset'];
@@ -29,22 +56,22 @@
 /// Remove highlighting from [offset].
 void removeHighlight(int offset, int lineNumber) {
   if (offset != null) {
-    var anchor = document.getElementById("o$offset");
+    var anchor = document.getElementById('o$offset');
     if (anchor != null) {
-      anchor.classes.remove("target");
+      anchor.classes.remove('target');
     }
   }
   if (lineNumber != null) {
-    var line = document.querySelector(".line-$lineNumber");
+    var line = document.querySelector('.line-$lineNumber');
     if (line != null) {
-      line.parent.classes.remove("highlight");
+      line.parent.classes.remove('highlight');
     }
   }
 }
 
 /// Return the absolute path of [path], assuming [path] is relative to [root].
 String absolutePath(String path) {
-  if (path[0] != "/") {
+  if (path[0] != '/') {
     return '$rootPath/$path';
   } else {
     return path;
@@ -54,7 +81,7 @@
 /// If [path] lies within [root], return the relative path of [path] from [root].
 /// Otherwise, return [path].
 String relativePath(String path) {
-  var root = querySelector(".root").text + "/";
+  var root = querySelector('.root').text + '/';
   if (path.startsWith(root)) {
     return path.substring(root.length);
   } else {
@@ -64,55 +91,49 @@
 
 /// Write the contents of the Edit List, from JSON data [editListData].
 void writeEditList(dynamic editListData) {
-  var editList = document.querySelector(".edit-list .panel-content");
-  editList.innerHtml = "";
-  var p = editList.append(document.createElement("p"));
-  var countElement = p.append(document.createElement("strong"));
-  int editCount = editListData["editCount"];
-  countElement.append(Text(editCount.toString()));
-  if (editCount == 1) {
-    p.append(
-        Text(" edit was made to this file. Click the edit's checkbox to toggle "
-            "its reviewed state."));
+  var editList = document.querySelector('.edit-list .panel-content');
+  editList.innerHtml = '';
+  var p = editList.append(document.createElement('p'));
+  int editCount = editListData['editCount'];
+  if (editCount == 0) {
+    p.append(Text('$editCount proposed edits'));
   } else {
-    p.append(Text(
-        " edits were made to this file. Click an edit's checkbox to toggle "
-        "its reviewed state."));
+    p.append(Text('$editCount proposed ${pluralize(editCount, 'edit')}:'));
   }
-  for (var edit in editListData["edits"]) {
-    ParagraphElement editP = editList.append(document.createElement("p"));
-    editP.classes.add("edit");
-    Element checkbox = editP.append(document.createElement("input"));
-    checkbox.setAttribute("type", "checkbox");
-    checkbox.setAttribute("title", "Click to mark reviewed");
-    checkbox.setAttribute("disabled", "disabled");
-    editP.append(Text('line ${edit["line"]}: ${edit["explanation"]}.'));
-    AnchorElement a = editP.append(document.createElement("a"));
-    a.classes.add("edit-link");
-    int offset = edit["offset"];
-    a.dataset['offset'] = '$offset';
-    int line = edit["line"];
-    a.dataset['line'] = '$line';
-    a.append(Text("[view]"));
-    a.onClick.listen((MouseEvent event) {
+
+  Element list = editList.append(document.createElement('ul'));
+  for (var edit in editListData['edits']) {
+    Element item = list.append(document.createElement('li'));
+    item.classes.add('edit');
+    AnchorElement anchor = item.append(document.createElement('a'));
+    anchor.classes.add('edit-link');
+    int offset = edit['offset'];
+    anchor.dataset['offset'] = '$offset';
+    int line = edit['line'];
+    anchor.dataset['line'] = '$line';
+    anchor.append(Text('line $line'));
+    anchor.onClick.listen((MouseEvent event) {
       navigate(window.location.pathname, offset, line, callback: () {
         pushState(window.location.pathname, offset, line);
       });
-      loadRegionExplanation(a);
+      loadRegionExplanation(anchor);
     });
+    item.append(Text(': ${edit['explanation']}'));
   }
 }
 
 /// Load data from [data] into the .code and the .regions divs.
 void writeCodeAndRegions(dynamic data) {
-  var regions = document.querySelector(".regions");
-  var code = document.querySelector(".code");
-  PermissiveNodeValidator.setInnerHtml(regions, data["regions"]);
-  PermissiveNodeValidator.setInnerHtml(code, data["navContent"]);
-  writeEditList(data["editList"]);
+  var regions = document.querySelector('.regions');
+  var code = document.querySelector('.code');
+
+  _PermissiveNodeValidator.setInnerHtml(regions, data['regions']);
+  _PermissiveNodeValidator.setInnerHtml(code, data['navContent']);
+
+  writeEditList(data['editList']);
   highlightAllCode();
-  addClickHandlers(".code");
-  addClickHandlers(".regions");
+  addClickHandlers('.code');
+  addClickHandlers('.regions');
 }
 
 /// Navigate to [path] and optionally scroll [offset] into view.
@@ -160,23 +181,23 @@
   Element line;
 
   if (offset != null) {
-    target = document.getElementById("o$offset");
-    line = document.querySelector(".line-$lineNumber");
+    target = document.getElementById('o$offset');
+    line = document.querySelector('.line-$lineNumber');
     if (target != null) {
       maybeScrollIntoView(target);
-      target.classes.add("target");
+      target.classes.add('target');
     } else if (line != null) {
       // If the target doesn't exist, but the line does, scroll that into view
       // instead.
-      maybeScrollIntoView(line);
+      maybeScrollIntoView(line.parent);
     }
     if (line != null) {
-      (line.parentNode as Element).classes.add("highlight");
+      (line.parentNode as Element).classes.add('highlight');
     }
   } else {
     // If no offset is given, this is likely a navigation link, and we need to
     // scroll back to the top of the page.
-    target = document.getElementById("unit-name");
+    target = document.getElementById('unit-name');
     maybeScrollIntoView(target);
   }
 }
@@ -190,37 +211,46 @@
   VoidCallback callback,
 }) {
   // Navigating to another file; request it, then do work with the response.
+
+  // TODO(devoncarew): path might be a url; if it is, then use url manipulation
+  // to add additional args.
+
   HttpRequest.request(
-    "$path?inline=true",
+    path.contains('?') ? '$path&inline=true' : '$path?inline=true',
     requestHeaders: {'Content-Type': 'application/json; charset=UTF-8'},
   ).then((HttpRequest xhr) {
     if (xhr.status == 200) {
       var response = jsonDecode(xhr.responseText);
       writeCodeAndRegions(response);
       maybeScrollToAndHighlight(offset, lineNumber);
-      updatePage(path, offset);
+      String filePathPart =
+          path.contains('?') ? path.substring(0, path.indexOf('?')) : path;
+      updatePage(filePathPart, offset);
       if (callback != null) {
         callback();
       }
     } else {
-      window.alert("Request failed; status of ${xhr.status}");
+      window.alert('Request failed; status of ${xhr.status}');
     }
   }).catchError((e, st) {
-    logError(e, st);
+    logError('loadFile: $e', st);
 
-    window.alert('Could not load $path; preview server might be disconnected.');
+    window.alert('Could not load $path ($e).');
   });
 }
 
 void pushState(String path, int offset, int lineNumber) {
-  var newLocation = window.location.origin + path + "?";
+  // TODO(devoncarew): Path might be a url; if it is, then use url manipulation
+  // to add additional args.
+
+  var newLocation = window.location.origin + path + '?';
   if (offset != null) {
-    newLocation = newLocation + "offset=$offset&";
+    newLocation = newLocation + 'offset=$offset&';
   }
   if (lineNumber != null) {
-    newLocation = newLocation + "line=$lineNumber";
+    newLocation = newLocation + 'line=$lineNumber';
   }
-  window.history.pushState({}, "", newLocation);
+  window.history.pushState({}, '', newLocation);
 }
 
 /// Update the heading and navigation links.
@@ -229,40 +259,40 @@
 void updatePage(String path, int offset) {
   path = relativePath(path);
   // Update page heading.
-  Element unitName = document.querySelector("#unit-name");
+  Element unitName = document.querySelector('#unit-name');
   unitName.text = path;
   // Update navigation styles.
-  document.querySelectorAll(".nav-panel .nav-link").forEach((Element link) {
+  document.querySelectorAll('.nav-panel .nav-link').forEach((Element link) {
     var name = link.dataset['name'];
     if (name == path) {
-      link.classes.add("selected-file");
+      link.classes.add('selected-file');
     } else {
-      link.classes.remove("selected-file");
+      link.classes.remove('selected-file');
     }
   });
 }
 
 void highlightAllCode() {
-  document.querySelectorAll(".code").forEach((Element block) {
+  document.querySelectorAll('.code').forEach((Element block) {
     hljs.highlightBlock(block);
   });
 }
 
 void addArrowClickHandler(Element arrow) {
   Element childList =
-      (arrow.parentNode as Element).querySelector(":scope > ul");
+      (arrow.parentNode as Element).querySelector(':scope > ul');
   // Animating height from "auto" to "0" is not supported by CSS [1], so all we
   // have are hacks. The `* 2` allows for events in which the list grows in
   // height when resized, with additional text wrapping.
   // [1] https://css-tricks.com/using-css-transitions-auto-dimensions/
-  childList.style.maxHeight = "${childList.offsetHeight * 2}px";
+  childList.style.maxHeight = '${childList.offsetHeight * 2}px';
   arrow.onClick.listen((MouseEvent event) {
-    if (!childList.classes.contains("collapsed")) {
-      childList.classes.add("collapsed");
-      arrow.classes.add("collapsed");
+    if (!childList.classes.contains('collapsed')) {
+      childList.classes.add('collapsed');
+      arrow.classes.add('collapsed');
     } else {
-      childList.classes.remove("collapsed");
-      arrow.classes.remove("collapsed");
+      childList.classes.remove('collapsed');
+      arrow.classes.remove('collapsed');
     }
   });
 }
@@ -270,9 +300,9 @@
 void handleNavLinkClick(MouseEvent event) {
   Element target = event.currentTarget;
 
-  var path = absolutePath(target.getAttribute("href"));
-  int offset = getOffset(target.getAttribute("href"));
-  int lineNumber = getLine(target.getAttribute("href"));
+  var path = absolutePath(target.getAttribute('href'));
+  int offset = getOffset(target.getAttribute('href'));
+  int lineNumber = getLine(target.getAttribute('href'));
 
   if (offset != null) {
     navigate(path, offset, lineNumber, callback: () {
@@ -287,7 +317,7 @@
 }
 
 void handlePostLinkClick(MouseEvent event) {
-  String path = (event.currentTarget as Element).getAttribute("href");
+  String path = (event.currentTarget as Element).getAttribute('href');
   path = absolutePath(path);
 
   // Directing the server to produce an edit; request it, then do work with the
@@ -300,64 +330,65 @@
     if (xhr.status == 200) {
       // Likely request new navigation and file content.
     } else {
-      window.alert("Request failed; status of ${xhr.status}");
+      window.alert('Request failed; status of ${xhr.status}');
     }
   }).catchError((e, st) {
-    logError(e, st);
+    logError('handlePostLinkClick: $e', st);
 
-    window.alert('Could not load $path; preview server might be disconnected.');
+    window.alert('Could not load $path ($e).');
   });
 }
 
-void addClickHandlers(String parentSelector) {
-  Element parentElement = document.querySelector(parentSelector);
+void addClickHandlers(String selector) {
+  Element parentElement = document.querySelector(selector);
 
-  var navLinks = parentElement.querySelectorAll(".nav-link");
+  List<Element> navLinks = parentElement.querySelectorAll('.nav-link');
   navLinks.forEach((link) {
     link.onClick.listen(handleNavLinkClick);
   });
 
-  var regions = parentElement.querySelectorAll(".region");
-  regions.forEach((Element region) {
-    region.onClick.listen((event) {
-      loadRegionExplanation(region);
+  // TODO(devoncarew): Move this code to where the elements are defined.
+  List<Element> regions = parentElement.querySelectorAll('.region');
+  regions.forEach((Element anchor) {
+    anchor.onClick.listen((event) {
+      loadRegionExplanation(anchor);
     });
   });
 
-  var postLinks = parentElement.querySelectorAll(".post-link");
+  List<Element> postLinks = parentElement.querySelectorAll('.post-link');
   postLinks.forEach((link) {
     link.onClick.listen(handlePostLinkClick);
   });
 }
 
 void writeNavigationSubtree(Element parentElement, dynamic tree) {
-  var ul = parentElement.append(document.createElement('ul'));
+  Element ul = parentElement.append(document.createElement('ul'));
   for (var entity in tree) {
     Element li = ul.append(document.createElement('li'));
-    if (entity["type"] == "directory") {
-      li.classes.add("dir");
+    if (entity['type'] == 'directory') {
+      li.classes.add('dir');
       Element arrow = li.append(document.createElement('span'));
-      arrow.classes.add("arrow");
-      arrow.innerHtml = "&#x25BC;";
+      arrow.classes.add('arrow');
+      arrow.innerHtml = '&#x25BC;';
       Element icon = li.append(document.createElement('span'));
-      icon.innerHtml = "&#x1F4C1;";
-      li.append(Text(entity["name"]));
-      writeNavigationSubtree(li, entity["subtree"]);
+      icon.innerHtml = '&#x1F4C1;';
+      li.append(Text(entity['name']));
+      writeNavigationSubtree(li, entity['subtree']);
       addArrowClickHandler(arrow);
     } else {
-      li.innerHtml = "&#x1F4C4;";
-      Element a = li.append(document.createElement("a"));
-      a.classes.add("nav-link");
-      a.dataset['name'] = entity["path"];
-      a.setAttribute("href", entity["href"]);
-      a.append(Text(entity["name"]));
+      li.innerHtml = '&#x1F4C4;';
+      Element a = li.append(document.createElement('a'));
+      a.classes.add('nav-link');
+      a.dataset['name'] = entity['path'];
+      a.setAttribute('href', entity['href']);
+      a.append(Text(entity['name']));
       a.onClick.listen(handleNavLinkClick);
-      int editCount = entity["editCount"];
+      int editCount = entity['editCount'];
       if (editCount > 0) {
-        Element editsBadge = li.append(document.createElement("span"));
-        editsBadge.classes.add("edit-count");
-        var edits = editCount == 1 ? 'edit' : 'edits';
-        editsBadge.setAttribute("title", '$editCount $edits');
+        Element editsBadge = li.append(document.createElement('span'));
+        editsBadge.classes.add('edit-count');
+        editsBadge.setAttribute(
+            'title', '$editCount ${pluralize(editCount, 'edit')}');
         editsBadge.append(Text(editCount.toString()));
       }
     }
@@ -366,7 +397,7 @@
 
 /// Load the navigation tree into the ".nav-tree" div.
 void loadNavigationTree() {
-  String path = "/_preview/navigationTree.json";
+  String path = '/_preview/navigationTree.json';
 
   // Request the navigation tree, then do work with the response.
   HttpRequest.request(
@@ -375,16 +406,16 @@
   ).then((HttpRequest xhr) {
     if (xhr.status == 200) {
       dynamic response = jsonDecode(xhr.responseText);
-      var navTree = document.querySelector(".nav-tree");
-      navTree.innerHtml = "";
+      var navTree = document.querySelector('.nav-tree');
+      navTree.innerHtml = '';
       writeNavigationSubtree(navTree, response);
     } else {
       window.alert('Request failed; status of ${xhr.status}');
     }
   }).catchError((e, st) {
-    logError(e, st);
+    logError('loadNavigationTree: $e', st);
 
-    window.alert('Could not load $path; preview server might be disconnected.');
+    window.alert('Could not load $path ($e).');
   });
 }
 
@@ -394,60 +425,61 @@
 }
 
 void writeRegionExplanation(dynamic response) {
-  var editPanel = document.querySelector(".edit-panel .panel-content");
-  editPanel.innerHtml = "";
-  var regionLocation = document.createElement("p");
-  regionLocation.classes.add("region-location");
-  // Insert a zero-width space after each "/", to allow lines to wrap after each
-  // directory name.
-  // TODO(devoncarew): Handle the following regex (to improve layout).
-  //var path = response["path"].replace(/\//g, "/\u200B");
-  var path = response["path"];
-  regionLocation.append(Text('$path '));
-  Element regionLine = regionLocation.append(document.createElement("span"));
-  regionLine.append(Text('line ${response["line"]}'));
-  regionLine.classes.add("nowrap");
-  editPanel.append(regionLocation);
-  var explanation = editPanel.append(document.createElement("p"));
-  explanation.append(Text(response["explanation"]));
-  var detailCount = response["details"].length;
+  var editPanel = document.querySelector('.edit-panel .panel-content');
+  editPanel.innerHtml = '';
+
+  String filePath = response['path'];
+  String parentDirectory = _p.dirname(filePath);
+
+  // 'Changed ... at foo.dart:12.'
+  String explanationMessage = response['explanation'];
+  String relPath = _p.relative(filePath, from: rootPath);
+  int line = response['line'];
+  Element explanation = editPanel.append(document.createElement('p'));
+  explanation.append(Text('$explanationMessage at $relPath:$line.'));
+  int 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:".
-    explanation.append(Text("."));
   } else {
-    explanation.append(Text(detailCount == 1
-        ? ' for $detailCount reason:'
-        : ' for $detailCount reasons:'));
-    var detailList = editPanel.append(document.createElement("ol"));
-    for (var detail in response["details"]) {
-      var detailItem = detailList.append(document.createElement("li"));
-      detailItem.append(Text(detail["description"]));
-      if (detail["link"] != null) {
-        detailItem.append(Text(" ("));
-        AnchorElement a = detailItem.append(document.createElement("a"));
-        a.append(Text(detail["link"]["text"]));
-        a.setAttribute("href", detail["link"]["href"]);
-        a.classes.add("nav-link");
-        detailItem.append(Text(")"));
+    editPanel.append(ParagraphElement()..text = 'Edit rationale:');
+
+    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']));
+      if (detail['link'] != null) {
+        int targetLine = detail['link']['line'];
+
+        detailItem.append(Text(' ('));
+        AnchorElement a = detailItem.append(document.createElement('a'));
+        a.append(Text("${detail['link']['text']}:$targetLine"));
+
+        String relLink = detail['link']['href'];
+        String fullPath = _p.normalize(_p.join(parentDirectory, relLink));
+
+        a.setAttribute('href', fullPath);
+        a.classes.add('nav-link');
+        detailItem.append(Text(')'));
       }
     }
   }
-  if (response["edits"] != null) {
-    for (var edit in response["edits"]) {
-      Element editParagraph = editPanel.append(document.createElement("p"));
-      Element a = editParagraph.append(document.createElement("a"));
-      a.append(Text(edit["text"]));
-      a.setAttribute("href", edit["href"]);
-      a.classes.add("post-link");
+
+  if (response['edits'] != null) {
+    for (var edit in response['edits']) {
+      Element editParagraph = editPanel.append(document.createElement('p'));
+      Element a = editParagraph.append(document.createElement('a'));
+      a.append(Text(edit['text']));
+      a.setAttribute('href', edit['href']);
+      a.classes.add('post-link');
     }
   }
 }
 
 /// Load the explanation for [region], into the ".panel-content" div.
-void loadRegionExplanation(Element region) {
+void loadRegionExplanation(AnchorElement anchor) {
   String path = window.location.pathname;
-  String offset = region.dataset['offset'];
+  String offset = anchor.dataset['offset'];
 
   // Request the region, then do work with the response.
   HttpRequest.request(
@@ -457,137 +489,19 @@
     if (xhr.status == 200) {
       var response = jsonDecode(xhr.responseText);
       writeRegionExplanation(response);
-      addClickHandlers(".edit-panel .panel-content");
+      addClickHandlers('.edit-panel .panel-content');
     } else {
       window.alert('Request failed; status of ${xhr.status}');
     }
   }).catchError((e, st) {
-    logError(e, st);
+    logError('loadRegionExplanation: $e', st);
 
-    window.alert('Could not load $path; preview server might be disconnected.');
+    window.alert('Could not load $path ($e).');
   });
 }
 
-/// Resize the fixed-size and fixed-position navigation and information panels.
-void resizePanels() {
-  var navInner = document.querySelector(".nav-inner");
-  var height = window.innerHeight;
-  navInner.style.height = "${height}px";
-
-  var infoPanelHeight = height / 2 - 6;
-  var editPanel = document.querySelector(".edit-panel");
-  editPanel.style.height = "${infoPanelHeight}px";
-
-  var editListHeight = height / 2 - 6;
-  var editList = document.querySelector(".edit-list");
-  editList.style.height = "${editListHeight}px";
-}
-
-void main() {
-  document.addEventListener("DOMContentLoaded", (event) {
-    String path = window.location.pathname;
-    int offset = getOffset(window.location.href);
-    int lineNumber = getLine(window.location.href);
-    loadNavigationTree();
-    if (path != "/" && path != rootPath) {
-      // TODO(srawlins): replaceState?
-      loadFile(path, offset, lineNumber, callback: () {
-        pushState(path, offset, lineNumber);
-      });
-    }
-    resizePanels();
-  });
-
-  window.addEventListener("popstate", (event) {
-    var path = window.location.pathname;
-    int offset = getOffset(window.location.href);
-    var lineNumber = getLine(window.location.href);
-    if (path.length > 1) {
-      loadFile(path, offset, lineNumber);
-    } else {
-      // Blank out the page, for the index screen.
-      writeCodeAndRegions({"regions": "", "navContent": ""});
-      updatePage("&nbsp;", null);
-    }
-  });
-
-  final Debouncer resizeDebouncer =
-      Debouncer(const Duration(milliseconds: 200));
-  window.addEventListener("resize", (event) {
-    resizeDebouncer.run(resizePanels);
-  });
-
-  final Debouncer scrollDebouncer =
-      Debouncer(const Duration(milliseconds: 200));
-
-  // When scrolling the page, determine whether the navigation and information
-  // panels need to be fixed in place, or allowed to scroll.
-  window.addEventListener("scroll", (event) {
-    var navPanel = document.querySelector(".nav-panel");
-    var navInner = navPanel.querySelector(".nav-inner");
-    var infoPanel = document.querySelector(".info-panel");
-    var panelContainer = document.querySelector(".panel-container");
-    var innerTopOffset = navPanel.offsetTop;
-    if (window.pageYOffset > innerTopOffset) {
-      if (!navInner.classes.contains("fixed")) {
-        var navPanelWidth = navPanel.offsetWidth - 14;
-        navPanel.style.width = "${navPanelWidth}px";
-        // Subtract 7px for nav-inner's padding.
-        navInner.style.width = (navPanelWidth + 7).toString() + "px";
-        navInner.classes.add("fixed");
-      }
-      if (!panelContainer.classes.contains("fixed")) {
-        var infoPanelWidth = infoPanel.offsetWidth;
-        infoPanel.style.width = "${infoPanelWidth}px";
-        panelContainer.style.width = "${infoPanelWidth}px";
-        panelContainer.classes.add("fixed");
-      }
-    } else {
-      if (navInner.classes.contains("fixed")) {
-        navPanel.style.width = "";
-        navInner.style.width = "";
-        navInner.classes.remove("fixed");
-      }
-      if (panelContainer.classes.contains("fixed")) {
-        infoPanel.style.width = "";
-        panelContainer.style.width = "";
-        panelContainer.classes.remove("fixed");
-      }
-    }
-    scrollDebouncer.run(resizePanels);
-  });
-}
-
-final HighlightJs hljs = HighlightJs._();
-
-/// A small wrapper around the JavaScript highlight.js APIs.
-class HighlightJs {
-  static JsObject get _hljs => context['hljs'];
-
-  HighlightJs._();
-
-  void highlightBlock(Element block) {
-    _hljs.callMethod('highlightBlock', [block]);
-  }
-}
-
-/// A utility class to debounce an action at the given duration.
-class Debouncer {
-  final Duration duration;
-  Timer _timer;
-
-  Debouncer(this.duration);
-
-  void run(VoidCallback action) {
-    if (_timer != null) {
-      _timer.cancel();
-    }
-    _timer = Timer(duration, action);
-  }
-}
-
-class PermissiveNodeValidator implements NodeValidator {
-  static PermissiveNodeValidator instance = PermissiveNodeValidator();
+class _PermissiveNodeValidator implements NodeValidator {
+  static _PermissiveNodeValidator instance = _PermissiveNodeValidator();
 
   static void setInnerHtml(Element element, String html) {
     element.setInnerHtml(html, validator: instance);
@@ -603,3 +517,7 @@
     return true;
   }
 }
+
+String pluralize(int count, String single, {String multiple}) {
+  return count == 1 ? single : (multiple ?? '${single}s');
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart b/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart
index 4cb330d..775b40b 100644
--- a/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/highlight_css_page.dart
@@ -12,10 +12,6 @@
 /// The page that contains the CSS used to style the semantic highlighting
 /// within a Dart file.
 class HighlightCssPage extends PreviewPage {
-  /// The decoded content of the page. Use [pageContent] to access this field so
-  /// that it is initialized on first read.
-  static String _pageContent;
-
   /// Initialize a newly created CSS page within the given [site].
   HighlightCssPage(PreviewSite site)
       : super(site, PreviewSite.highlightCssPath.substring(1));
@@ -27,11 +23,6 @@
 
   @override
   Future<void> generatePage(Map<String, String> params) async {
-    buf.write(pageContent());
-  }
-
-  /// Return the content of the page.
-  String pageContent() {
-    return _pageContent ??= resources.highlight_css;
+    buf.write(resources.highlight_css);
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart b/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart
index a024eca..49646da 100644
--- a/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/highlight_js_page.dart
@@ -12,10 +12,6 @@
 /// The page that contains the JavaScript used to apply semantic highlighting
 /// styles to a Dart file.
 class HighlightJSPage extends PreviewPage {
-  /// The decoded content of the page. Use [pageContent] to access this field so
-  /// that it is initialized on first read.
-  static String _pageContent;
-
   /// Initialize a newly created JS page within the given [site].
   HighlightJSPage(PreviewSite site)
       : super(site, PreviewSite.highlightJsPath.substring(1));
@@ -27,11 +23,6 @@
 
   @override
   Future<void> generatePage(Map<String, String> params) async {
-    buf.write(pageContent());
-  }
-
-  /// Return the content of the page.
-  String pageContent() {
-    return _pageContent ??= resources.highlight_pack_js;
+    buf.write(resources.highlight_pack_js);
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart b/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
index e4c025f..7a8d2f1 100644
--- a/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
@@ -14,7 +14,7 @@
 
   @override
   // TODO(srawlins): Refactor JSON-returning pages like this to not inherit all
-  //  of the HTML logic from  [PreviewPage].
+  //  of the HTML logic from [PreviewPage].
   void generateBody(Map<String, String> params) {
     throw UnsupportedError('generateBody');
   }
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 ef90020..98ce643 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
@@ -9,6 +9,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/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/resolver.dart'
@@ -43,7 +44,21 @@
       if (classOrMixin != null) {
         var type = classOrMixin.declaredElement.thisType;
         _addExtensionMembers(containingLibrary, type);
+      } else {
+        var extension = request.target.containingNode
+            .thisOrAncestorOfType<ExtensionDeclaration>();
+        if (extension != null) {
+          var type = extension.extendedType.type;
+          if (type is InterfaceType) {
+            var types = <InterfaceType>[];
+            ClassElementImpl.collectAllSupertypes(types, type, null);
+            for (var type in types) {
+              _addTypeMembers(type);
+            }
+          }
+        }
       }
+
       return builder.suggestions.toList();
     }
 
@@ -108,6 +123,25 @@
     }
   }
 
+  void _addTypeMembers(InterfaceType type) {
+    for (var elem in type.methods) {
+      builder.addSuggestion(elem);
+    }
+    var variables = <Element>{};
+    for (var elem in type.accessors) {
+      if (elem.isSynthetic) {
+        var variable = elem.variable;
+        // Ensure we don't have duplicate suggestions for accessors of non-final
+        // fields (which have a getter and setter).
+        if (variables.add(variable)) {
+          builder.addSuggestion(elem.variable);
+        }
+      } else {
+        builder.addSuggestion(elem);
+      }
+    }
+  }
+
   /// Use the [type] of the object being extended in the [library] to compute
   /// the actual type extended by the [extension]. Return the computed type,
   /// or `null` if the type cannot be computed.
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index e8f4bf4..9a4365b 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -199,6 +199,8 @@
       'dart.assist.convert.replaceWithVar',
       30,
       "Replace type annotation with 'var'");
+  static const SHADOW_FIELD = AssistKind('dart.assist.shadowField', 30,
+      'Create a local variable that shadows the field');
   static const SORT_CHILD_PROPERTY_LAST = AssistKind(
       'dart.assist.sort.child.properties.last',
       30,
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 8c2f968..7506563 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -16,6 +16,7 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/exchange_operands.dart';
+import 'package:analysis_server/src/services/correction/dart/shadow_field.dart';
 import 'package:analysis_server/src/services/correction/dart/split_and_condition.dart';
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
 import 'package:analysis_server/src/services/correction/selection_analyzer.dart';
@@ -294,6 +295,10 @@
       DartAssistKind.EXCHANGE_OPERANDS,
     );
     await compute(
+      ShadowField(),
+      DartAssistKind.SHADOW_FIELD,
+    );
+    await compute(
       SplitAndCondition(),
       DartAssistKind.SPLIT_AND_CONDITION,
     );
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index ecabe3c..ed9fd2f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -25,6 +25,8 @@
 
   AstNode get node => _context.node;
 
+  ResolvedUnitResult get resolvedResult => _context.resolvedResult;
+
   int get selectionLength => _context.selectionLength;
 
   int get selectionOffset => _context.selectionOffset;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware.dart
index 027c931..6f96573 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware.dart
@@ -13,6 +13,10 @@
   @override
   Future<void> compute(DartChangeBuilder builder) async {
     AstNode node = this.node;
+    if (node.parent is BinaryExpression &&
+        node.parent.parent is ConditionalExpression) {
+      node = node.parent.parent;
+    }
     if (node is! ConditionalExpression) {
       return;
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart b/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart
new file mode 100644
index 0000000..e3672b5
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.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';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class ShadowField extends CorrectionProducer {
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
+    var element = (node as SimpleIdentifier).staticElement;
+    if (element is! PropertyAccessorElement) {
+      return;
+    }
+    var accessor = element as PropertyAccessorElement;
+    if (!accessor.isGetter || accessor.enclosingElement is! ClassElement) {
+      // TODO(brianwilkerson) Should we also require that the getter be synthetic?
+      return;
+    }
+    var statement = getStatement();
+    if (statement == null) {
+      return;
+    }
+    if (statement.parent is! Block) {
+      // TODO(brianwilkerson) Support adding a block between the statement and
+      //  its parent (where the parent will be something like a while or if
+      //  statement). Also support the case where the parent is a case clause.
+      return;
+    }
+    var enclosingBlock = statement.parent as Block;
+    _ReferenceFinder finder = _ReferenceFinder(accessor.correspondingSetter);
+    enclosingBlock.accept(finder);
+    if (finder.hasSetterReference) {
+      return;
+    }
+    var fieldName = accessor.name;
+    var offset = statement.offset;
+    var prefix = utils.getLinePrefix(offset);
+    //
+    // Build the change.
+    //
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addInsertion(offset, (builder) {
+        // TODO(brianwilkerson) Conditionally write a type annotation instead of
+        //  'var' when we're able to discover user preferences.
+        builder.write('var ');
+        builder.write(fieldName);
+        builder.write(' = this.');
+        builder.write(fieldName);
+        builder.writeln(';');
+        builder.write(prefix);
+      });
+      // TODO(brianwilkerson) Consider removing unnecessary casts and null
+      //  checks that are no longer needed because promotion works. This would
+      //  be dependent on whether enhanced promotion is supported in the library
+      //  being edited.
+    });
+  }
+
+  /// Return the statement immediately enclosing the [node] that would promote
+  /// the type of the field if it were replaced by a local variable.
+  Statement getStatement() {
+    var parent = node.parent;
+
+    Statement enclosingIf(Expression expression) {
+      var parent = expression.parent;
+      while (parent is BinaryExpression) {
+        var opType = (parent as BinaryExpression).operator.type;
+        if (opType != TokenType.AMPERSAND_AMPERSAND) {
+          break;
+        }
+        parent = parent.parent;
+      }
+      if (parent is IfStatement) {
+        return parent;
+      }
+      return null;
+    }
+
+    if (parent is IsExpression && parent.expression == node) {
+      return enclosingIf(parent);
+    } else if (parent is BinaryExpression &&
+        resolvedResult.libraryElement.isNonNullableByDefault) {
+      var opType = parent.operator.type;
+      if (opType == TokenType.EQ_EQ || opType == TokenType.BANG_EQ) {
+        return enclosingIf(parent);
+      }
+    }
+    return null;
+  }
+}
+
+/// A utility that will find any references to a setter within an AST structure.
+class _ReferenceFinder extends RecursiveAstVisitor<void> {
+  /// The setter being searched for.
+  final PropertyAccessorElement setter;
+
+  /// A flag indicating whether a reference to the [setter] has been found.
+  bool hasSetterReference = false;
+
+  /// Initialize a newly created reference finder to find references to the
+  /// given [setter].
+  _ReferenceFinder(this.setter);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.staticElement == setter) {
+      hasSetterReference = true;
+    }
+  }
+}
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index c36ecd8..73ed2fb 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -15,7 +15,6 @@
   linter: any
   logging: any
   meta: any
-  mustache: any
   nnbd_migration: any
   source_span: any
   package_config: any
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 7b89151..d207b6e 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -2,45 +2,93 @@
 // for details. All 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/dart/utilities.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-
 import '../services/completion/dart/completion_contributor_util.dart';
 import 'impl/completion_driver.dart';
 
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(BasicCompletionTest);
+    defineReflectiveTests(CompletionWithSuggestionsTest);
   });
 }
 
 abstract class AbstractCompletionDriverTest with ResourceProviderMixin {
   CompletionDriver driver;
-
   Map<String, String> packageRoots;
-
   List<CompletionSuggestion> suggestions;
 
-  bool get supportsAvailableDeclarations;
+  String get projectName => 'project';
 
-  String addTestFile(String content, {int offset}) =>
-      driver.addTestFile(content, offset: offset);
+  String get projectPath => '/$projectName';
+
+  bool get supportsAvailableSuggestions;
+
+  String get testFilePath => '$projectPath/bin/test.dart';
+
+  Future<void> addProjectFile(String relativePath, String content) async {
+    newFile('$projectPath/$relativePath', content: content);
+    // todo (pq): handle more than lib
+    expect(relativePath, startsWith('lib/'));
+    var packageRelativePath = relativePath.substring(4);
+    var uriStr = 'package:$projectName/$packageRelativePath';
+    await driver.waitForSetWithUri(uriStr);
+  }
+
+  Future<void> addTestFile(String content, {int offset}) async {
+    driver.addTestFile(content, offset: offset);
+    await getSuggestions();
+  }
 
   Future<List<CompletionSuggestion>> getSuggestions() async {
+    if (supportsAvailableSuggestions) {
+      // todo (pq): consider moving
+      const internalLibs = [
+        'dart:async2',
+        'dart:_interceptors',
+        'dart:_internal',
+      ];
+      for (var lib in driver.sdk.sdkLibraries) {
+        var uri = lib.shortName;
+        if (!internalLibs.contains(uri)) {
+          await driver.waitForSetWithUri(uri);
+        }
+      }
+    }
+
     suggestions = await driver.getSuggestions();
     return suggestions;
   }
 
+  /// Display sorted suggestions.
+  void printSuggestions() {
+    suggestions.sort(completionComparator);
+    for (var s in suggestions) {
+      print(
+          '[${s.relevance}] ${s.completion} • ${s.element?.kind?.name ?? ""} ${s.kind.name} ${s.element?.location?.file ?? ""}');
+    }
+  }
+
   @mustCallSuper
   void setUp() {
     driver = CompletionDriver(
-        supportsAvailableDeclarations: supportsAvailableDeclarations,
+        supportsAvailableSuggestions: supportsAvailableSuggestions,
+        projectPath: projectPath,
+        testFilePath: testFilePath,
         resourceProvider: resourceProvider);
     driver.createProject(packageRoots: packageRoots);
+
+    newFile('$projectPath/pubspec.yaml', content: '');
+    newFile('$projectPath/.packages', content: '''
+project:${toUri('$projectPath/lib')}
+''');
+    // todo (pq): add logic (possibly to driver) that waits for SDK suggestions
   }
 
   SuggestionMatcher suggestionHas(
@@ -60,12 +108,19 @@
         return false;
       };
 
+  Iterable<CompletionSuggestion> suggestionsWith(
+          {@required String completion,
+          ElementKind element,
+          CompletionSuggestionKind kind}) =>
+      suggestions.where(
+          suggestionHas(completion: completion, element: element, kind: kind));
+
   CompletionSuggestion suggestionWith(
       {@required String completion,
       ElementKind element,
       CompletionSuggestionKind kind}) {
-    final matches = suggestions.where(
-        suggestionHas(completion: completion, element: element, kind: kind));
+    final matches =
+        suggestionsWith(completion: completion, element: element, kind: kind);
     expect(matches, hasLength(1));
     return matches.first;
   }
@@ -74,11 +129,11 @@
 @reflectiveTest
 class BasicCompletionTest extends AbstractCompletionDriverTest {
   @override
-  bool get supportsAvailableDeclarations => false;
+  bool get supportsAvailableSuggestions => false;
 
-  /// Duplicates (and potentially replaces DeprecatedMemberRelevanceTest.
+  /// Duplicates (and potentially replaces DeprecatedMemberRelevanceTest).
   Future<void> test_deprecated_member_relevance() async {
-    addTestFile('''
+    await addTestFile('''
 class A {
   void a1() { }
   @deprecated
@@ -91,7 +146,6 @@
 }
 ''');
 
-    await getSuggestions();
     expect(
         suggestionWith(
                 completion: 'a2',
@@ -105,3 +159,63 @@
             .relevance));
   }
 }
+
+@reflectiveTest
+class CompletionWithSuggestionsTest extends AbstractCompletionDriverTest {
+  @override
+  bool get supportsAvailableSuggestions => true;
+
+  @override
+  String get testFilePath => '$projectPath/lib/test.dart';
+
+  Future<void> test_basic() async {
+    await addProjectFile('lib/a.dart', r'''
+class A {}
+''');
+
+    await addTestFile('''
+void main() {
+  ^
+}
+''');
+
+    var suggestions = suggestionsWith(
+        completion: 'A', kind: CompletionSuggestionKind.INVOCATION);
+    // todo (pq): seems like this should be 1; investigate duplication.
+    expect(suggestions, hasLength(2));
+  }
+
+  Future<void> test_sdk_lib_suggestions() async {
+    await addTestFile('''
+void main() {
+  ^
+}
+''');
+
+    // A set of SDK suggestions.
+    expect(
+        // from dart:async (StreamSubscription)
+        suggestionWith(
+            completion: 'asFuture', kind: CompletionSuggestionKind.INVOCATION),
+        isNotNull);
+
+    expect(
+        // from dart:core
+        suggestionWith(
+            completion: 'print', kind: CompletionSuggestionKind.INVOCATION),
+        isNotNull);
+
+    expect(
+        // from dart:collection (ListMixin)
+        suggestionWith(
+            completion: 'firstWhere',
+            kind: CompletionSuggestionKind.INVOCATION),
+        isNotNull);
+
+    expect(
+        // from dart:math
+        suggestionWith(
+            completion: 'tan', kind: CompletionSuggestionKind.INVOCATION),
+        isNotNull);
+  }
+}
diff --git a/pkg/analysis_server/test/client/impl/abstract_client.dart b/pkg/analysis_server/test/client/impl/abstract_client.dart
index d938063..3c5286b 100644
--- a/pkg/analysis_server/test/client/impl/abstract_client.dart
+++ b/pkg/analysis_server/test/client/impl/abstract_client.dart
@@ -9,6 +9,7 @@
     hide AnalysisOptions;
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
+import 'package:analysis_server/src/domain_completion.dart';
 import 'package:analysis_server/src/utilities/mocks.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -31,14 +32,14 @@
   final Map<AnalysisService, List<String>> analysisSubscriptions = {};
 
   final String projectPath;
-  final String testFolder;
-  final String testFile;
+  final String testFilePath;
   String testCode;
 
+  MockSdk sdk;
+
   AbstractClient({
     @required this.projectPath,
-    @required this.testFolder,
-    @required this.testFile,
+    @required this.testFilePath,
     @required String sdkPath,
   })  : serverChannel = MockServerChannel(),
         pluginManager = TestPluginManager() {
@@ -52,11 +53,14 @@
   AnalysisDomainHandler get analysisHandler => server.handlers
       .singleWhere((handler) => handler is AnalysisDomainHandler);
 
-  AnalysisOptions get analysisOptions => testDiver.analysisOptions;
+  CompletionDomainHandler get completionHandler =>
+      server.handlers.whereType<CompletionDomainHandler>().single;
+
+  AnalysisOptions get analysisOptions => testDriver.analysisOptions;
 
   ResourceProvider get resourceProvider;
 
-  AnalysisDriver get testDiver => server.getAnalysisDriver(testFile);
+  AnalysisDriver get testDriver => server.getAnalysisDriver(testFilePath);
 
   void addAnalysisOptionsFile(String content) {
     newFile(
@@ -86,9 +90,9 @@
   }
 
   String addTestFile(String content) {
-    newFile(testFile, content);
+    newFile(testFilePath, content);
     testCode = content;
-    return testFile;
+    return testFilePath;
   }
 
   void assertValidId(String id) {
@@ -98,13 +102,14 @@
 
   /// Create an analysis server with the given [sdkPath].
   AnalysisServer createAnalysisServer(String sdkPath) {
-    MockSdk(resourceProvider: resourceProvider);
+    sdk = MockSdk(resourceProvider: resourceProvider);
     var options = AnalysisServerOptions();
     return AnalysisServer(serverChannel, resourceProvider, options,
         DartSdkManager(sdkPath, true), InstrumentationService.NULL_SERVICE);
   }
 
   /// Create a project at [projectPath].
+  @mustCallSuper
   void createProject({Map<String, String> packageRoots}) {
     newFolder(projectPath);
     var request = AnalysisSetAnalysisRootsParams([projectPath], [],
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 8a6415e..1ef4ece 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -18,28 +18,48 @@
 import 'abstract_client.dart';
 import 'expect_mixin.dart';
 
+CompletionSuggestion _createCompletionSuggestionFromAvailableSuggestion(
+    AvailableSuggestion suggestion) {
+  // todo (pq): IMPLEMENT
+  // com.jetbrains.lang.dart.ide.completion.DartServerCompletionContributor#createCompletionSuggestionFromAvailableSuggestion
+  return CompletionSuggestion(
+      // todo (pq): in IDEA, this is "UNKNOWN" but here we need a value; figure out what's up.
+      CompletionSuggestionKind.INVOCATION,
+      0,
+      suggestion.label,
+      0,
+      0,
+      suggestion.element.isDeprecated,
+      false);
+}
+
 class CompletionDriver extends AbstractClient with ExpectMixin {
-  final bool supportsAvailableDeclarations;
+  final bool supportsAvailableSuggestions;
   final MemoryResourceProvider _resourceProvider;
 
   Map<String, Completer<void>> receivedSuggestionsCompleters = {};
   List<CompletionSuggestion> suggestions = [];
-  bool suggestionsDone = false;
   Map<String, List<CompletionSuggestion>> allSuggestions = {};
 
+  final Map<int, AvailableSuggestionSet> idToSetMap = {};
+  final Map<String, AvailableSuggestionSet> uriToSetMap = {};
+  final Map<String, CompletionResultsParams> idToSuggestions = {};
+  final Map<String, ExistingImports> fileToExistingImports = {};
+
   String completionId;
   int completionOffset;
   int replacementOffset;
   int replacementLength;
 
   CompletionDriver({
-    @required this.supportsAvailableDeclarations,
+    @required this.supportsAvailableSuggestions,
     @required MemoryResourceProvider resourceProvider,
+    @required String projectPath,
+    @required String testFilePath,
   })  : _resourceProvider = resourceProvider,
         super(
-            projectPath: resourceProvider.convertPath('/project'),
-            testFolder: resourceProvider.convertPath('/project/bin'),
-            testFile: resourceProvider.convertPath('/project/bin/test.dart'),
+            projectPath: projectPath,
+            testFilePath: testFilePath,
             sdkPath: resourceProvider.convertPath('/sdk'));
 
   @override
@@ -60,17 +80,26 @@
         content.substring(completionOffset + 1));
   }
 
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    super.createProject(packageRoots: packageRoots);
+    if (supportsAvailableSuggestions) {
+      var request = CompletionSetSubscriptionsParams(
+          [CompletionService.AVAILABLE_SUGGESTION_SETS]).toRequest('0');
+      handleSuccessfulRequest(request, handler: completionHandler);
+    }
+  }
+
   Future<List<CompletionSuggestion>> getSuggestions() async {
     await waitForTasksFinished();
 
-    var request = CompletionGetSuggestionsParams(testFile, completionOffset)
+    var request = CompletionGetSuggestionsParams(testFilePath, completionOffset)
         .toRequest('0');
     var response = await waitResponse(request);
     var result = CompletionGetSuggestionsResult.fromResponse(response);
     completionId = result.id;
     assertValidId(completionId);
     await _getResultsCompleter(completionId).future;
-    expect(suggestionsDone, isTrue);
     return suggestions;
   }
 
@@ -82,24 +111,68 @@
   Folder newFolder(String path) => resourceProvider.newFolder(path);
 
   @override
+  @mustCallSuper
   Future<void> processNotification(Notification notification) async {
     if (notification.event == COMPLETION_RESULTS) {
       var params = CompletionResultsParams.fromNotification(notification);
       var id = params.id;
       assertValidId(id);
+      idToSuggestions[id] = params;
       replacementOffset = params.replacementOffset;
       replacementLength = params.replacementLength;
-      suggestionsDone = params.isLast;
-      expect(suggestionsDone, isNotNull);
       suggestions = params.results;
       expect(allSuggestions.containsKey(id), isFalse);
       allSuggestions[id] = params.results;
+
+      for (var set in params.includedSuggestionSets) {
+        var id = set.id;
+        while (!idToSetMap.containsKey(id)) {
+          await Future.delayed(const Duration(milliseconds: 1));
+        }
+        var suggestionSet = idToSetMap[id];
+        for (var suggestion in suggestionSet.items) {
+          var completionSuggestion =
+              _createCompletionSuggestionFromAvailableSuggestion(suggestion
+                  //, includedSet.getRelevance(), includedRelevanceTags
+                  );
+          suggestions.add(completionSuggestion);
+        }
+      }
+
       _getResultsCompleter(id).complete(null);
+    } else if (notification.event ==
+        COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS) {
+      var params = CompletionAvailableSuggestionsParams.fromNotification(
+        notification,
+      );
+      for (var set in params.changedLibraries) {
+        idToSetMap[set.id] = set;
+        uriToSetMap[set.uri] = set;
+      }
+      for (var id in params.removedLibraries) {
+        var set = idToSetMap.remove(id);
+        uriToSetMap.remove(set?.uri);
+      }
+    } else if (notification.event == COMPLETION_NOTIFICATION_EXISTING_IMPORTS) {
+      var params = CompletionExistingImportsParams.fromNotification(
+        notification,
+      );
+      fileToExistingImports[params.file] = params.imports;
     } else if (notification.event == SERVER_NOTIFICATION_ERROR) {
       throw Exception('server error: ${notification.toJson()}');
     }
   }
 
+  Future<AvailableSuggestionSet> waitForSetWithUri(String uri) async {
+    while (true) {
+      var result = uriToSetMap[uri];
+      if (result != null) {
+        return result;
+      }
+      await Future.delayed(const Duration(milliseconds: 1));
+    }
+  }
+
   Completer<void> _getResultsCompleter(String id) =>
       receivedSuggestionsCompleters.putIfAbsent(id, () => Completer<void>());
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
index 2d8bfc3..4085340 100644
--- a/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
@@ -27,6 +27,79 @@
     super.setUp();
   }
 
+  Future<void> test_extended_members_inExtension_field() async {
+    addTestSource('''
+class A {
+  int a = 0;
+}
+class B extends A {
+  int b = 0;
+}
+extension E on B {
+  void e() { 
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestField('a', 'int');
+    assertSuggestField('b', 'int');
+  }
+
+  Future<void> test_extended_members_inExtension_getter_setter() async {
+    addTestSource('''
+class A {
+  int get a => 0;
+}
+class B extends A {
+  set b(int b) { }
+}
+extension E on B {
+  void e() { 
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestGetter('a', 'int');
+    assertSuggestSetter('b');
+  }
+
+  Future<void> test_extended_members_inExtension_method() async {
+    addTestSource('''
+class A {
+  void a() { }
+}
+class B extends A {
+  void b() { }
+}
+extension E on B {
+  void e() { 
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestMethod('b', 'B', 'void');
+    assertSuggestMethod('a', 'A', 'void');
+  }
+
+  Future<void> test_extended_members_inExtension_method_paramType() async {
+    addTestSource('''
+class A<T> {
+  T a() => null;
+}
+
+extension E on A<int> {
+  void e() { 
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestMethod('a', 'A', 'int');
+  }
+
   Future<void> test_extension() async {
     addTestSource('''
 extension E on int {}
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index c46b81f..b09dfac 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -489,7 +490,7 @@
 
     return AnalysisDriver(scheduler, logger, resourceProvider, byteStore,
         contentOverlay, null, SourceFactory(resolvers), AnalysisOptionsImpl(),
-        enableIndex: true);
+        packages: Packages.empty, enableIndex: true);
   }
 
   static void _assertContainsClass(Set<ClassElement> subtypes, String name) {
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
index 10a1557..371d79c 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
@@ -134,16 +134,15 @@
             isJsonMap.containing({
               'name': 'src',
               'subtree': [
-                isJsonMap.containing(
-                    {'href': convertPath('/project/lib/src/b.dart')})
+                isJsonMap.containing({'href': '/project/lib/src/b.dart'})
               ]
             }),
-            isJsonMap.containing({'href': convertPath('/project/lib/a.dart')})
+            isJsonMap.containing({'href': '/project/lib/a.dart'})
           ]
         }));
 
     var toolNode = response[1];
-    expect(toolNode['href'], convertPath('/project/tool.dart'));
+    expect(toolNode['href'], '/project/tool.dart');
   }
 
   Future<void> test_containsMultipleLinks_multipleDepths() async {
@@ -208,12 +207,12 @@
             isJsonMap.containing({
               'name': 'a.dart',
               'path': convertPath('lib/a.dart'),
-              'href': convertPath('/project/lib/a.dart')
+              'href': '/project/lib/a.dart'
             }),
             isJsonMap.containing({
               'name': 'b.dart',
               'path': convertPath('lib/b.dart'),
-              'href': convertPath('/project/lib/b.dart')
+              'href': '/project/lib/b.dart'
             })
           ]
         }));
@@ -264,7 +263,7 @@
                 isJsonMap.containing({
                   'name': 'a.dart',
                   'path': convertPath('lib/src/a.dart'),
-                  'href': convertPath('/project/lib/src/a.dart')
+                  'href': '/project/lib/src/a.dart'
                 })
               ]
             })
@@ -281,7 +280,7 @@
     var aNode = response[0];
     expect(aNode['name'], 'a.dart');
     expect(aNode['path'], 'a.dart');
-    expect(aNode['href'], convertPath('/project/a.dart'));
+    expect(aNode['href'], '/project/a.dart');
   }
 }
 
diff --git a/pkg/analysis_server/test/src/services/correction/assist/shadow_field_test.dart b/pkg/analysis_server/test/src/services/correction/assist/shadow_field_test.dart
new file mode 100644
index 0000000..c6bfb62
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/shadow_field_test.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.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ShadowFieldTest);
+    defineReflectiveTests(ShadowFieldWithNNBDTest);
+  });
+}
+
+@reflectiveTest
+class ShadowFieldTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.SHADOW_FIELD;
+
+  Future<void> test_is_assigned() async {
+    await resolveTestUnit('''
+class C {
+  num f = 0;
+
+  void m() {
+    if (f is int) {
+      print(f.abs());
+    }
+    f = 0;
+    print(f.abs());
+  }
+}
+''');
+    await assertNoAssistAt('f is');
+  }
+
+  Future<void> test_is_noBlock_while() async {
+    await resolveTestUnit('''
+class C {
+  num f = 0;
+
+  void m() {
+    while (true) 
+      if (f is int) {
+        print((f as int).abs());
+      }
+  }
+}
+''');
+    await assertNoAssistAt('f is');
+  }
+
+  Future<void> test_is_referencedViaThis() async {
+    await resolveTestUnit('''
+class C {
+  num f = 0;
+
+  void m() {
+    if (f is int) {
+      print(this.f);
+    }
+  }
+}
+''');
+    await assertHasAssistAt('f is', '''
+class C {
+  num f = 0;
+
+  void m() {
+    var f = this.f;
+    if (f is int) {
+      print(this.f);
+    }
+  }
+}
+''');
+  }
+
+  Future<void> test_is_simple() async {
+    await resolveTestUnit('''
+class C {
+  num f = 0;
+
+  void m() {
+    if (f is int) {
+      print((f as int).abs());
+    }
+  }
+}
+''');
+    await assertHasAssistAt('f is', '''
+class C {
+  num f = 0;
+
+  void m() {
+    var f = this.f;
+    if (f is int) {
+      print((f as int).abs());
+    }
+  }
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ShadowFieldWithNNBDTest extends ShadowFieldTest {
+  @override
+  AssistKind get kind => DartAssistKind.SHADOW_FIELD;
+
+  @override
+  void setUp() {
+    super.setUp();
+    createAnalysisOptionsFile(experiments: ['non-nullable']);
+  }
+
+  Future<void> test_notNull() async {
+    await resolveTestUnit('''
+class C {
+  int? f;
+
+  void m() {
+    if (f != null) {
+      print(f!.abs());
+    }
+  }
+}
+''');
+    await assertHasAssistAt('f !=', '''
+class C {
+  int? f;
+
+  void m() {
+    var f = this.f;
+    if (f != null) {
+      print(f!.abs());
+    }
+  }
+}
+''');
+  }
+
+  Future<void> test_notNull_assigned() async {
+    await resolveTestUnit('''
+class C {
+  int? f;
+
+  void m() {
+    if (f != null) {
+      print(f!.abs());
+    }
+    f = 0;
+    print(f!.abs());
+  }
+}
+''');
+    await assertNoAssistAt('f != ');
+  }
+
+  Future<void> test_notNull_referencedViaThis() async {
+    await resolveTestUnit('''
+class C {
+  int? f;
+
+  void m() {
+    if (f != null) {
+      print(this.f!);
+    }
+  }
+}
+''');
+    await assertHasAssistAt('f != ', '''
+class C {
+  int? f;
+
+  void m() {
+    var f = this.f;
+    if (f != null) {
+      print(this.f!);
+    }
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 2a1f7e2..4280ef9 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -72,6 +72,7 @@
 import 'replace_if_else_with_conditional_test.dart'
     as replace_if_else_with_conditional;
 import 'replace_with_var_test.dart' as replace_with_var;
+import 'shadow_field_test.dart' as shadow_field;
 import 'sort_child_property_last_test.dart' as sort_child_property_last;
 import 'split_and_condition_test.dart' as split_and_condition;
 import 'split_variable_declaration_test.dart' as split_variable_declaration;
@@ -146,6 +147,7 @@
     replace_conditional_with_if_else.main();
     replace_if_else_with_conditional.main();
     replace_with_var.main();
+    shadow_field.main();
     sort_child_property_last.main();
     split_and_condition.main();
     split_variable_declaration.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_test.dart
index f84f0ec..a3bca6d 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_test.dart
@@ -29,7 +29,7 @@
 abstract class A {
   int m();
 }
-int f(A a) => null == a /*LINT*/? null : a.m();
+int f(A a) => null == a ? null : a.m();
 ''');
     await assertHasFix('''
 abstract class A {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
index c55737c..0f607e6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
@@ -24,15 +24,24 @@
   String get lintCode => LintNames.avoid_relative_lib_imports;
 
   /// More coverage in the `convert_to_package_import_test.dart` assist test.
+  @failingTest
   Future<void> test_relativeImport() async {
-    addSource('/home/test/lib/foo.dart', '');
-    testFile = convertPath('/home/test/lib/src/test.dart');
+    // This test fails because any attempt to specify a relative path that
+    // includes 'lib' (which the lint requires) results in a malformed URI when
+    // trying to resolve the import.
+    newFile('/home/test/lib/foo/bar.dart', content: '''
+class C {}
+''');
     await resolveTestUnit('''
-import /*LINT*/'../lib/foo.dart';
+import '../lib/foo/bar.dart';
+
+C c;
 ''');
 
     await assertHasFix('''
 import 'package:test/lib/foo.dart';
+
+C c;
 ''');
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 6ed206e..f633431 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -24,9 +24,6 @@
 /// A base class defining support for writing fix processor tests that are
 /// specific to fixes associated with lints that use the FixKind.
 abstract class FixProcessorLintTest extends FixProcessorTest {
-  /// The marker used to indicate where the lint is expected to be found.
-  static const lintMarker = '/*LINT*/';
-
   /// The offset of the lint marker in the code being analyzed.
   int lintOffset = -1;
 
@@ -34,17 +31,6 @@
   String get lintCode;
 
   @override
-  Future<void> resolveTestUnit(String code) async {
-    lintOffset = code.indexOf(lintMarker);
-    if (lintOffset < 0) {
-      return super.resolveTestUnit(code);
-    }
-    var endOffset = lintOffset + lintMarker.length;
-    code = code.substring(0, lintOffset) + code.substring(endOffset);
-    return super.resolveTestUnit(code);
-  }
-
-  @override
   void setUp() {
     super.setUp();
     createAnalysisOptionsFile(lints: [lintCode]);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
index 5fccf8e..8d6e2f5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
@@ -26,12 +26,14 @@
   Future<void> test_field_type() async {
     await resolveTestUnit('''
 class C {
-  int /*LINT*/f = 2;
+  int _f = 2;
+  int get g => _f;
 }
 ''');
     await assertHasFix('''
 class C {
-  final int f = 2;
+  final int _f = 2;
+  int get g => _f;
 }
 ''');
   }
@@ -39,70 +41,15 @@
   Future<void> test_field_var() async {
     await resolveTestUnit('''
 class C {
-  var /*LINT*/f = 2;
+  var _f = 2;
+  int get g => _f;
 }
 ''');
     await assertHasFix('''
 class C {
-  final f = 2;
+  final _f = 2;
+  int get g => _f;
 }
 ''');
   }
-
-  Future<void> test_local_type() async {
-    await resolveTestUnit('''
-bad() {
-  int /*LINT*/x = 2;
-}
-''');
-    await assertHasFix('''
-bad() {
-  final int x = 2;
-}
-''');
-  }
-
-  Future<void> test_local_var() async {
-    await resolveTestUnit('''
-bad() {
-  var /*LINT*/x = 2;
-}
-''');
-    await assertHasFix('''
-bad() {
-  final x = 2;
-}
-''');
-  }
-
-  Future<void> test_noKeyword() async {
-    await resolveTestUnit('''
-class C {
-  /*LINT*/f = 2;
-}
-''');
-    await assertHasFix('''
-class C {
-  final f = 2;
-}
-''');
-  }
-
-  Future<void> test_topLevel_type() async {
-    await resolveTestUnit('''
-int /*LINT*/x = 2;
-''');
-    await assertHasFix('''
-final int x = 2;
-''');
-  }
-
-  Future<void> test_topLevel_var() async {
-    await resolveTestUnit('''
-var /*LINT*/x = 2;
-''');
-    await assertHasFix('''
-final x = 2;
-''');
-  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart
index cd3e80c..5b35b7c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_method_declaration_test.dart
@@ -134,7 +134,9 @@
 ''');
   }
 
+  @failingTest
   Future<void> test_setter() async {
+    // The lint doesn't catch unnecessary setters.
     await resolveTestUnit('''
 class A {
   int foo;
@@ -142,7 +144,7 @@
 
 class B extends A {
   @override
-  set /*LINT*/foo(int value) {
+  set foo(int value) {
     super.foo = value;
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
index d974b43..e26569b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
@@ -23,63 +23,41 @@
   @override
   String get lintCode => LintNames.null_closures;
 
-  /// Currently failing since the LINT annotation is tagging the ArgumentList
-  /// where the fix (and lint) expect a NullLiteral.
-  @failingTest
-  Future<void> test_null_closure_literal() async {
+  Future<void> test_named() async {
     await resolveTestUnit('''
-void f(dynamic x) { }
-main() {
-  f(null/*LINT*/);
+void f(List<int> l) {
+  l.firstWhere((e) => e.isEven, orElse: null);
 }
 ''');
     await assertHasFix('''
-void f(dynamic x) { }
-main() {
-  f(() => null);
+void f(List<int> l) {
+  l.firstWhere((e) => e.isEven, orElse: () => null);
 }
 ''');
   }
 
-  Future<void> test_null_closure_named_expression() async {
+  Future<void> test_named_withArgs() async {
     await resolveTestUnit('''
-main() {
-  [1, 3, 5].firstWhere((e) => e.isEven, orElse: null);
+void f(String s) {
+  s.splitMapJoin('', onNonMatch: null);
 }
 ''');
     await assertHasFix('''
-main() {
-  [1, 3, 5].firstWhere((e) => e.isEven, orElse: () => null);
+void f(String s) {
+  s.splitMapJoin('', onNonMatch: (String nonMatch) => null);
 }
 ''');
   }
 
-  Future<void> test_null_closure_named_expression_with_args() async {
+  Future<void> test_required() async {
     await resolveTestUnit('''
-void f({int closure(x, y)}) { }
-main() {
-  f(closure: /*LINT*/null);
+void f(List<int> l) {
+  l.firstWhere(null);
 }
 ''');
     await assertHasFix('''
-void f({int closure(x, y)}) { }
-main() {
-  f(closure: (x, y) => null);
-}
-''');
-  }
-
-  Future<void> test_null_closure_named_expression_with_args_2() async {
-    await resolveTestUnit('''
-void f({int closure(x, y, {z})}) { }
-main() {
-  f(closure: /*LINT*/null);
-}
-''');
-    await assertHasFix('''
-void f({int closure(x, y, {z})}) { }
-main() {
-  f(closure: (x, y, {z}) => null);
+void f(List<int> l) {
+  l.firstWhere(() => null);
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
new file mode 100644
index 0000000..a410f22
--- /dev/null
+++ b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_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.
+
+import 'package:test/test.dart';
+
+import '../../../tool/completion_metrics/metrics_util.dart';
+
+void main() {
+  group('Counter', () {
+    test('empty', () {
+      var counter = Counter('empty');
+      expect(counter.map, isEmpty);
+      expect(counter.totalCount, equals(0));
+    });
+
+    test('clear', () {
+      var counter = Counter('name');
+      counter.count('bucket-1', 1);
+      expect(counter.map, isNotEmpty);
+      expect(counter.totalCount, equals(1));
+
+      counter.clear();
+      expect(counter.map, isEmpty);
+      expect(counter.totalCount, equals(0));
+    });
+
+    test('getCountOf', () {
+      var counter = Counter('name');
+      counter.count('bucket-1', 1);
+      counter.count('bucket-2', 1);
+      counter.count('bucket-2', 1);
+      counter.count('bucket-3', 3);
+      expect(counter.name, equals('name'));
+      expect(counter.map, isNotEmpty);
+      expect(counter.totalCount, equals(6)); // 1 + 2 + 3
+      expect(counter.getCountOf('bucket-0'), equals(0));
+      expect(counter.getCountOf('bucket-1'), equals(1));
+      expect(counter.getCountOf('bucket-2'), equals(2));
+      expect(counter.getCountOf('bucket-3'), equals(3));
+    });
+  });
+
+  group('MeanReciprocalRankComputer', () {
+    test('empty', () {
+      var mrrc = MeanReciprocalRankComputer();
+      expect(mrrc.rankCount, equals(0));
+      expect(mrrc.ranks, isEmpty);
+      expect(mrrc.mrr, equals(0));
+    });
+
+    test('clear', () {
+      var mrrc = MeanReciprocalRankComputer();
+      mrrc.addRank(2);
+      expect(mrrc.rankCount, equals(1));
+      expect(mrrc.ranks, isNotEmpty);
+
+      mrrc.clear();
+      expect(mrrc.rankCount, equals(0));
+      expect(mrrc.ranks, isEmpty);
+    });
+
+    test('mmr- single value', () {
+      var mrrc = MeanReciprocalRankComputer();
+      mrrc.addRank(3);
+      mrrc.addRank(3);
+      mrrc.addRank(3);
+      mrrc.addRank(3);
+      mrrc.addRank(3);
+      expect(mrrc.rankCount, equals(5));
+      expect(mrrc.ranks, equals([3, 3, 3, 3, 3]));
+      expect(mrrc.mrr, doubleEquals(1 / 3));
+    });
+
+    test('mmr- example', () {
+      var mrrc = MeanReciprocalRankComputer();
+      mrrc.addRank(3);
+      mrrc.addRank(2);
+      mrrc.addRank(1);
+      expect(mrrc.rankCount, equals(3));
+      expect(mrrc.ranks, equals([3, 2, 1]));
+      expect(mrrc.mrr, doubleEquals(11 / 18));
+    });
+  });
+
+  group('Place', () {
+    test('none', () {
+      var place = Place.none();
+      expect(place.numerator, equals(0));
+      expect(place.denominator, equals(0));
+      expect(place.rank, equals(0));
+      expect(place, equals(Place.none()));
+      expect(place == Place(1, 1), isFalse);
+    });
+
+    test('default', () {
+      var place = Place(10, 20);
+      expect(place.numerator, equals(10));
+      expect(place.rank, equals(10));
+      expect(place.denominator, equals(20));
+      expect(place, equals(Place(10, 20)));
+      expect(place == Place(1, 2), isFalse);
+      expect(place == Place(10, 200), isFalse);
+      expect(place == Place(1, 20), isFalse);
+    });
+  });
+}
+
+/// Returns matcher that can compare double values.
+Matcher doubleEquals(expected) => _DoubleEquals(expected);
+
+class _DoubleEquals extends Matcher {
+  final double _value;
+  final int fractionDigits = 10;
+
+  const _DoubleEquals(this._value);
+
+  @override
+  Description describe(Description description) =>
+      description.add(_value.toString());
+
+  @override
+  bool matches(item, Map matchState) {
+    return item is num &&
+        item != null &&
+        _value != null &&
+        num.parse(item.toStringAsFixed(fractionDigits)) ==
+            num.parse(_value.toStringAsFixed(fractionDigits));
+  }
+}
diff --git a/pkg/analysis_server/test/tool/completion_metrics/test_all.dart b/pkg/analysis_server/test/tool/completion_metrics/test_all.dart
new file mode 100644
index 0000000..8ca30d9
--- /dev/null
+++ b/pkg/analysis_server/test/tool/completion_metrics/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 'metrics_util_test.dart' as metrics_util_test;
+
+void main() {
+  defineReflectiveSuite(() {
+    metrics_util_test.main();
+  }, name: 'completion_metrics');
+}
diff --git a/pkg/analysis_server/test/tool/test_all.dart b/pkg/analysis_server/test/tool/test_all.dart
index e70aa9b..659a796 100644
--- a/pkg/analysis_server/test/tool/test_all.dart
+++ b/pkg/analysis_server/test/tool/test_all.dart
@@ -5,9 +5,11 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'lsp_spec/test_all.dart' as lsp_spec;
+import 'completion_metrics/test_all.dart' as completion_metrics;
 
 void main() {
   defineReflectiveSuite(() {
+    completion_metrics.main();
     lsp_spec.main();
   }, name: 'tool');
 }
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index 913e94d..5fc90db 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -25,11 +25,18 @@
 import 'relevance_analyzers.dart';
 import 'visitors.dart';
 
-// TODO(jwren) have the analysis root and verbose option be configurable via a
-//  command line UX
-Future<void> main() async {
-  await CompletionCoverageMetrics('').compute();
-//  await RelevanceAnalyzerMetrics('', [RHSOfAsExpression()]).compute();
+Future<void> main(List<String> args) async {
+  if (args.isEmpty) {
+    print('Usage: a single absolute file path to analyze.');
+    io.exit(1);
+  } else {
+    if (args.length > 1 && args[1] == '--relevance-analyzers') {
+      await RelevanceAnalyzerMetrics(args[0], [RHSOfAsExpression()]).compute();
+    } else {
+      await CompletionCoverageMetrics(args[0]).compute();
+    }
+    io.exit(0);
+  }
 }
 
 /// This is the main metrics computer class for code completions. After the
diff --git a/pkg/analysis_server/tool/nnbd_migration/check_generated_test.dart b/pkg/analysis_server/tool/nnbd_migration/check_generated_test.dart
index 228656c..17708b30 100644
--- a/pkg/analysis_server/tool/nnbd_migration/check_generated_test.dart
+++ b/pkg/analysis_server/tool/nnbd_migration/check_generated_test.dart
@@ -2,11 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:test/test.dart';
+
 import 'generate_resources.dart' as generate_resources;
 
 /// Validate that the
 /// pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
 /// file was regenerated after changing upstream dependencies.
 void main() async {
-  generate_resources.main(['--verify']);
+  test('description', () {
+    generate_resources.verifyResourcesGDartGenerated(failVerification: fail);
+  }, skip: 'https://github.com/dart-lang/sdk/issues/40505');
 }
diff --git a/pkg/analysis_server/tool/nnbd_migration/generate_resources.dart b/pkg/analysis_server/tool/nnbd_migration/generate_resources.dart
index 7b0d82e..f295114 100644
--- a/pkg/analysis_server/tool/nnbd_migration/generate_resources.dart
+++ b/pkg/analysis_server/tool/nnbd_migration/generate_resources.dart
@@ -41,6 +41,8 @@
   } else {
     await compileWebFrontEnd();
 
+    print('');
+
     createResourcesGDart();
   }
 }
@@ -55,7 +57,17 @@
 final javascriptOutput = File(path.join('pkg', 'analysis_server', 'lib', 'src',
     'edit', 'nnbd_migration', 'resources', 'migration.js'));
 
-void verifyResourcesGDartGenerated() {
+final List<String> resourceTypes = [
+  '.css',
+  '.html',
+  '.js',
+];
+
+typedef VerificationFunction = void Function(String);
+
+void verifyResourcesGDartGenerated({
+  VerificationFunction failVerification = failGenerate,
+}) {
   print('Verifying that ${path.basename(resourcesFile.path)} is up-to-date...');
 
   // Find the hashes for the last generated version of resources.g.dart.
@@ -70,7 +82,7 @@
   // For all resources (modulo compiled JS ones), verify the hash.
   for (FileSystemEntity entity in resourceDir.listSync()) {
     String name = path.basename(entity.path);
-    if (!name.endsWith('.js') && !name.endsWith('.css')) {
+    if (!resourceTypes.contains(path.extension(name))) {
       continue;
     }
 
@@ -81,11 +93,11 @@
 
     String key = name.replaceAll('.', '_');
     if (!resourceHashes.containsKey(key)) {
-      failGenerate('No entry on resources.g.dart for $name');
+      failVerification('No entry on resources.g.dart for $name');
     } else {
       String hash = md5String((entity as File).readAsStringSync());
       if (hash != resourceHashes[key]) {
-        failGenerate('$name not up to date in resources.g.dart');
+        failVerification('$name not up to date in resources.g.dart');
       }
     }
   }
@@ -99,7 +111,7 @@
   }
   String hash = md5String(sourceCode.toString());
   if (hash != resourceHashes['migration_dart']) {
-    failGenerate('Compiled javascript not up to date in resources.g.dart');
+    failVerification('Compiled javascript not up to date in resources.g.dart');
   }
 
   print('Generated resources up to date.');
@@ -108,7 +120,7 @@
 void createResourcesGDart() {
   String content = generateResourceFile(resourceDir.listSync().where((entity) {
     String name = path.basename(entity.path);
-    return entity is File && (name.endsWith('.js') || name.endsWith('.css'));
+    return entity is File && resourceTypes.contains(path.extension(name));
   }).cast<File>());
 
   // write the content
@@ -132,6 +144,8 @@
 
   for (File resource in resources) {
     String name = path.basename(resource.path).replaceAll('.', '_');
+    print('adding $name...');
+
     buf.writeln();
     buf.writeln('String get $name {');
     buf.writeln('  return _$name ??= _decode(_${name}_base64);');
@@ -200,9 +214,16 @@
   String sdkBinDir = path.dirname(Platform.resolvedExecutable);
   String dart2jsPath = path.join(sdkBinDir, 'dart2js');
 
+  const minified = true;
+
   // dart2js -m -o output source
-  Process process = await Process.start(
-      dart2jsPath, ['-m', '-o', javascriptOutput.path, dartSources.path]);
+  Process process = await Process.start(dart2jsPath, [
+    if (minified) '-m',
+    '--no-frequency-based-minification',
+    '-o',
+    javascriptOutput.path,
+    dartSources.path,
+  ]);
   process.stdout.listen((List<int> data) => stdout.add(data));
   process.stderr.listen((List<int> data) => stderr.add(data));
   int exitCode = await process.exitCode;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 38c46a8..76ae5b2 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1374,6 +1374,14 @@
   /// Return the class defined in this library that has the given [name], or
   /// `null` if this library does not define a class with the given name.
   ClassElement getType(String className);
+
+  /// If a legacy library, return the legacy view on the [element].
+  /// Otherwise, return the original element.
+  T toLegacyElementIfOptOut<T extends Element>(T element);
+
+  /// If a legacy library, return the legacy version of the [type].
+  /// Otherwise, return the original type.
+  DartType toLegacyTypeIfOptOut(DartType type);
 }
 
 /// An element that can be (but is not required to be) defined within a method
diff --git a/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart b/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart
new file mode 100644
index 0000000..9ddfd9c
--- /dev/null
+++ b/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.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 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+
+/// Every [DartType] has the nullability suffix, elements declared in legacy
+/// libraries have types with star suffixes, and types in migrated libraries
+/// have none, question mark, or star suffixes.  Analyzer itself can handle
+/// mixtures of nullabilities with legacy and migrated libraries.
+///
+/// However analyzer clients saw only star suffixes so far.  Exposing other
+/// nullabilities is a breaking change, because types types with different
+/// nullabilities are not equal, `null` cannot be used where a non-nullable
+/// type is expected, etc.  When accessing elements and types that come from
+/// migrated libraries, while analyzing a legacy library, nullabilities must
+/// be erased, using [LibraryElement.toLegacyElementIfOptOut] and
+/// [LibraryElement.toLegacyTypeIfOptOut].  The client must explicitly do
+/// this, and explicitly specify that it knows how to handle nullabilities
+/// by setting this flag to `true`.
+///
+/// When this flag is `false` (by default), all types will return their
+/// nullability as star.  So, type equality and subtype checks will work
+/// as they worked before some libraries migrated.  Note, that during
+/// analysis (building element models, and resolving ASTs), analyzer will use
+/// actual nullabilities, according to the language specification, so report
+/// all corresponding errors, and perform necessary type operations.  It is
+/// only when the client later views on the types, they will look as legacy.
+class NullSafetyUnderstandingFlag {
+  static final _zoneKey = Object();
+
+  static bool get isEnabled {
+    return Zone.current[_zoneKey] ?? false;
+  }
+
+  /// Code that understands nullability should be run using this method,
+  /// otherwise all type operations will treat all nullabilities as star.
+  static R enableNullSafetyTypes<R>(R body()) {
+    return runZoned<R>(body, zoneValues: {_zoneKey: true});
+  }
+}
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 38cec6e..4873def 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -85,6 +85,7 @@
   CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME,
   CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME,
   CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+  CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE,
   CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD,
   CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
   CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 70d6aa7..5038e0f 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -129,6 +129,7 @@
         contextRoot,
         sf,
         options,
+        packages: createPackageMap(path),
         enableIndex: enableIndex,
         externalSummaries: summaryData);
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index d94e3f8..7ea2d29 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -11,11 +11,13 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart' show LibraryElement;
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context_root.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -130,6 +132,9 @@
   /// The analysis options to analyze with.
   AnalysisOptionsImpl _analysisOptions;
 
+  /// The [Packages] object with packages and their language versions.
+  Packages _packages;
+
   /// The [SourceFactory] is used to resolve URIs to paths and restore URIs
   /// from file paths.
   SourceFactory _sourceFactory;
@@ -285,11 +290,13 @@
       this.contextRoot,
       SourceFactory sourceFactory,
       this._analysisOptions,
-      {this.disableChangesAndCacheAllResults = false,
+      {@required Packages packages,
+      this.disableChangesAndCacheAllResults = false,
       this.enableIndex = false,
       SummaryDataStore externalSummaries,
       bool retainDataForTesting = false})
       : _logger = logger,
+        _packages = packages ?? Packages.empty,
         _sourceFactory = sourceFactory,
         _externalSummaries = externalSummaries,
         testingData = retainDataForTesting ? TestingData() : null {
@@ -487,11 +494,17 @@
   ///
   /// At least one of the optional parameters should be provided, but only those
   /// that represent state that has actually changed need be provided.
-  void configure(
-      {AnalysisOptions analysisOptions, SourceFactory sourceFactory}) {
+  void configure({
+    AnalysisOptions analysisOptions,
+    Packages packages,
+    SourceFactory sourceFactory,
+  }) {
     if (analysisOptions != null) {
       _analysisOptions = analysisOptions;
     }
+    if (packages != null) {
+      _packages = packages;
+    }
     if (sourceFactory != null) {
       _sourceFactory = sourceFactory;
     }
@@ -816,11 +829,9 @@
   ///
   /// The [path] must be absolute and normalized.
   Future<SourceKind> getSourceKind(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     _throwIfNotAbsolutePath(path);
     if (AnalysisEngine.isDartFileName(path)) {
-      FileState file = _fsState.getFileForPath(path);
+      FileState file = _fileTracker.verifyApiSignature(path);
       return file.isPart ? SourceKind.PART : SourceKind.LIBRARY;
     }
     return null;
@@ -1216,6 +1227,21 @@
       {bool withUnit = false,
       bool asIsIfPartWithoutLibrary = false,
       bool skipIfSameSignature = false}) {
+    return NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+      return _computeAnalysisResult2(
+        path,
+        withUnit: withUnit,
+        asIsIfPartWithoutLibrary: asIsIfPartWithoutLibrary,
+        skipIfSameSignature: skipIfSameSignature,
+      );
+    });
+  }
+
+  /// Unwrapped implementation of [_computeAnalysisResult].
+  AnalysisResult _computeAnalysisResult2(String path,
+      {bool withUnit = false,
+      bool asIsIfPartWithoutLibrary = false,
+      bool skipIfSameSignature = false}) {
     FileState file = _fsState.getFileForPath(path);
 
     // Prepare the library - the file itself, or the known library.
@@ -1446,7 +1472,7 @@
 
     var featureSetProvider = FeatureSetProvider.build(
       resourceProvider: resourceProvider,
-      contextRoot: contextRoot,
+      packages: _packages,
       sourceFactory: _sourceFactory,
       defaultFeatureSet: _analysisOptions.contextFeatures,
     );
@@ -1476,21 +1502,24 @@
       }
     }
 
-    if (_libraryContext == null) {
-      _libraryContext = LibraryContext(
-        session: currentSession,
-        logger: _logger,
-        fsState: fsState,
-        byteStore: _byteStore,
-        analysisOptions: _analysisOptions,
-        declaredVariables: declaredVariables,
-        sourceFactory: _sourceFactory,
-        externalSummaries: _externalSummaries,
-        targetLibrary: library,
-      );
-    } else {
-      _libraryContext.load2(library);
-    }
+    NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+      if (_libraryContext == null) {
+        _libraryContext = LibraryContext(
+          session: currentSession,
+          logger: _logger,
+          fsState: fsState,
+          byteStore: _byteStore,
+          analysisOptions: _analysisOptions,
+          declaredVariables: declaredVariables,
+          sourceFactory: _sourceFactory,
+          externalSummaries: _externalSummaries,
+          targetLibrary: library,
+        );
+      } else {
+        _libraryContext.load2(library);
+      }
+    });
+
     return _libraryContext;
   }
 
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 2f7abdf..0bbaee5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
@@ -51,7 +50,7 @@
 
   static FeatureSetProvider build({
     @required ResourceProvider resourceProvider,
-    @required ContextRoot contextRoot,
+    @required Packages packages,
     @required SourceFactory sourceFactory,
     @required FeatureSet defaultFeatureSet,
   }) {
@@ -61,8 +60,6 @@
       defaultFeatureSet,
     );
 
-    var packages = _findPackages(resourceProvider, contextRoot);
-
     return FeatureSetProvider._(
       sdkFeatureSet: sdkFeatureSet,
       packages: packages,
@@ -97,16 +94,4 @@
 
     return defaultFeatureSet;
   }
-
-  static Packages _findPackages(
-    ResourceProvider resourceProvider,
-    ContextRoot contextRoot,
-  ) {
-    if (contextRoot == null) {
-      return Packages(const {});
-    }
-
-    var rootFolder = resourceProvider.getFolder(contextRoot.root);
-    return findPackagesFrom(resourceProvider, rootFolder);
-  }
 }
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 19c32b4..f5af931 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -83,6 +83,8 @@
             _typeProvider, declaredVariables,
             typeSystem: _typeSystem, experimentStatus: featureSet);
 
+  bool get _isNonNullableByDefault => _currentLibrary.isNonNullableByDefault;
+
   @override
   void visitAnnotation(Annotation node) {
     super.visitAnnotation(node);
@@ -230,40 +232,10 @@
 
   @override
   void visitSwitchStatement(SwitchStatement node) {
-    // TODO(paulberry): to minimize error messages, it would be nice to
-    // compare all types with the most popular type rather than the first
-    // type.
-    NodeList<SwitchMember> switchMembers = node.members;
-    bool foundError = false;
-    DartType firstType;
-    for (SwitchMember switchMember in switchMembers) {
-      if (switchMember is SwitchCase) {
-        Expression expression = switchMember.expression;
-        DartObjectImpl caseResult = _validate(
-            expression, CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION);
-        if (caseResult != null) {
-          _reportErrorIfFromDeferredLibrary(
-              expression,
-              CompileTimeErrorCode
-                  .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY);
-          DartObject value = caseResult;
-          if (firstType == null) {
-            firstType = value.type;
-          } else {
-            DartType nType = value.type;
-            if (firstType != nType) {
-              _errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
-                  expression,
-                  [expression.toSource(), firstType]);
-              foundError = true;
-            }
-          }
-        }
-      }
-    }
-    if (!foundError) {
-      _checkForCaseExpressionTypeImplementsEquals(node, firstType);
+    if (_isNonNullableByDefault) {
+      _validateSwitchStatement_nullSafety(node);
+    } else {
+      _validateSwitchStatement_legacy(node);
     }
     super.visitSwitchStatement(node);
   }
@@ -296,27 +268,6 @@
     }
   }
 
-  /// This verifies that the passed switch statement does not have a case
-  /// expression with the operator '==' overridden.
-  ///
-  /// @param node the switch statement to evaluate
-  /// @param type the common type of all 'case' expressions
-  /// @return `true` if and only if an error code is generated on the passed
-  ///         node.
-  /// See [CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS].
-  bool _checkForCaseExpressionTypeImplementsEquals(
-      SwitchStatement node, DartType type) {
-    if (!_implementsEqualsWhenNotAllowed(type)) {
-      return false;
-    }
-    // report error
-    _errorReporter.reportErrorForToken(
-        CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
-        node.switchKeyword,
-        [type]);
-    return true;
-  }
-
   /// Verify that the given [type] does not reference any type parameters.
   ///
   /// See [CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS].
@@ -579,6 +530,101 @@
       }
     }
   }
+
+  void _validateSwitchStatement_legacy(SwitchStatement node) {
+    // TODO(paulberry): to minimize error messages, it would be nice to
+    // compare all types with the most popular type rather than the first
+    // type.
+    bool foundError = false;
+    DartType firstType;
+    for (var switchMember in node.members) {
+      if (switchMember is SwitchCase) {
+        Expression expression = switchMember.expression;
+
+        DartObjectImpl expressionValue = _validate(
+          expression,
+          CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION,
+        );
+        if (expressionValue == null) {
+          continue;
+        }
+
+        _reportErrorIfFromDeferredLibrary(
+          expression,
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+        );
+
+        if (firstType == null) {
+          firstType = expressionValue.type;
+        } else {
+          var expressionValueType = expressionValue.type;
+          if (firstType != expressionValueType) {
+            _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
+              expression,
+              [expression.toSource(), firstType],
+            );
+            foundError = true;
+          }
+        }
+      }
+    }
+
+    if (foundError) {
+      return;
+    }
+
+    if (_implementsEqualsWhenNotAllowed(firstType)) {
+      _errorReporter.reportErrorForToken(
+        CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+        node.switchKeyword,
+        [firstType],
+      );
+    }
+  }
+
+  void _validateSwitchStatement_nullSafety(SwitchStatement node) {
+    var switchType = node.expression.staticType;
+    for (var switchMember in node.members) {
+      if (switchMember is SwitchCase) {
+        Expression expression = switchMember.expression;
+
+        DartObjectImpl expressionValue = _validate(
+          expression,
+          CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION,
+        );
+        if (expressionValue == null) {
+          continue;
+        }
+
+        _reportErrorIfFromDeferredLibrary(
+          expression,
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+        );
+
+        var expressionType = expressionValue.type;
+
+        if (_implementsEqualsWhenNotAllowed(expressionType)) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+            expression,
+            [expressionType],
+          );
+        }
+
+        if (!_typeSystem.isSubtypeOf(expressionType, switchType)) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE,
+            expression,
+            [expressionType, switchType],
+          );
+        }
+      }
+    }
+  }
 }
 
 class _ConstLiteralVerifier {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 6e0cf47..6512d66 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -24,6 +24,7 @@
 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';
@@ -66,7 +67,7 @@
 
   /// The type system.  This is used to guess the types of constants when their
   /// exact value is unknown.
-  final TypeSystem typeSystem;
+  final TypeSystemImpl typeSystem;
 
   /// The helper for evaluating variables declared on the command line
   /// using '-D', and represented as [DeclaredVariables].
@@ -108,7 +109,7 @@
   }
 
   bool get _isNonNullableByDefault {
-    return (typeSystem as TypeSystemImpl).isNonNullableByDefault;
+    return typeSystem.isNonNullableByDefault;
   }
 
   DartObjectImpl get _nullObject {
@@ -936,7 +937,7 @@
       return true;
     }
     var objType = obj.type;
-    return typeSystem.isSubtypeOf(objType, type);
+    return typeSystem.isSubtypeOf2(objType, type);
   }
 
   /// Determine whether the given string is a valid name for a public symbol
@@ -1038,7 +1039,7 @@
   ExperimentStatus get experimentStatus => evaluationEngine.experimentStatus;
 
   /// Convenience getter to gain access to the [evaluationEngine]'s type system.
-  TypeSystem get typeSystem => evaluationEngine.typeSystem;
+  TypeSystemImpl get typeSystem => evaluationEngine.typeSystem;
 
   /// Convenience getter to gain access to the [evaluationEngine]'s type
   /// provider.
@@ -1210,7 +1211,7 @@
     ParameterizedType elseType = elseResult.type;
     return DartObjectImpl.validWithUnknownValue(
       typeSystem,
-      typeSystem.leastUpperBound(thenType, elseType) as ParameterizedType,
+      typeSystem.getLeastUpperBound(thenType, elseType) as ParameterizedType,
     );
   }
 
@@ -1671,7 +1672,7 @@
         // TODO(brianwilkerson) Figure out why the static type is sometimes null.
         DartType staticType = condition.staticType;
         if (staticType == null ||
-            typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
+            typeSystem.isAssignableTo2(staticType, _typeProvider.boolType)) {
           // If the static type is not assignable, then we will have already
           // reported this error.
           // TODO(mfairhurst) get the FeatureSet to suppress this for nnbd too.
@@ -1690,6 +1691,13 @@
     element = element?.declaration;
     Element variableElement =
         element is PropertyAccessorElement ? element.variable : element;
+
+    if (node is SimpleIdentifier &&
+        (node.tearOffTypeArgumentTypes?.any(_hasAppliedTypeParameters) ??
+            false)) {
+      _error(node, null);
+    }
+
     if (variableElement is VariableElementImpl) {
       // We access values of constant variables here in two cases: when we
       // compute values of other constant variables, or when we compute values
@@ -1755,6 +1763,13 @@
     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(
@@ -1801,6 +1816,27 @@
   }
 }
 
+/// 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 visitTypeParameterType(_) {
+    result = true;
+    // Stop visiting at this point.
+    return false;
+  }
+
+  @override
+  bool defaultDartType(_) => true; // Continue visiting in this case.
+}
+
 /// A utility class that contains methods for manipulating instances of a Dart
 /// class and for collecting errors during evaluation.
 class DartObjectComputer {
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 726e1ea..c032be1 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -262,7 +262,7 @@
     if (isNull) {
       return this;
     }
-    if (!typeSystem.isSubtypeOf(type, (castType._state as TypeState)._type)) {
+    if (!typeSystem.isSubtypeOf2(type, (castType._state as TypeState)._type)) {
       throw EvaluationException(
           CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
     }
@@ -478,7 +478,7 @@
         state = BoolState.FALSE_STATE;
       }
     } else {
-      state = BoolState.from(typeSystem.isSubtypeOf(type, typeType));
+      state = BoolState.from(typeSystem.isSubtypeOf2(type, typeType));
     }
     return DartObjectImpl(typeSystem, typeSystem.typeProvider.boolType, state);
   }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f17b1be..dfb9c92 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -16,6 +16,8 @@
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/display_string_builder.dart';
+import 'package:analyzer/src/dart/element/member.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_provider.dart';
@@ -5663,6 +5665,18 @@
   }
 
   @override
+  T toLegacyElementIfOptOut<T extends Element>(T element) {
+    if (isNonNullableByDefault) return element;
+    return Member.legacy(element);
+  }
+
+  @override
+  DartType toLegacyTypeIfOptOut(DartType type) {
+    if (isNonNullableByDefault) return type;
+    return NullabilityEliminator.perform(typeProvider, type);
+  }
+
+  @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
     _definingCompilationUnit?.accept(visitor);
diff --git a/pkg/analyzer/lib/src/dart/element/top_merge.dart b/pkg/analyzer/lib/src/dart/element/top_merge.dart
index 147e00b..334b6c2 100644
--- a/pkg/analyzer/lib/src/dart/element/top_merge.dart
+++ b/pkg/analyzer/lib/src/dart/element/top_merge.dart
@@ -236,8 +236,8 @@
       if (R_isCovariant) {
         var T1 = T_parameter.type;
         var T2 = S_parameter.type;
-        var T1_isSubtype = typeSystem.isSubtypeOf(T1, T2);
-        var T2_isSubtype = typeSystem.isSubtypeOf(T2, T1);
+        var T1_isSubtype = typeSystem.isSubtypeOf2(T1, T2);
+        var T2_isSubtype = typeSystem.isSubtypeOf2(T2, T1);
         if (T1_isSubtype && T2_isSubtype) {
           // if `T1 <: T2` and `T2 <: T1`, then the result is
           // `NNBD_TOP_MERGE(T1, T2)`, and it is covariant.
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index d240f68..27174ba 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/token.dart';
 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';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
@@ -241,9 +242,19 @@
   List<TypeParameterElement> get typeParameters => const [] /*TODO(paulberry)*/;
 
   @override
-  bool operator ==(Object object) {
-    if (object is FunctionTypeImpl) {
-      if (typeFormals.length != object.typeFormals.length) {
+  bool operator ==(Object other) {
+    if (identical(other, this)) {
+      return true;
+    }
+
+    if (other is FunctionTypeImpl) {
+      if (NullSafetyUnderstandingFlag.isEnabled) {
+        if (other.nullabilitySuffix != nullabilitySuffix) {
+          return false;
+        }
+      }
+
+      if (other.typeFormals.length != typeFormals.length) {
         return false;
       }
       // `<T>T -> T` should be equal to `<U>U -> U`
@@ -251,17 +262,15 @@
       // variables, and see if the result is equal.
       if (typeFormals.isNotEmpty) {
         List<DartType> freshVariables = FunctionTypeImpl.relateTypeFormals(
-            this, object, (t, s, _, __) => t == s);
+            this, other, (t, s, _, __) => t == s);
         if (freshVariables == null) {
           return false;
         }
-        return instantiate(freshVariables) ==
-            object.instantiate(freshVariables);
+        return instantiate(freshVariables) == other.instantiate(freshVariables);
       }
 
-      return returnType == object.returnType &&
-          _equalParameters(parameters, object.parameters) &&
-          nullabilitySuffix == object.nullabilitySuffix;
+      return other.returnType == returnType &&
+          _equalParameters(other.parameters, parameters);
     }
     return false;
   }
@@ -930,14 +939,18 @@
       (element.library.session as AnalysisSessionImpl).inheritanceManager;
 
   @override
-  bool operator ==(Object object) {
-    if (identical(object, this)) {
+  bool operator ==(Object other) {
+    if (identical(other, this)) {
       return true;
     }
-    if (object is InterfaceTypeImpl) {
-      return element == object.element &&
-          TypeImpl.equalArrays(typeArguments, object.typeArguments) &&
-          nullabilitySuffix == object.nullabilitySuffix;
+    if (other is InterfaceTypeImpl) {
+      if (NullSafetyUnderstandingFlag.isEnabled) {
+        if (other.nullabilitySuffix != nullabilitySuffix) {
+          return false;
+        }
+      }
+      return other.element == element &&
+          TypeImpl.equalArrays(other.typeArguments, typeArguments);
     }
     return false;
   }
@@ -1553,7 +1566,7 @@
     for (DartType type in types) {
       // If any existing type in the bucket is more specific than this type,
       // then we can ignore this type.
-      if (bucket.any((DartType t) => typeSystem.isSubtypeOf(t, type))) {
+      if (bucket.any((DartType t) => typeSystem.isSubtypeOf2(t, type))) {
         continue;
       }
       // Otherwise, we need to add this type to the bucket and remove any types
@@ -1561,7 +1574,7 @@
       bool added = false;
       int i = 0;
       while (i < bucket.length) {
-        if (typeSystem.isSubtypeOf(type, bucket[i])) {
+        if (typeSystem.isSubtypeOf2(type, bucket[i])) {
           if (added) {
             if (i < bucket.length - 1) {
               bucket[i] = bucket.removeLast();
@@ -2057,9 +2070,13 @@
       return true;
     }
 
-    if (other is TypeParameterTypeImpl &&
-        other.nullabilitySuffix == nullabilitySuffix &&
-        other.element == element) {
+    if (other is TypeParameterTypeImpl && other.element == element) {
+      if (NullSafetyUnderstandingFlag.isEnabled) {
+        if (other.nullabilitySuffix != nullabilitySuffix) {
+          return false;
+        }
+      }
+
       // If the same declaration, or the same promoted element.
       if (identical(other.element, element)) {
         return true;
diff --git a/pkg/analyzer/lib/src/dart/element/type_visitor.dart b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
index eff54ee..11ef758 100644
--- a/pkg/analyzer/lib/src/dart/element/type_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_visitor.dart
@@ -135,3 +135,32 @@
     throw UnimplementedError('(${type.runtimeType}) $type');
   }
 }
+
+/// Recursively visits a DartType tree until any visit method returns `false`.
+abstract class RecursiveTypeVisitor extends DartTypeVisitor<bool> {
+  /// Visit each item in the list until one returns `false`, in which case, this
+  /// will also return `false`.
+  bool visitChildren(Iterable<DartType> types) =>
+      types.every((type) => DartTypeVisitor.visit(type, this));
+
+  @override
+  bool visitFunctionType(FunctionType type) => visitChildren([
+        type.returnType,
+        ...type.typeFormals
+            .map((formal) => formal.bound)
+            .where((type) => type != null),
+        ...type.parameters.map((param) => param.type),
+      ]);
+
+  @override
+  bool visitFunctionTypeBuilder(FunctionTypeBuilder type) =>
+      throw StateError("Builders should not exist outside substitution.");
+
+  @override
+  bool visitInterfaceType(InterfaceType type) =>
+      visitChildren(type.typeArguments);
+
+  @override
+  bool visitNamedTypeBuilder(NamedTypeBuilder type) =>
+      throw StateError("Builders should not exist outside substitution.");
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 56a67ea..098854c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -293,7 +293,7 @@
       _inferenceHelper.recordStaticType(node, type);
 
       var leftWriteType = _getStaticType2(node.leftHandSide);
-      if (!_typeSystem.isAssignableTo(type, leftWriteType)) {
+      if (!_typeSystem.isAssignableTo2(type, leftWriteType)) {
         _resolver.errorReporter.reportErrorForNode(
           StaticTypeWarningCode.INVALID_ASSIGNMENT,
           node.rightHandSide,
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 a1cc73a..fd27511 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -153,7 +153,7 @@
     if (receiverType.isVoid) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.USE_OF_VOID_RESULT, receiverExpression);
-    } else if (!_typeSystem.isAssignableTo(receiverType, node.extendedType)) {
+    } else if (!_typeSystem.isAssignableTo2(receiverType, node.extendedType)) {
       _errorReporter.reportErrorForNode(
         CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE,
         receiverExpression,
@@ -212,7 +212,7 @@
         var boundType = typeParameters[i].bound;
         if (boundType != null) {
           boundType = substitution.substituteType(boundType);
-          if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+          if (!_typeSystem.isSubtypeOf2(argType, boundType)) {
             _errorReporter.reportErrorForNode(
               CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
               typeArgumentList.arguments[i],
@@ -429,7 +429,7 @@
 
   /// Ask the type system for a subtype check.
   bool _isSubtypeOf(DartType type1, DartType type2) =>
-      _typeSystem.isSubtypeOf(type1, type2);
+      _typeSystem.isSubtypeOf2(type1, type2);
 
   List<DartType> _listOfDynamic(List<TypeParameterElement> parameters) {
     return List<DartType>.filled(parameters.length, _dynamicType);
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 f682667..f51e9a1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -317,7 +317,7 @@
 
   @override
   bool isSubtypeOf(DartType leftType, DartType rightType) {
-    return typeSystem.isSubtypeOf(leftType, rightType);
+    return typeSystem.isSubtypeOf2(leftType, rightType);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 115f447..359d327 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -423,7 +423,10 @@
       InterfaceType receiverType, SimpleIdentifier nameNode, String name) {
     if (_isCoreFunction(receiverType) &&
         name == FunctionElement.CALL_METHOD_NAME) {
-      _resolver.nullableDereferenceVerifier.expression(receiver);
+      _resolver.nullableDereferenceVerifier.expression(
+        receiver,
+        type: receiverType,
+      );
       _setDynamicResolution(node);
       return;
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 687889f..0d5cb00 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -71,7 +71,7 @@
   void _checkForInvalidAssignmentIncDec(
       AstNode node, Expression operand, DartType type) {
     var operandWriteType = _getWriteType(operand);
-    if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+    if (!_typeSystem.isAssignableTo2(type, operandWriteType)) {
       _resolver.errorReporter.reportErrorForNode(
         StaticTypeWarningCode.INVALID_ASSIGNMENT,
         node,
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index d985231..46e6e28 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -71,7 +71,7 @@
   void _checkForInvalidAssignmentIncDec(
       AstNode node, Expression operand, DartType type) {
     var operandWriteType = _getStaticType(operand);
-    if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+    if (!_typeSystem.isAssignableTo2(type, operandWriteType)) {
       _resolver.errorReporter.reportErrorForNode(
         StaticTypeWarningCode.INVALID_ASSIGNMENT,
         node,
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 52817e6..238602d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -168,7 +168,7 @@
       }
 
       var elseType = _computeElementType(elseElement);
-      return _typeSystem.leastUpperBound(thenType, elseType);
+      return _typeSystem.getLeastUpperBound(thenType, elseType);
     } else if (element is MapLiteralEntry) {
       // This error will be reported elsewhere.
       return _typeProvider.dynamicType;
@@ -271,9 +271,9 @@
       DartType unwrappedContextType = unwrap(contextType);
       // TODO(brianwilkerson) Find out what the "greatest closure" is and use that
       // where [unwrappedContextType] is used below.
-      bool isIterable = _typeSystem.isSubtypeOf(
+      bool isIterable = _typeSystem.isSubtypeOf2(
           unwrappedContextType, _typeProvider.iterableForSetMapDisambiguation);
-      bool isMap = _typeSystem.isSubtypeOf(
+      bool isMap = _typeSystem.isSubtypeOf2(
           unwrappedContextType, _typeProvider.mapForSetMapDisambiguation);
       if (isIterable && !isMap) {
         return _LiteralResolution(
@@ -332,7 +332,7 @@
       DartType expressionType = element.expression.staticType;
       bool isNull = expressionType.isDartCoreNull;
       if (!isNull && expressionType is InterfaceType) {
-        if (_typeSystem.isSubtypeOf(
+        if (_typeSystem.isSubtypeOf2(
             expressionType, _typeProvider.iterableForSetMapDisambiguation)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.iterableElement);
@@ -340,7 +340,7 @@
               elementType: iterableType.typeArguments[0],
               keyType: null,
               valueType: null);
-        } else if (_typeSystem.isSubtypeOf(
+        } else if (_typeSystem.isSubtypeOf2(
             expressionType, _typeProvider.mapForSetMapDisambiguation)) {
           InterfaceType mapType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.mapElement);
@@ -475,10 +475,10 @@
     bool contextProvidesAmbiguityResolutionClues =
         contextType != null && contextType is! UnknownInferredType;
     bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(
+        _typeSystem.isSubtypeOf2(
             contextType, _typeProvider.iterableForSetMapDisambiguation);
     bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(
+        _typeSystem.isSubtypeOf2(
             contextType, _typeProvider.mapForSetMapDisambiguation);
     if (contextIsIterable && !contextIsMap) {
       return _toSetType(literal, contextType, inferredTypes);
@@ -830,7 +830,7 @@
     } else if (second == null) {
       return first;
     } else {
-      return typeSystem.leastUpperBound(first, second);
+      return typeSystem.getLeastUpperBound(first, second);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index cfd68d6..e568a7f 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -1305,7 +1305,7 @@
   ///
   /// Returns `true` if and only if an unnecessary cast hint should be generated
   /// on [node].  See [HintCode.UNNECESSARY_CAST].
-  static bool isUnnecessaryCast(AsExpression node, TypeSystem typeSystem) {
+  static bool isUnnecessaryCast(AsExpression node, TypeSystemImpl typeSystem) {
     // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to
     // remove the (x is! TypeParameterType) checks.
     AstNode parent = node.parent;
@@ -1329,8 +1329,8 @@
           elseType != null &&
           !thenType.isDynamic &&
           !elseType.isDynamic &&
-          !typeSystem.isSubtypeOf(thenType, elseType) &&
-          !typeSystem.isSubtypeOf(elseType, thenType)) {
+          !typeSystem.isSubtypeOf2(thenType, elseType) &&
+          !typeSystem.isSubtypeOf2(elseType, thenType)) {
         return false;
       }
     }
@@ -1340,7 +1340,7 @@
         rhsType != null &&
         !lhsType.isDynamic &&
         !rhsType.isDynamic &&
-        typeSystem.isSubtypeOf(lhsType, rhsType)) {
+        typeSystem.isSubtypeOf2(lhsType, rhsType)) {
       return true;
     }
     return false;
diff --git a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
index 3f626bd..0acc357 100644
--- a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
+++ b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
@@ -49,7 +49,7 @@
       {@required ErrorCode errorCode, List<Object> arguments}) {
     var type = expression.staticType;
     if (!_checkForUseOfVoidResult(expression) &&
-        !_typeSystem.isAssignableTo(type, _boolType)) {
+        !_typeSystem.isAssignableTo2(type, _boolType)) {
       if (type.element == _boolElement) {
         _nullableDereferenceVerifier.report(expression, type);
       } else {
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 70fc7dc..d5b1143 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -611,6 +611,18 @@
           "The switch case expression type '{0}' can't override the == "
               "operator.");
 
+  /// Given a switch statement which switches over an expression `e` of type
+  /// `T`, where the cases are dispatched based on expressions `e0` ... `ek`:
+  ///
+  /// It is an error if any of the `ei` evaluate to a value whose static type
+  /// is not a subtype of `T`.
+  static const CompileTimeErrorCode
+      CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE =
+      CompileTimeErrorCode(
+          'CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE',
+          "The switch case expression type '{0}' must be a subtype of the "
+              "switch expression type '{1}'.");
+
   /**
    * 10.11 Class Member Conflicts: Let `C` be a class. It is a compile-time
    * error if `C` declares a constructor named `C.n`, and a static member with
@@ -7048,10 +7060,15 @@
   // is used and type arguments are provided, but the number of type arguments
   // isn't the same as the number of type parameters.
   //
+  // The analyzer also produces this diagnostic when a constructor is invoked
+  // and the number of type arguments doesn't match the number of type
+  // parameters declared for the class.
+  //
   // #### Examples
   //
   // The following code produces this diagnostic because `C` has one type
-  // parameter but two type arguments are provided:
+  // parameter but two type arguments are provided when it is used as a type
+  // annotation:
   //
   // ```dart
   // class C<E> {}
@@ -7059,6 +7076,15 @@
   // void f([!C<int, int>!] x) {}
   // ```
   //
+  // The following code produces this diagnostic because `C` declares one type
+  // parameter, but two type arguments are provided when creating an instance:
+  //
+  // ```dart
+  // class C<E> {}
+  //
+  // var c = [!C<int, int>!]();
+  // ```
+  //
   // #### Common fixes
   //
   // Add or remove type arguments, as necessary, to match the number of type
@@ -8311,6 +8337,7 @@
           'MISSING_ENUM_CONSTANT_IN_SWITCH', "Missing case clause for '{0}'.",
           correction: "Try adding a case clause for the missing constant, or "
               "adding a default clause.",
+          errorSeverity: ErrorSeverity.WARNING,
           hasPublishedDocs: true);
 
   @Deprecated('No longer an error in the spec and no longer generated')
diff --git a/pkg/analyzer/lib/src/error/correct_override.dart b/pkg/analyzer/lib/src/error/correct_override.dart
index 7e0a016..f88bc43 100644
--- a/pkg/analyzer/lib/src/error/correct_override.dart
+++ b/pkg/analyzer/lib/src/error/correct_override.dart
@@ -38,7 +38,7 @@
     @required ExecutableElement superMember,
   }) {
     var superType = superMember.type;
-    if (!_typeSystem.isSubtypeOf(_thisTypeForSubtype, superType)) {
+    if (!_typeSystem.isSubtypeOf2(_thisTypeForSubtype, superType)) {
       return false;
     }
 
@@ -71,8 +71,10 @@
             );
           }
 
-          if (!_typeSystem.isSubtypeOf(superParameterType, thisParameterType) &&
-              !_typeSystem.isSubtypeOf(thisParameterType, superParameterType)) {
+          if (!_typeSystem.isSubtypeOf2(
+                  superParameterType, thisParameterType) &&
+              !_typeSystem.isSubtypeOf2(
+                  thisParameterType, superParameterType)) {
             return false;
           }
         }
diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
index 98834a1..40d859f 100644
--- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart
+++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
@@ -315,7 +315,7 @@
           int length = visitedTypes.length;
           for (int j = 0; j < length; j++) {
             DartType type = visitedTypes[j];
-            if (_typeSystem.isSubtypeOf(currentType, type)) {
+            if (_typeSystem.isSubtypeOf2(currentType, type)) {
               CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
               int offset = catchClause.offset;
               int length = lastCatchClause.end - offset;
diff --git a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
index c9287f4..c21040b 100644
--- a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
+++ b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart
@@ -115,8 +115,8 @@
 
   bool _match(DartType getterType, DartType setterType) {
     return _isNonNullableByDefault
-        ? _typeSystem.isSubtypeOf(getterType, setterType)
-        : _typeSystem.isAssignableTo(getterType, setterType);
+        ? _typeSystem.isSubtypeOf2(getterType, setterType)
+        : _typeSystem.isAssignableTo2(getterType, setterType);
   }
 
   /// Return the return type of the [getter].
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 0e3b487..798717c 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -264,7 +264,7 @@
     AstNode node,
     Uri libraryUri,
     ExecutableElement member, {
-    List<AstNode> methodParameterNodes,
+    List<FormalParameter> methodParameterNodes,
   }) {
     if (member == null) return;
     if (member.isStatic) return;
@@ -293,7 +293,9 @@
         errorNode: node,
       );
 
-      if (methodParameterNodes != null) {
+      if (superMember is MethodElement &&
+          member is MethodElement &&
+          methodParameterNodes != null) {
         _checkForOptionalParametersDifferentDefaultValues(
           superMember,
           member,
@@ -385,11 +387,12 @@
   }
 
   void _checkForOptionalParametersDifferentDefaultValues(
-    ExecutableElement baseExecutable,
-    ExecutableElement derivedExecutable,
-    List<AstNode> derivedParameterNodes,
+    MethodElement baseExecutable,
+    MethodElement derivedExecutable,
+    List<FormalParameter> derivedParameterNodes,
   ) {
-    var derivedOptionalNodes = <AstNode>[];
+    var derivedIsAbstract = derivedExecutable.isAbstract;
+    var derivedOptionalNodes = <FormalParameter>[];
     var derivedOptionalElements = <ParameterElementImpl>[];
     var derivedParameterElements = derivedExecutable.parameters;
     for (var i = 0; i < derivedParameterElements.length; i++) {
@@ -417,6 +420,11 @@
     if (derivedOptionalElements[0].isNamed) {
       for (int i = 0; i < derivedOptionalElements.length; i++) {
         var derivedElement = derivedOptionalElements[i];
+        if (_isNonNullableByDefault &&
+            derivedIsAbstract &&
+            derivedElement.initializer == null) {
+          continue;
+        }
         var name = derivedElement.name;
         for (var j = 0; j < baseOptionalElements.length; j++) {
           var baseParameter = baseOptionalElements[j];
@@ -442,10 +450,16 @@
       for (var i = 0;
           i < derivedOptionalElements.length && i < baseOptionalElements.length;
           i++) {
+        var derivedElement = derivedOptionalElements[i];
+        if (_isNonNullableByDefault &&
+            derivedIsAbstract &&
+            derivedElement.initializer == null) {
+          continue;
+        }
         var baseElement = baseOptionalElements[i];
         if (baseElement.initializer != null) {
           var baseValue = baseElement.computeConstantValue();
-          var derivedResult = derivedOptionalElements[i].evaluationResult;
+          var derivedResult = derivedElement.evaluationResult;
           if (!_constantValuesEqual(derivedResult.value, baseValue)) {
             reporter.reportErrorForNode(
               StaticWarningCode
@@ -602,7 +616,7 @@
       var candidatesStr = conflict.candidates.map((candidate) {
         var className = candidate.enclosingElement.name;
         var typeStr = candidate.type.getDisplayString(
-          withNullability: typeSystem.isNonNullableByDefault,
+          withNullability: _isNonNullableByDefault,
         );
         return '$className.${name.name} ($typeStr)';
       }).join(', ');
@@ -615,6 +629,8 @@
     }
   }
 
+  bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
+
   void _reportInheritedAbstractMembers(List<ExecutableElement> elements) {
     if (elements == null) {
       return;
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 96f1ba6..d6090cc 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -48,7 +48,7 @@
   /// Check that the given [type] is assignable to the [elementType], otherwise
   /// report the list or set error on the [errorNode].
   void _checkAssignableToElementType(DartType type, AstNode errorNode) {
-    if (!typeSystem.isAssignableTo(type, elementType)) {
+    if (!typeSystem.isAssignableTo2(type, elementType)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -108,7 +108,7 @@
     }
 
     var keyType = entry.key.staticType;
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo2(keyType, mapKeyType)) {
       errorReporter.reportErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         entry.key,
@@ -117,7 +117,7 @@
     }
 
     var valueType = entry.value.staticType;
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo2(valueType, mapValueType)) {
       errorReporter.reportErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         entry.value,
@@ -155,7 +155,7 @@
     }
 
     var iterableElementType = iterableType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+    if (!typeSystem.isAssignableTo2(iterableElementType, elementType)) {
       var errorCode = forList
           ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -196,7 +196,7 @@
     }
 
     var keyType = mapType.typeArguments[0];
-    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+    if (!typeSystem.isAssignableTo2(keyType, mapKeyType)) {
       errorReporter.reportErrorForNode(
         StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
         expression,
@@ -205,7 +205,7 @@
     }
 
     var valueType = mapType.typeArguments[1];
-    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+    if (!typeSystem.isAssignableTo2(valueType, mapValueType)) {
       errorReporter.reportErrorForNode(
         StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
         expression,
diff --git a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
index d37a1ab..2e69e36 100644
--- a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
+++ b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
@@ -21,12 +21,13 @@
   })  : _typeSystem = typeSystem,
         _errorReporter = errorReporter;
 
-  bool expression(Expression expression) {
+  bool expression(Expression expression, {DartType type}) {
     if (!_typeSystem.isNonNullableByDefault) {
       return false;
     }
 
-    return _check(expression, expression.staticType);
+    type ??= expression.staticType;
+    return _check(expression, type);
   }
 
   void report(AstNode errorNode, DartType receiverType) {
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index dd84cbe..98e1df1 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -18,12 +18,18 @@
 
 class TypeArgumentsVerifier {
   final AnalysisOptionsImpl _options;
-  final TypeSystemImpl _typeSystem;
+  final LibraryElement _libraryElement;
   final ErrorReporter _errorReporter;
 
-  TypeArgumentsVerifier(this._options, this._typeSystem, this._errorReporter);
+  TypeArgumentsVerifier(
+    this._options,
+    this._libraryElement,
+    this._errorReporter,
+  );
 
-  TypeProvider get _typeProvider => _typeSystem.typeProvider;
+  TypeProvider get _typeProvider => _libraryElement.typeProvider;
+
+  TypeSystemImpl get _typeSystem => _libraryElement.typeSystem;
 
   void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     _checkTypeArguments(node);
@@ -223,17 +229,18 @@
       }
       DartType boundType = typeParameters[i].bound;
       if (argType != null && boundType != null) {
+        boundType = _libraryElement.toLegacyTypeIfOptOut(boundType);
         if (shouldSubstitute) {
           boundType = Substitution.fromPairs(typeParameters, typeArguments)
               .substituteType(boundType);
         }
 
-        if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+        if (!_typeSystem.isSubtypeOf2(argType, boundType)) {
           if (_shouldAllowSuperBoundedTypes(typeName)) {
             var replacedType =
                 (argType as TypeImpl).replaceTopAndBottom(_typeProvider);
             if (!identical(replacedType, argType) &&
-                _typeSystem.isSubtypeOf(replacedType, boundType)) {
+                _typeSystem.isSubtypeOf2(replacedType, boundType)) {
               // Bound is satisfied under super-bounded rules, so we're ok.
               continue;
             }
@@ -329,7 +336,7 @@
 
         var substitution = Substitution.fromPairs(fnTypeParams, typeArgs);
         var bound = substitution.substituteType(rawBound);
-        if (!_typeSystem.isSubtypeOf(argType, bound)) {
+        if (!_typeSystem.isSubtypeOf2(argType, bound)) {
           _errorReporter.reportErrorForNode(
               CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
               typeArgumentList[i],
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 0e5fab1..7f41b77 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1603,6 +1603,7 @@
             identifier.parent is CommentReference)) {
       Identifier setterId = SyntheticIdentifier('${identifier.name}=');
       element = _resolver.nameScope.lookup(setterId, _definingLibrary);
+      element = _resolver.toLegacyElement(element);
     }
     if (element == null) {
       InterfaceType enclosingType;
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 96a2965..abb22ee 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -275,7 +275,7 @@
     _typeSystem = _currentLibrary.typeSystem;
     _options = _currentLibrary.context.analysisOptions;
     _typeArgumentsVerifier =
-        TypeArgumentsVerifier(_options, _typeSystem, _errorReporter);
+        TypeArgumentsVerifier(_options, _currentLibrary, _errorReporter);
     _constructorFieldsVerifier = ConstructorFieldsVerifier(
       typeSystem: _typeSystem,
       errorReporter: _errorReporter,
@@ -1485,14 +1485,14 @@
     // Report specific problem when return type is incompatible
     FunctionType constructorType = declaration.declaredElement.type;
     DartType constructorReturnType = constructorType.returnType;
-    if (!_typeSystem.isAssignableTo(
+    if (!_typeSystem.isAssignableTo2(
         redirectedReturnType, constructorReturnType)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
           redirectedConstructor,
           [redirectedReturnType, constructorReturnType]);
       return;
-    } else if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) {
+    } else if (!_typeSystem.isSubtypeOf2(redirectedType, constructorType)) {
       // Check parameters.
       _errorReporter.reportErrorForNode(
           StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE,
@@ -1702,7 +1702,7 @@
       DartType actualStaticType,
       DartType expectedStaticType,
       ErrorCode errorCode) {
-    if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
+    if (!_typeSystem.isAssignableTo2(actualStaticType, expectedStaticType)) {
       _errorReporter.reportErrorForNode(
           errorCode, expression, [actualStaticType, expectedStaticType]);
       return false;
@@ -2448,7 +2448,7 @@
           StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
           node.iterable,
           [iterableType, loopTypeName]);
-    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+    } else if (!_typeSystem.isAssignableTo2(bestIterableType, variableType)) {
       _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
           node.iterable,
@@ -2666,7 +2666,7 @@
     if (staticType == null) {
       return;
     }
-    if (_typeSystem.isAssignableTo(staticType, fieldType)) {
+    if (_typeSystem.isAssignableTo2(staticType, fieldType)) {
       return;
     }
     // report problem
@@ -2881,7 +2881,7 @@
       typeArguments: [NeverTypeImpl.instance],
       nullabilitySuffix: NullabilitySuffix.star,
     );
-    if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
+    if (!_typeSystem.isSubtypeOf2(lowerBound, returnType)) {
       _errorReporter.reportErrorForNode(errorCode, returnTypeName);
     }
   }
@@ -3393,49 +3393,53 @@
   void _checkForMissingEnumConstantInSwitch(SwitchStatement statement) {
     // TODO(brianwilkerson) This needs to be checked after constant values have
     // been computed.
-    Expression expression = statement.expression;
-    DartType expressionType = getStaticType(expression);
-    if (expressionType == null) {
-      return;
-    }
-    Element expressionElement = expressionType.element;
-    if (expressionElement is ClassElement) {
-      if (!expressionElement.isEnum) {
-        return;
-      }
-      List<String> constantNames = <String>[];
-      List<FieldElement> fields = expressionElement.fields;
-      int fieldCount = fields.length;
-      for (int i = 0; i < fieldCount; i++) {
-        FieldElement field = fields[i];
-        if (field.isStatic && !field.isSynthetic) {
-          constantNames.add(field.name);
+    var expressionType = getStaticType(statement.expression);
+
+    var hasCaseNull = false;
+    if (expressionType is InterfaceType) {
+      var enumElement = expressionType.element;
+      if (enumElement.isEnum) {
+        var constantNames = enumElement.fields
+            .where((field) => field.isStatic && !field.isSynthetic)
+            .map((field) => field.name)
+            .toSet();
+
+        for (var member in statement.members) {
+          if (member is SwitchCase) {
+            var expression = member.expression;
+            if (expression is NullLiteral) {
+              hasCaseNull = true;
+            } else {
+              var constantName = _getConstantName(expression);
+              constantNames.remove(constantName);
+            }
+          }
+          if (member is SwitchDefault) {
+            return;
+          }
         }
-      }
-      NodeList<SwitchMember> members = statement.members;
-      int memberCount = members.length;
-      for (int i = 0; i < memberCount; i++) {
-        SwitchMember member = members[i];
-        if (member is SwitchDefault) {
-          return;
-        }
-        String constantName =
-            _getConstantName((member as SwitchCase).expression);
-        if (constantName != null) {
-          constantNames.remove(constantName);
-        }
-      }
-      if (constantNames.isEmpty) {
-        return;
-      }
-      for (int i = 0; i < constantNames.length; i++) {
-        int offset = statement.offset;
-        int end = statement.rightParenthesis.end;
-        _errorReporter.reportErrorForOffset(
+
+        for (var constantName in constantNames) {
+          int offset = statement.offset;
+          int end = statement.rightParenthesis.end;
+          _errorReporter.reportErrorForOffset(
             StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
             offset,
             end - offset,
-            [constantNames[i]]);
+            [constantName],
+          );
+        }
+
+        if (_typeSystem.isNullable(expressionType) && !hasCaseNull) {
+          int offset = statement.offset;
+          int end = statement.rightParenthesis.end;
+          _errorReporter.reportErrorForOffset(
+            StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
+            offset,
+            end - offset,
+            ['null'],
+          );
+        }
       }
     }
   }
@@ -3522,11 +3526,11 @@
         superType = superType.withNullability(NullabilitySuffix.none);
       }
 
-      bool isSatisfied = _typeSystem.isSubtypeOf(superType, constraint);
+      bool isSatisfied = _typeSystem.isSubtypeOf2(superType, constraint);
       if (!isSatisfied) {
         for (int i = 0; i < mixinIndex && !isSatisfied; i++) {
           isSatisfied =
-              _typeSystem.isSubtypeOf(_enclosingClass.mixins[i], constraint);
+              _typeSystem.isSubtypeOf2(_enclosingClass.mixins[i], constraint);
         }
       }
       if (!isSatisfied) {
@@ -4375,7 +4379,7 @@
     if (!expectedType.isVoid && !fromType.isVoid) {
       var checkWithType =
           !_inAsync ? fromType : _typeProvider.futureType2(fromType);
-      if (_typeSystem.isAssignableTo(checkWithType, expectedType)) {
+      if (_typeSystem.isAssignableTo2(checkWithType, expectedType)) {
         return;
       }
     }
@@ -4458,6 +4462,11 @@
    * See [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE].
    */
   void _checkForSwitchExpressionNotAssignable(SwitchStatement statement) {
+    // For NNBD we verify runtime types of values, and subtyping.
+    if (_isNonNullableByDefault) {
+      return;
+    }
+
     Expression expression = statement.expression;
     if (_checkForUseOfVoidResult(expression)) {
       return;
@@ -4480,7 +4489,7 @@
     DartType caseType = getStaticType(caseExpression);
 
     // check types
-    if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
+    if (!_typeSystem.isAssignableTo2(expressionType, caseType)) {
       _errorReporter.reportErrorForNode(
           StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
           expression,
@@ -4779,7 +4788,7 @@
                 [parameter.identifier.name]);
           } else if (declaredType != null &&
               fieldType != null &&
-              !_typeSystem.isAssignableTo(declaredType, fieldType)) {
+              !_typeSystem.isAssignableTo2(declaredType, fieldType)) {
             _errorReporter.reportErrorForNode(
                 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
                 parameter,
@@ -5075,7 +5084,7 @@
       } else {
         requiredReturnType = _typeProvider.iterableDynamicType;
       }
-      if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) {
+      if (!_typeSystem.isAssignableTo2(impliedReturnType, requiredReturnType)) {
         _errorReporter.reportErrorForNode(
             StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
             yieldExpression,
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 92686aa..70b6e5a 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -6,9 +6,9 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/error/ffi_code.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 
 /// A visitor used to find problems with the way the `dart:ffi` APIs are being
 /// used. See 'pkg/vm/lib/transformations/ffi_checks.md' for the specification
@@ -32,7 +32,7 @@
   ];
 
   /// The type system used to check types.
-  final TypeSystem typeSystem;
+  final TypeSystemImpl typeSystem;
 
   /// The error reporter used to report errors.
   final ErrorReporter _errorReporter;
@@ -441,8 +441,8 @@
       return dartType.isVoid;
     } else if (dartType is InterfaceType && nativeType is InterfaceType) {
       return checkCovariance
-          ? typeSystem.isSubtypeOf(dartType, nativeType)
-          : typeSystem.isSubtypeOf(nativeType, dartType);
+          ? typeSystem.isSubtypeOf2(dartType, nativeType)
+          : typeSystem.isSubtypeOf2(nativeType, dartType);
     } else {
       // If the [nativeType] is not a primitive int/double type then it has to
       // be a Pointer type atm.
diff --git a/pkg/analyzer/lib/src/generated/migration.dart b/pkg/analyzer/lib/src/generated/migration.dart
index 26f48f4..8ea9925 100644
--- a/pkg/analyzer/lib/src/generated/migration.dart
+++ b/pkg/analyzer/lib/src/generated/migration.dart
@@ -25,6 +25,12 @@
   /// applied.
   DartType modifyExpressionType(Expression expression, DartType dartType);
 
+  /// Called after the resolver has inferred the type of a function literal
+  /// parameter.  Should return the type that the parameter has after migrations
+  /// have been applied.
+  DartType modifyInferredParameterType(
+      ParameterElement parameter, DartType type);
+
   /// Called when the resolver starts or stops making use of a [FlowAnalysis]
   /// instance.
   void setFlowAnalysis(
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index f2b0528..418996f 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -137,7 +137,7 @@
       context ??= DynamicTypeImpl.instance;
       inferred ??= DynamicTypeImpl.instance;
 
-      if (_typeSystem.isSubtypeOf(inferred, context)) {
+      if (_typeSystem.isSubtypeOf2(inferred, context)) {
         setType(node, inferred);
       }
     } else {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index d9047b9..9478407 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -164,6 +164,10 @@
           if (inferredType.isDartCoreNull) {
             inferredType = _typeProvider.objectType;
           }
+          if (_migrationResolutionHooks != null) {
+            inferredType = _migrationResolutionHooks
+                .modifyInferredParameterType(p, inferredType);
+          }
           if (!inferredType.isDynamic) {
             p.type = inferredType;
             inferred = true;
@@ -403,8 +407,8 @@
     var context = InferenceContext.getContext(
         (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node);
     if (context == null ||
-        _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
-        !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
+        _typeSystem.isAssignableTo2(_typeProvider.intType, context) ||
+        !_typeSystem.isAssignableTo2(_typeProvider.doubleType, context)) {
       _recordStaticType(node, _nonNullable(_typeProvider.intType));
     } else {
       _recordStaticType(node, _nonNullable(_typeProvider.doubleType));
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 96177bd..1179f06 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/ast.dart' show AstNode, ConstructorName;
 import 'package:analyzer/dart/ast/token.dart' show Keyword, 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';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
@@ -272,7 +273,7 @@
     if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull) {
       // * Null if Null <: T2
       // * Never otherwise
-      if (isSubtypeOf(nullNone, T2)) {
+      if (isSubtypeOf2(nullNone, T2)) {
         return nullNone;
       } else {
         return NeverTypeImpl.instance;
@@ -283,7 +284,7 @@
     if (T2_nullability == NullabilitySuffix.none && T2.isDartCoreNull) {
       // * Null if Null <: T1
       // * Never otherwise
-      if (isSubtypeOf(nullNone, T1)) {
+      if (isSubtypeOf2(nullNone, T1)) {
         return nullNone;
       } else {
         return NeverTypeImpl.instance;
@@ -371,12 +372,12 @@
     }
 
     // DOWN(T1, T2) = T1 if T1 <: T2
-    if (isSubtypeOf(T1, T2)) {
+    if (isSubtypeOf2(T1, T2)) {
       return T1;
     }
 
     // DOWN(T1, T2) = T2 if T2 <: T1
-    if (isSubtypeOf(T2, T1)) {
+    if (isSubtypeOf2(T2, T1)) {
       return T2;
     }
 
@@ -570,11 +571,11 @@
     // UP(X1 & B1, T2)
     if (T1 is TypeParameterType) {
       // T2 if X1 <: T2
-      if (isSubtypeOf(T1, T2)) {
+      if (isSubtypeOf2(T1, T2)) {
         return T2;
       }
       // otherwise X1 if T2 <: X1
-      if (isSubtypeOf(T2, T1)) {
+      if (isSubtypeOf2(T2, T1)) {
         return T1;
       }
       // otherwise UP(B1[Object/X1], T2)
@@ -586,12 +587,12 @@
     // UP(T1, X2 & B2)
     if (T2 is TypeParameterType) {
       // X2 if T1 <: X2
-      if (isSubtypeOf(T1, T2)) {
+      if (isSubtypeOf2(T1, T2)) {
         // TODO(scheglov) How to get here?
         return T2;
       }
       // otherwise T1 if X2 <: T1
-      if (isSubtypeOf(T2, T1)) {
+      if (isSubtypeOf2(T2, T1)) {
         return T1;
       }
       // otherwise UP(T1, B2[Object/X2])
@@ -899,8 +900,16 @@
 
   @override
   bool isAssignableTo(DartType fromType, DartType toType) {
+    if (!NullSafetyUnderstandingFlag.isEnabled) {
+      fromType = NullabilityEliminator.perform(typeProvider, fromType);
+      toType = NullabilityEliminator.perform(typeProvider, toType);
+    }
+    return isAssignableTo2(fromType, toType);
+  }
+
+  bool isAssignableTo2(DartType fromType, DartType toType) {
     // An actual subtype
-    if (isSubtypeOf(fromType, toType)) {
+    if (isSubtypeOf2(fromType, toType)) {
       return true;
     }
 
@@ -909,7 +918,7 @@
         !isNullable(fromType) &&
         acceptsFunctionType(toType)) {
       var callMethodType = getCallMethodType(fromType);
-      if (callMethodType != null && isAssignableTo(callMethodType, toType)) {
+      if (callMethodType != null && isAssignableTo2(callMethodType, toType)) {
         return true;
       }
     }
@@ -944,7 +953,7 @@
     }
 
     // If the subtype relation goes the other way, allow the implicit downcast.
-    if (isSubtypeOf(toType, fromType)) {
+    if (isSubtypeOf2(toType, fromType)) {
       // TODO(leafp,jmesserly): we emit warnings/hints for these in
       // src/task/strong/checker.dart, which is a bit inconsistent. That
       // code should be handled into places that use isAssignableTo, such as
@@ -1078,7 +1087,7 @@
   }
 
   @override
-  bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf(t1, t2);
+  bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf2(t1, t2);
 
   /// Defines a total order on top and Object types.
   bool isMoreTop(DartType T, DartType S) {
@@ -1221,6 +1230,14 @@
   /// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
   @override
   bool isSubtypeOf(DartType _T0, DartType _T1) {
+    if (!NullSafetyUnderstandingFlag.isEnabled) {
+      _T0 = NullabilityEliminator.perform(typeProvider, _T0);
+      _T1 = NullabilityEliminator.perform(typeProvider, _T1);
+    }
+    return isSubtypeOf2(_T0, _T1);
+  }
+
+  bool isSubtypeOf2(DartType _T0, DartType _T1) {
     // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`.
     if (identical(_T0, _T1)) {
       return true;
@@ -1248,7 +1265,7 @@
     //   then `T0 <: T1` if `Object? <: T1`.
     if (identical(T0, DynamicTypeImpl.instance) ||
         identical(T0, VoidTypeImpl.instance)) {
-      if (isSubtypeOf(objectQuestion, T1)) {
+      if (isSubtypeOf2(objectQuestion, T1)) {
         return true;
       }
     }
@@ -1269,18 +1286,18 @@
       if (T0_nullability == NullabilitySuffix.none &&
           T0 is TypeParameterTypeImpl) {
         var bound = T0.element.bound ?? objectQuestion;
-        return isSubtypeOf(bound, objectNone);
+        return isSubtypeOf2(bound, 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);
+        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 isSubtypeOf(
+        return isSubtypeOf2(
           T0.withNullability(NullabilitySuffix.none),
           T1,
         );
@@ -1306,7 +1323,7 @@
           T1 is InterfaceTypeImpl &&
           T1.isDartAsyncFutureOr) {
         var S = T1.typeArguments[0];
-        return isSubtypeOf(nullNone, S);
+        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 ||
@@ -1326,14 +1343,14 @@
     if (T0_nullability == NullabilitySuffix.star) {
       // * `T0 <: T1` iff `S0 <: T1`.
       var S0 = T0.withNullability(NullabilitySuffix.none);
-      return isSubtypeOf(S0, T1);
+      return isSubtypeOf2(S0, T1);
     }
 
     // Right Legacy `T1` is `S1*` then:
     //   * `T0 <: T1` iff `T0 <: S1?`.
     if (T1_nullability == NullabilitySuffix.star) {
       var S1 = T1.withNullability(NullabilitySuffix.question);
-      return isSubtypeOf(T0, S1);
+      return isSubtypeOf2(T0, S1);
     }
 
     // Left FutureOr: if `T0` is `FutureOr<S0>` then:
@@ -1342,12 +1359,12 @@
         T0.isDartAsyncFutureOr) {
       var S0 = T0.typeArguments[0];
       // * `T0 <: T1` iff `Future<S0> <: T1` and `S0 <: T1`
-      if (isSubtypeOf(S0, T1)) {
+      if (isSubtypeOf2(S0, T1)) {
         var FutureS0 = typeProvider.futureElement.instantiate(
           typeArguments: [S0],
           nullabilitySuffix: NullabilitySuffix.none,
         );
-        return isSubtypeOf(FutureS0, T1);
+        return isSubtypeOf2(FutureS0, T1);
       }
       return false;
     }
@@ -1356,7 +1373,7 @@
     //   * `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);
+      return isSubtypeOf2(S0, T1) && isSubtypeOf2(nullNone, T1);
     }
 
     // Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`:
@@ -1365,14 +1382,14 @@
       if (T1 is TypeParameterTypeImpl && T0.definition == T1.definition) {
         var S0 = T0.element.bound ?? objectQuestion;
         var S1 = T1.element.bound ?? objectQuestion;
-        if (isSubtypeOf(S0, S1)) {
+        if (isSubtypeOf2(S0, S1)) {
           return true;
         }
       }
 
       var T0_element = T0.element;
       if (T0_element is TypeParameterMember) {
-        return isSubtypeOf(T0_element.bound, T1);
+        return isSubtypeOf2(T0_element.bound, T1);
       }
     }
 
@@ -1387,18 +1404,18 @@
         typeArguments: [S1],
         nullabilitySuffix: NullabilitySuffix.none,
       );
-      if (isSubtypeOf(T0, FutureS1)) {
+      if (isSubtypeOf2(T0, FutureS1)) {
         return true;
       }
       // * or `T0 <: S1`
-      if (isSubtypeOf(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.element.bound ?? objectQuestion;
-        if (isSubtypeOf(S0, T1)) {
+        if (isSubtypeOf2(S0, T1)) {
           return true;
         }
       }
@@ -1411,18 +1428,18 @@
       var S1 = T1.withNullability(NullabilitySuffix.none);
       // `T0 <: T1` iff any of the following hold:
       // * either `T0 <: S1`
-      if (isSubtypeOf(T0, S1)) {
+      if (isSubtypeOf2(T0, S1)) {
         return true;
       }
       // * or `T0 <: Null`
-      if (isSubtypeOf(T0, nullNone)) {
+      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.element.bound ?? objectQuestion;
-        return isSubtypeOf(S0, T1);
+        return isSubtypeOf2(S0, T1);
       }
       // iff
       return false;
@@ -1441,7 +1458,7 @@
     //   * and `B0 <: T1`
     if (T0 is TypeParameterTypeImpl) {
       var S0 = T0.element.bound ?? objectQuestion;
-      if (isSubtypeOf(S0, T1)) {
+      if (isSubtypeOf2(S0, T1)) {
         return true;
       }
     }
@@ -1579,13 +1596,13 @@
     //
     // This allows the variable to be used wherever the supertype (here `Base`)
     // is expected, while gaining a more precise type.
-    if (isSubtypeOf(to, from)) {
+    if (isSubtypeOf2(to, from)) {
       return to;
     }
     // For a type parameter `T extends U`, allow promoting the upper bound
     // `U` to `S` where `S <: U`, yielding a type parameter `T extends S`.
     if (from is TypeParameterType) {
-      if (isSubtypeOf(to, from.bound ?? DynamicTypeImpl.instance)) {
+      if (isSubtypeOf2(to, from.bound ?? DynamicTypeImpl.instance)) {
         var declaration = from.element.declaration;
         var newElement = TypeParameterMember(declaration, null, to);
         return newElement.instantiate(
@@ -1901,7 +1918,7 @@
         FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) {
       // Type parameter bounds are invariant.
       // TODO(scheglov) We do this for top types, but the spec says explicitly.
-      return isSubtypeOf(t, s) && isSubtypeOf(s, t);
+      return isSubtypeOf2(t, s) && isSubtypeOf2(s, t);
     });
     if (freshTypeFormalTypes == null) {
       return false;
@@ -1910,7 +1927,7 @@
     f = f.instantiate(freshTypeFormalTypes);
     g = g.instantiate(freshTypeFormalTypes);
 
-    if (!isSubtypeOf(f.returnType, g.returnType)) {
+    if (!isSubtypeOf2(f.returnType, g.returnType)) {
       return false;
     }
 
@@ -1924,7 +1941,7 @@
       var gParameter = gParameters[gIndex];
       if (fParameter.isRequiredPositional) {
         if (gParameter.isRequiredPositional) {
-          if (isSubtypeOf(gParameter.type, fParameter.type)) {
+          if (isSubtypeOf2(gParameter.type, fParameter.type)) {
             fIndex++;
             gIndex++;
           } else {
@@ -1935,7 +1952,7 @@
         }
       } else if (fParameter.isOptionalPositional) {
         if (gParameter.isPositional) {
-          if (isSubtypeOf(gParameter.type, fParameter.type)) {
+          if (isSubtypeOf2(gParameter.type, fParameter.type)) {
             fIndex++;
             gIndex++;
           } else {
@@ -1950,7 +1967,7 @@
           if (compareNames == 0) {
             if (fParameter.isRequiredNamed && !gParameter.isRequiredNamed) {
               return false;
-            } else if (isSubtypeOf(gParameter.type, fParameter.type)) {
+            } else if (isSubtypeOf2(gParameter.type, fParameter.type)) {
               fIndex++;
               gIndex++;
             } else {
@@ -2020,15 +2037,15 @@
         // variance is added to the interface.
         Variance variance = (tParams[i] as TypeParameterElementImpl).variance;
         if (variance.isCovariant) {
-          if (!isSubtypeOf(t1, t2)) {
+          if (!isSubtypeOf2(t1, t2)) {
             return false;
           }
         } else if (variance.isContravariant) {
-          if (!isSubtypeOf(t2, t1)) {
+          if (!isSubtypeOf2(t2, t1)) {
             return false;
           }
         } else if (variance.isInvariant) {
-          if (!isSubtypeOf(t1, t2) || !isSubtypeOf(t2, t1)) {
+          if (!isSubtypeOf2(t1, t2) || !isSubtypeOf2(t2, t1)) {
             return false;
           }
         } else {
@@ -3016,10 +3033,10 @@
     type1 = type1.withNullability(NullabilitySuffix.none);
     type2 = type2.withNullability(NullabilitySuffix.none);
 
-    if (typeSystem.isSubtypeOf(type1, type2)) {
+    if (typeSystem.isSubtypeOf2(type1, type2)) {
       return type2.withNullability(nullability);
     }
-    if (typeSystem.isSubtypeOf(type2, type1)) {
+    if (typeSystem.isSubtypeOf2(type2, type1)) {
       return type1.withNullability(nullability);
     }
 
@@ -3045,8 +3062,8 @@
             args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
           }
         } else if (parameterVariance.isInvariant) {
-          if (!typeSystem.isSubtypeOf(args1[i], args2[i]) ||
-              !typeSystem.isSubtypeOf(args2[i], args1[i])) {
+          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),
@@ -3471,6 +3488,10 @@
 
   @override
   DartType leastUpperBound(DartType leftType, DartType rightType) {
+    if (!NullSafetyUnderstandingFlag.isEnabled) {
+      leftType = NullabilityEliminator.perform(typeProvider, leftType);
+      rightType = NullabilityEliminator.perform(typeProvider, rightType);
+    }
     return getLeastUpperBound(leftType, rightType);
   }
 
@@ -3921,7 +3942,7 @@
   bool get isDownwards => origin is! _TypeConstraintFromArgument;
 
   bool isSatisifedBy(TypeSystemImpl ts, DartType type) =>
-      ts.isSubtypeOf(lowerBound, type) && ts.isSubtypeOf(type, upperBound);
+      ts.isSubtypeOf2(lowerBound, type) && ts.isSubtypeOf2(type, upperBound);
 
   /// Converts this constraint to a message suitable for a type inference error.
   @override
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index a5d61ba..49536c7 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -175,14 +175,16 @@
     PerformanceLog log = PerformanceLog(null);
     AnalysisDriverScheduler scheduler = AnalysisDriverScheduler(log);
     AnalysisDriver analysisDriver = AnalysisDriver(
-        scheduler,
-        log,
-        resourceProvider,
-        MemoryByteStore(),
-        FileContentOverlay(),
-        null,
-        sourceFactory,
-        _buildAnalyzerOptions(options));
+      scheduler,
+      log,
+      resourceProvider,
+      MemoryByteStore(),
+      FileContentOverlay(),
+      null,
+      sourceFactory,
+      _buildAnalyzerOptions(options),
+      packages: Packages.empty,
+    );
     analysisDriver.results.listen((_) {});
     analysisDriver.exceptions.listen((_) {});
     scheduler.start();
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index cf73b01..20a05bf 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -354,7 +354,7 @@
       var fieldElement =
           node.identifier.staticElement as FieldFormalParameterElement;
       var fieldType = _elementType(fieldElement.field);
-      if (!rules.isSubtypeOf(type, fieldType)) {
+      if (!rules.isSubtypeOf2(type, fieldType)) {
         _recordMessage(node, StrongModeCode.INVALID_PARAMETER_DECLARATION,
             [node, fieldType]);
       }
@@ -682,13 +682,13 @@
       return null; // unrelated
     }
 
-    if (rules.isSubtypeOf(from, to)) {
+    if (rules.isSubtypeOf2(from, to)) {
       // Sound subtype.
       // However we may still need cast if we have a call tearoff.
       return callTearoff;
     }
 
-    if (rules.isSubtypeOf(to, from)) {
+    if (rules.isSubtypeOf2(to, from)) {
       // Assignable, but needs cast.
       return true;
     }
@@ -878,12 +878,12 @@
     }
 
     // fromT <: toT, no coercion needed.
-    if (rules.isSubtypeOf(from, to)) {
+    if (rules.isSubtypeOf2(from, to)) {
       return false;
     }
 
     // Down cast or legal sideways cast, coercion needed.
-    if (rules.isAssignableTo(from, to)) {
+    if (rules.isAssignableTo2(from, to)) {
       return true;
     }
 
@@ -916,7 +916,7 @@
     // want to warn if it's a legal subtype.
     if (from is InterfaceType && rules.acceptsFunctionType(to)) {
       var type = rules.getCallMethodType(from);
-      if (type != null && rules.isSubtypeOf(type, to)) {
+      if (type != null && rules.isSubtypeOf2(type, to)) {
         return;
       }
     }
@@ -1038,7 +1038,7 @@
         nullabilitySuffix: _noneOrStarSuffix,
       );
 
-      if (rules.isSubtypeOf(sequenceType, iterableType)) {
+      if (rules.isSubtypeOf2(sequenceType, iterableType)) {
         _recordImplicitCast(node.iterable, sequenceType, from: iterableType);
         elementType = DynamicTypeImpl.instance;
       }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index cfbb4ff..39af320 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -453,6 +453,8 @@
 
   int codeUnitAt(int index);
   bool contains(String other, [int startIndex = 0]);
+  String splitMapJoin(Pattern pattern,
+      {String onMatch(Match match), String onNonMatch(String nonMatch)});
   String substring(int len) => null;
   String toLowerCase();
   String toUpperCase();
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index 0e9e973..c70198c 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -3,10 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/workspace/simple.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:analyzer/src/context/packages.dart';
 
 /// Information about a Pub workspace.
 class PubWorkspace extends SimpleWorkspace {
@@ -18,10 +19,14 @@
   /// Each Pub workspace is itself one package.
   PubWorkspacePackage _theOnlyPackage;
 
+  /// The associated pubspec file.
+  final File _pubspecFile;
+
   PubWorkspace._(
     ResourceProvider provider,
     Map<String, List<Folder>> packageMap,
     String root,
+    this._pubspecFile,
   ) : super(provider, packageMap, root);
 
   @override
@@ -52,10 +57,11 @@
         return null;
       }
 
-      if (folder.getChildAssumingFile(_pubspecName).exists) {
+      var pubspec = folder.getChildAssumingFile(_pubspecName);
+      if (pubspec.exists) {
         // Found the pubspec.yaml file; this is our root.
         String root = folder.path;
-        return PubWorkspace._(provider, packageMap, root);
+        return PubWorkspace._(provider, packageMap, root, pubspec);
       }
 
       // Go up a folder.
@@ -73,11 +79,31 @@
   @override
   final String root;
 
+  Pubspec _pubspec;
+
+  /// A flag to indicate if we've tried to parse the pubspec.
+  bool _parsedPubspec = false;
+
   @override
   final PubWorkspace workspace;
 
   PubWorkspacePackage(this.root, this.workspace);
 
+  /// Get the associated parsed [Pubspec], or `null` if there was an error in
+  /// reading or parsing.
+  Pubspec get pubspec {
+    if (!_parsedPubspec) {
+      _parsedPubspec = true;
+      try {
+        final content = workspace._pubspecFile.readAsStringSync();
+        _pubspec = Pubspec.parse(content);
+      } catch (_) {
+        // Pubspec will be null.
+      }
+    }
+    return _pubspec;
+  }
+
   @override
   bool contains(Source source) {
     String filePath = filePathFromSource(source);
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index e2486f4..0c72327 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -8,19 +8,19 @@
 
 dependencies:
   _fe_analyzer_shared: ^1.0.3
-  args: '>=0.12.1 <2.0.0'
+  args: ^1.0.0
   charcode: ^1.1.0
   collection: ^1.10.1
   convert: ^2.0.0
-  crypto: '>=1.1.1 <3.0.0'
+  crypto: ^2.0.0
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
   meta: ^1.0.2
-  package_config: '>=0.1.5 <2.0.0'
-  path: '>=0.9.0 <2.0.0'
+  package_config: ^1.0.0
+  path: ^1.0.0
   pub_semver: ^1.4.2
   source_span: ^1.2.0
-  watcher: '>=0.9.6 <0.10.0'
+  watcher: ^0.9.6
   yaml: ^2.1.2
 dev_dependencies:
   analysis_tool:
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 410f60f..8c4b0ce 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1189,65 +1189,6 @@
     ]);
   }
 
-  test_inconsistentCaseExpressionTypes() async {
-    await assertErrorsInCode(r'''
-f(var p) {
-  switch (p) {
-    case 1:
-      break;
-    case 'a':
-      break;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 60, 3),
-    ]);
-  }
-
-  test_inconsistentCaseExpressionTypes_dynamic() async {
-    // Even though A.S and S have a static type of "dynamic", we should see
-    // that they fail to match 3, because they are constant strings.
-    await assertErrorsInCode(r'''
-class A {
-  static const S = 'A.S';
-}
-
-const S = 'S';
-
-foo(var p) {
-  switch (p) {
-    case 3:
-      break;
-    case S:
-      break;
-    case A.S:
-      break;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 117, 1),
-      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 142, 3),
-    ]);
-  }
-
-  test_inconsistentCaseExpressionTypes_repeated() async {
-    await assertErrorsInCode(r'''
-f(var p) {
-  switch (p) {
-    case 1:
-      break;
-    case 'a':
-      break;
-    case 'b':
-      break;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 60, 3),
-      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 87, 3),
-    ]);
-  }
-
   test_initializerForNonExistent_const() async {
     // Check that the absence of a matching field doesn't cause a
     // crash during constant evaluation.
@@ -1814,65 +1755,6 @@
     ]);
   }
 
-  test_nonConstCaseExpression() async {
-    await assertErrorsInCode(r'''
-f(int p, int q) {
-  switch (p) {
-    case 3 + q:
-      break;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION, 46, 1),
-    ]);
-  }
-
-  test_nonConstCaseExpressionFromDeferredLibrary() async {
-    newFile('/test/lib/lib1.dart', content: '''
-library lib1;
-const int c = 1;
-''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-main (int p) {
-  switch (p) {
-    case a.c:
-      break;
-  }
-}
-''', [
-      error(
-          CompileTimeErrorCode
-              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
-          87,
-          3),
-    ]);
-  }
-
-  test_nonConstCaseExpressionFromDeferredLibrary_nested() async {
-    newFile('/test/lib/lib1.dart', content: '''
-library lib1;
-const int c = 1;
-''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-main (int p) {
-  switch (p) {
-    case a.c + 1:
-      break;
-  }
-}
-''', [
-      error(
-          CompileTimeErrorCode
-              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
-          87,
-          7),
-    ]);
-  }
-
   test_nonConstMapAsExpressionStatement_begin() async {
     // TODO(danrubel): Consider improving recovery
     await assertErrorsInCode(r'''
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 1ec4a8f..27a1466b 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1622,19 +1622,6 @@
 ''');
   }
 
-  test_inconsistentCaseExpressionTypes() async {
-    await assertNoErrorsInCode(r'''
-f(var p) {
-  switch (p) {
-    case 1:
-      break;
-    case 2:
-      break;
-  }
-}
-''');
-  }
-
   test_inconsistentMethodInheritance_accessors_typeParameter2() async {
     await assertNoErrorsInCode(r'''
 abstract class A<E> {
@@ -2651,35 +2638,6 @@
 ''');
   }
 
-  test_nonConstCaseExpression_constField() async {
-    await assertErrorsInCode(r'''
-f(double p) {
-  switch (p) {
-    case double.INFINITY:
-      return true;
-    default:
-      return false;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 16, 6),
-    ]);
-  }
-
-  test_nonConstCaseExpression_typeLiteral() async {
-    await assertNoErrorsInCode(r'''
-f(Type t) {
-  switch (t) {
-    case bool:
-    case int:
-      return true;
-    default:
-      return false;
-  }
-}
-''');
-  }
-
   test_nonConstListElement_constField() async {
     await assertNoErrorsInCode(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 86950e9..0575378 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -600,7 +601,8 @@
     PerformanceLog log = PerformanceLog(_logBuffer);
     AnalysisDriverScheduler scheduler = AnalysisDriverScheduler(log);
     driver = AnalysisDriver(scheduler, log, resourceProvider, MemoryByteStore(),
-        fileContentOverlay, null, sourceFactory, options);
+        fileContentOverlay, null, sourceFactory, options,
+        packages: Packages.empty);
     scheduler.start();
   }
 
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 2901cdd..028da1e 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -384,11 +384,11 @@
   }
 
   void _checkIsAssignableTo(DartType type1, DartType type2) {
-    expect(typeSystem.isAssignableTo(type1, type2), true);
+    expect(typeSystem.isAssignableTo2(type1, type2), true);
   }
 
   void _checkIsNotAssignableTo(DartType type1, DartType type2) {
-    expect(typeSystem.isAssignableTo(type1, type2), false);
+    expect(typeSystem.isAssignableTo2(type1, type2), false);
   }
 
   void _checkIsStrictAssignableTo(DartType type1, DartType type2) {
diff --git a/pkg/analyzer/test/id_tests/assigned_variables_test.dart b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
index 5cdd76b..a46ec06 100644
--- a/pkg/analyzer/test/id_tests/assigned_variables_test.dart
+++ b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
@@ -9,6 +9,7 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
@@ -19,13 +20,15 @@
   Directory dataDir = Directory.fromUri(Platform.script.resolve(
       '../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/'
       'data'));
-  await runTests<_Data>(dataDir,
-      args: args,
-      supportedMarkers: cfeAnalyzerMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest: runTestFor(
-          const _AssignedVariablesDataComputer(), [analyzerNnbdConfig]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<_Data>(dataDir,
+        args: args,
+        supportedMarkers: cfeAnalyzerMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const _AssignedVariablesDataComputer(), [analyzerNnbdConfig]));
+  });
 }
 
 class _AssignedVariablesDataComputer extends DataComputer<_Data> {
diff --git a/pkg/analyzer/test/id_tests/constant_test.dart b/pkg/analyzer/test/id_tests/constant_test.dart
index 8e1bf64..5ea6df5 100644
--- a/pkg/analyzer/test/id_tests/constant_test.dart
+++ b/pkg/analyzer/test/id_tests/constant_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 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/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
@@ -18,13 +19,15 @@
 main(List<String> args) async {
   Directory dataDir = Directory.fromUri(Platform.script
       .resolve('../../../_fe_analyzer_shared/test/constants/data'));
-  await runTests<String>(dataDir,
-      args: args,
-      supportedMarkers: sharedMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest: runTestFor(
-          const ConstantsDataComputer(), [analyzerConstantUpdate2018Config]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<String>(dataDir,
+        args: args,
+        supportedMarkers: sharedMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const ConstantsDataComputer(), [analyzerConstantUpdate2018Config]));
+  });
 }
 
 class ConstantsDataComputer extends DataComputer<String> {
diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
index a879acf..999e039 100644
--- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
@@ -8,6 +8,7 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
@@ -18,13 +19,15 @@
   Directory dataDir = Directory.fromUri(Platform.script.resolve(
       '../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/'
       'data'));
-  await runTests<String>(dataDir,
-      args: args,
-      supportedMarkers: cfeAnalyzerMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest: runTestFor(
-          const _DefiniteAssignmentDataComputer(), [analyzerNnbdConfig]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<String>(dataDir,
+        args: args,
+        supportedMarkers: cfeAnalyzerMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const _DefiniteAssignmentDataComputer(), [analyzerNnbdConfig]));
+  });
 }
 
 class _DefiniteAssignmentDataComputer extends DataComputer<String> {
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index 283e16e..e15edc8 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -21,13 +22,15 @@
 main(List<String> args) async {
   Directory dataDir = Directory.fromUri(Platform.script.resolve(
       '../../../_fe_analyzer_shared/test/flow_analysis/nullability/data'));
-  await runTests<String>(dataDir,
-      args: args,
-      supportedMarkers: cfeAnalyzerMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest:
-          runTestFor(const _NullabilityDataComputer(), [analyzerNnbdConfig]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<String>(dataDir,
+        args: args,
+        supportedMarkers: cfeAnalyzerMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest:
+            runTestFor(const _NullabilityDataComputer(), [analyzerNnbdConfig]));
+  });
 }
 
 class FlowTestBase {
diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart
index abe5cef..6b85af8 100644
--- a/pkg/analyzer/test/id_tests/reachability_test.dart
+++ b/pkg/analyzer/test/id_tests/reachability_test.dart
@@ -8,6 +8,7 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
@@ -18,13 +19,15 @@
 main(List<String> args) async {
   Directory dataDir = Directory.fromUri(Platform.script.resolve(
       '../../../_fe_analyzer_shared/test/flow_analysis/reachability/data'));
-  await runTests<Set<_ReachabilityAssertion>>(dataDir,
-      args: args,
-      supportedMarkers: cfeAnalyzerMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest:
-          runTestFor(const _ReachabilityDataComputer(), [analyzerNnbdConfig]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<Set<_ReachabilityAssertion>>(dataDir,
+        args: args,
+        supportedMarkers: cfeAnalyzerMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const _ReachabilityDataComputer(), [analyzerNnbdConfig]));
+  });
 }
 
 class FlowTestBase {
diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart
index e0779a3..874f429 100644
--- a/pkg/analyzer/test/id_tests/type_promotion_test.dart
+++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart
@@ -8,6 +8,7 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 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/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/element/member.dart';
@@ -20,13 +21,15 @@
   Directory dataDir = Directory.fromUri(Platform.script
       .resolve('../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/'
           'data'));
-  await runTests<DartType>(dataDir,
-      args: args,
-      supportedMarkers: sharedMarkers,
-      createUriForFileName: createUriForFileName,
-      onFailure: onFailure,
-      runTest:
-          runTestFor(const _TypePromotionDataComputer(), [analyzerNnbdConfig]));
+  await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+    return runTests<DartType>(dataDir,
+        args: args,
+        supportedMarkers: sharedMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure,
+        runTest: runTestFor(
+            const _TypePromotionDataComputer(), [analyzerNnbdConfig]));
+  });
 }
 
 class _TypePromotionDataComputer extends DataComputer<DartType> {
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index d1cebbc..4d2361c 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -99,6 +100,7 @@
           ResourceUriResolver(resourceProvider)
         ]),
         createAnalysisOptions(),
+        packages: Packages.empty,
         disableChangesAndCacheAllResults: disableChangesAndCacheAllResults,
         enableIndex: true,
         externalSummaries: externalSummaries);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 302c618..789a977d 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -78,7 +79,8 @@
         SourceFactory(
           [DartUriResolver(sdk), ResourceUriResolver(resourceProvider)],
         ),
-        AnalysisOptionsImpl());
+        AnalysisOptionsImpl(),
+        packages: Packages.empty);
     driver.results.forEach(allResults.add);
     return driver;
   }
@@ -1813,6 +1815,24 @@
     expect(result1.unit, isNotNull);
   }
 
+  test_getSourceKind_changeFile() async {
+    var path = convertPath('/test/lib/test.dart');
+    expect(await driver.getSourceKind(path), SourceKind.LIBRARY);
+
+    newFile(path, content: 'part of foo;');
+    driver.changeFile(path);
+    expect(await driver.getSourceKind(path), SourceKind.PART);
+
+    newFile(path, content: '');
+    driver.changeFile(path);
+    expect(await driver.getSourceKind(path), SourceKind.LIBRARY);
+  }
+
+  test_getSourceKind_doesNotExist() async {
+    var path = convertPath('/test/lib/test.dart');
+    expect(await driver.getSourceKind(path), SourceKind.LIBRARY);
+  }
+
   test_getSourceKind_library() async {
     var path = convertPath('/test/lib/test.dart');
     newFile(path, content: 'class A {}');
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 d5a39b6..a1746fa 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
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
@@ -128,11 +127,7 @@
   void _buildProvider(List<String> enabledExperiments) {
     provider = FeatureSetProvider.build(
       resourceProvider: resourceProvider,
-      contextRoot: ContextRoot(
-        convertPath('/test'),
-        [],
-        pathContext: resourceProvider.pathContext,
-      ),
+      packages: findPackagesFrom(resourceProvider, getFolder('/test')),
       sourceFactory: sourceFactory,
       defaultFeatureSet: FeatureSet.fromEnableFlags(enabledExperiments),
     );
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index de5f084..079713a 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -61,7 +62,7 @@
     AnalysisOptions analysisOptions = AnalysisOptionsImpl();
     var featureSetProvider = FeatureSetProvider.build(
       resourceProvider: resourceProvider,
-      contextRoot: null,
+      packages: Packages.empty,
       sourceFactory: sourceFactory,
       defaultFeatureSet: FeatureSet.fromEnableFlags([]),
     );
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 9da9fb7..2f919bf 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -1816,6 +1816,7 @@
   N1;
   N2();
   N3;
+  N4 = 0;
 }
 ''');
     ImportElement element = testLibraryElement.imports[0];
@@ -1825,7 +1826,7 @@
       _expectId(mainElement, kind, 'N1;', length: 0),
       _expectId(mainElement, kind, 'N2();', length: 0),
       _expectId(mainElement, kind, 'N3;', length: 0),
-//      _expectId(mainElement, kind, 'N4 =', length: 0),
+      _expectId(mainElement, kind, 'N4 =', length: 0),
     ];
     await _verifyReferences(element, expected);
   }
@@ -1846,6 +1847,7 @@
   a.N1;
   a.N2();
   a.N3;
+  a.N4 = 0;
 }
 ''');
     ImportElement element = testLibraryElement.imports[0];
@@ -1856,7 +1858,7 @@
       _expectId(mainElement, kind, 'a.N1;', length: length),
       _expectId(mainElement, kind, 'a.N2()', length: length),
       _expectId(mainElement, kind, 'a.N3', length: length),
-//      _expectId(mainElement, kind, 'a.N4', length: length),
+      _expectId(mainElement, kind, 'a.N4', length: length),
     ];
     await _verifyReferences(element, expected);
   }
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 9949337..5ec53ee 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -292,7 +292,7 @@
   }) {
     assertExpectedString(T0, strT0);
     assertExpectedString(T1, strT1);
-    expect(typeSystem.isSubtypeOf(T0, T1), isFalse);
+    expect(typeSystem.isSubtypeOf2(T0, T1), isFalse);
   }
 
   void isNotSubtype2(
@@ -301,7 +301,7 @@
   ) {
     var T0 = _getTypeByStr(strT0);
     var T1 = _getTypeByStr(strT1);
-    expect(typeSystem.isSubtypeOf(T0, T1), isFalse);
+    expect(typeSystem.isSubtypeOf2(T0, T1), isFalse);
   }
 
   void isNotSubtype3({
@@ -319,7 +319,7 @@
   }) {
     assertExpectedString(T0, strT0);
     assertExpectedString(T1, strT1);
-    expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
+    expect(typeSystem.isSubtypeOf2(T0, T1), isTrue);
   }
 
   void isSubtype2(
@@ -328,7 +328,7 @@
   ) {
     var T0 = _getTypeByStr(strT0);
     var T1 = _getTypeByStr(strT1);
-    expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
+    expect(typeSystem.isSubtypeOf2(T0, T1), isTrue);
   }
 
   @override
@@ -6086,7 +6086,7 @@
   void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
     var strType1 = _typeStr(type1);
     var strType2 = _typeStr(type2);
-    expect(typeSystem.isSubtypeOf(type1, type2), false,
+    expect(typeSystem.isSubtypeOf2(type1, type2), false,
         reason: '$strType1 was not supposed to be a subtype of $strType2');
   }
 
@@ -6098,7 +6098,7 @@
   void _checkIsSubtypeOf(DartType type1, DartType type2) {
     var strType1 = _typeStr(type1);
     var strType2 = _typeStr(type2);
-    expect(typeSystem.isSubtypeOf(type1, type2), true,
+    expect(typeSystem.isSubtypeOf2(type1, type2), true,
         reason: '$strType1 is not a subtype of $strType2');
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 3f89e34..14790a0 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -16,6 +16,7 @@
 import 'top_merge_test.dart' as top_merge;
 import 'type_algebra_test.dart' as type_algebra;
 import 'type_parameter_element_test.dart' as type_parameter_element;
+import 'type_visitor_test.dart' as type_visitor;
 import 'upper_lower_bound_test.dart' as upper_bound;
 
 /// Utility for manually running all tests.
@@ -33,6 +34,7 @@
     top_merge.main();
     type_algebra.main();
     type_parameter_element.main();
+    type_visitor.main();
     upper_bound.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
index a732006..73fd51e 100644
--- a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:test/test.dart';
@@ -146,11 +148,11 @@
     _setEnclosingElement(T1);
     _setEnclosingElement(T2);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isTrue);
-    expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isTrue);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isTrue);
+    _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isTrue);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeStar(T2), isFalse);
-    expect(typeParameterTypeStar(T1) == typeParameterTypeNone(T2), isFalse);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeStar(T2), isFalse);
+    _assertEqual(typeParameterTypeStar(T1), typeParameterTypeNone(T2), isFalse);
   }
 
   test_equal_equalElements_withRecursiveBounds() {
@@ -169,11 +171,11 @@
     _setEnclosingElement(T1);
     _setEnclosingElement(T2);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isTrue);
-    expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isTrue);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isTrue);
+    _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isTrue);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeStar(T2), isFalse);
-    expect(typeParameterTypeStar(T1) == typeParameterTypeNone(T2), isFalse);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeStar(T2), isFalse);
+    _assertEqual(typeParameterTypeStar(T1), typeParameterTypeNone(T2), isFalse);
   }
 
   test_equal_sameElement_differentBounds() {
@@ -183,39 +185,56 @@
     var T1 = TypeParameterMember(T, null, typeProvider.intType);
     var T2 = TypeParameterMember(T, null, typeProvider.doubleType);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T1), isTrue);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T1), isTrue);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isFalse);
-    expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isFalse);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isFalse);
+    _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isFalse);
 
-    expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T), isFalse);
-    expect(typeParameterTypeNone(T) == typeParameterTypeNone(T1), isFalse);
+    _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T), isFalse);
+    _assertEqual(typeParameterTypeNone(T), typeParameterTypeNone(T1), isFalse);
   }
 
   test_equal_sameElements() {
     var T = typeParameter('T');
 
-    expect(typeParameterTypeNone(T) == typeParameterTypeNone(T), isTrue);
-    expect(typeParameterTypeNone(T) == typeParameterTypeStar(T), isFalse);
-    expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse);
-
-    expect(typeParameterTypeStar(T) == typeParameterTypeNone(T), isFalse);
-    expect(typeParameterTypeStar(T) == typeParameterTypeStar(T), isTrue);
-    expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse);
-
-    expect(
-      typeParameterTypeQuestion(T) == typeParameterTypeNone(T),
+    _assertEqual(typeParameterTypeNone(T), typeParameterTypeNone(T), isTrue);
+    _assertEqual(typeParameterTypeNone(T), typeParameterTypeStar(T), isFalse);
+    _assertEqual(
+      typeParameterTypeNone(T),
+      typeParameterTypeQuestion(T),
       isFalse,
     );
-    expect(
-      typeParameterTypeQuestion(T) == typeParameterTypeStar(T),
+
+    _assertEqual(typeParameterTypeStar(T), typeParameterTypeNone(T), isFalse);
+    _assertEqual(typeParameterTypeStar(T), typeParameterTypeStar(T), isTrue);
+    _assertEqual(
+      typeParameterTypeNone(T),
+      typeParameterTypeQuestion(T),
       isFalse,
     );
-    expect(
-      typeParameterTypeQuestion(T) == typeParameterTypeQuestion(T),
+
+    _assertEqual(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeNone(T),
+      isFalse,
+    );
+    _assertEqual(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeStar(T),
+      isFalse,
+    );
+    _assertEqual(
+      typeParameterTypeQuestion(T),
+      typeParameterTypeQuestion(T),
       isTrue,
     );
   }
+
+  void _assertEqual(DartType T1, DartType T2, matcher) {
+    NullSafetyUnderstandingFlag.enableNullSafetyTypes(() async {
+      expect(T1 == T2, matcher);
+    });
+  }
 }
 
 class _TypeParameterElementBase extends AbstractTypeTest {
diff --git a/pkg/analyzer/test/src/dart/element/type_visitor_test.dart b/pkg/analyzer/test/src/dart/element/type_visitor_test.dart
new file mode 100644
index 0000000..0d27256
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_visitor_test.dart
@@ -0,0 +1,214 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/type_visitor.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'element_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RecursiveTypeVisitorTest);
+  });
+}
+
+@reflectiveTest
+class RecursiveTypeVisitorTest extends AbstractTypeTest {
+  _MockRecursiveVisitor visitor;
+
+  @override
+  void setUp() {
+    super.setUp();
+    visitor = _MockRecursiveVisitor();
+  }
+
+  void test_callsDefaultBehavior() {
+    expect(DartTypeVisitor.visit(intNone, visitor), true);
+    visitor.assertVisitedType(intNone);
+  }
+
+  void test_functionType_typeFormal_noBound() {
+    final T = this.typeParameter('T');
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [T],
+        parameters: [],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedType(dynamicType);
+  }
+
+  void test_functionType_complex() {
+    final T = typeParameter('T', bound: intNone);
+    final K = typeParameter('K', bound: stringNone);
+    final a = positionalParameter(type: numNone);
+    final b = positionalParameter(type: doubleNone);
+    final c = namedParameter(name: 'c', type: voidNone);
+    final d = namedParameter(name: 'd', type: objectNone);
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [T, K],
+        parameters: [a, b, c, d],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedTypes([
+      dynamicType,
+      intNone,
+      stringNone,
+      numNone,
+      doubleNone,
+      voidNone,
+      objectNone
+    ]);
+  }
+
+  void test_functionType_positionalParameter() {
+    final a = positionalParameter(type: intNone);
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [],
+        parameters: [a],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedType(intNone);
+  }
+
+  void test_functionType_returnType() {
+    final type = functionType(
+        returnType: intNone,
+        typeFormals: [],
+        parameters: [],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedType(intNone);
+  }
+
+  void test_functionType_typeFormal_bound() {
+    final T = typeParameter('T', bound: intNone);
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [T],
+        parameters: [],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedTypes([dynamicType, intNone]);
+  }
+
+  void test_interfaceType_typeParameter() {
+    final type = typeProvider.listType2(intNone);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedType(intNone);
+  }
+
+  void test_interfaceType_typeParameters() {
+    final type = typeProvider.mapType2(intNone, stringNone);
+    expect(DartTypeVisitor.visit(type, visitor), true);
+    visitor.assertVisitedTypes([intNone, stringNone]);
+  }
+
+  void test_stopVisiting_typeParameters() {
+    final type = typeProvider.mapType2(intNone, stringNone);
+    visitor.stopOnType = intNone;
+    expect(DartTypeVisitor.visit(type, visitor), false);
+    visitor.assertVisitedType(intNone);
+    visitor.assertNotVisitedType(stringNone);
+  }
+
+  void test_interfaceType_typeParameters_nested() {
+    final innerList = typeProvider.listType2(intNone);
+    final outerList = typeProvider.listType2(innerList);
+    expect(DartTypeVisitor.visit(outerList, visitor), true);
+    visitor.assertVisitedType(intNone);
+  }
+
+  void test_stopVisiting_first() {
+    final T = typeParameter('T', bound: intNone);
+    final K = typeParameter('K', bound: stringNone);
+    final a = positionalParameter(type: numNone);
+    final b = positionalParameter(type: doubleNone);
+    final c = namedParameter(name: 'c', type: voidNone);
+    final d = namedParameter(name: 'd', type: objectNone);
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [T, K],
+        parameters: [a, b, c, d],
+        nullabilitySuffix: NullabilitySuffix.none);
+    visitor.stopOnType = dynamicType;
+    expect(DartTypeVisitor.visit(type, visitor), false);
+    visitor.assertNotVisitedTypes(
+        [intNone, stringNone, numNone, doubleNone, voidNone, objectNone]);
+  }
+
+  void test_stopVisiting_halfway() {
+    final T = typeParameter('T', bound: intNone);
+    final K = typeParameter('K', bound: stringNone);
+    final a = positionalParameter(type: numNone);
+    final b = positionalParameter(type: doubleNone);
+    final c = namedParameter(name: 'c', type: voidNone);
+    final d = namedParameter(name: 'd', type: objectNone);
+    final type = functionType(
+        returnType: dynamicType,
+        typeFormals: [T, K],
+        parameters: [a, b, c, d],
+        nullabilitySuffix: NullabilitySuffix.none);
+    visitor.stopOnType = intNone;
+    expect(DartTypeVisitor.visit(type, visitor), false);
+    visitor.assertNotVisitedTypes([stringNone, voidNone, objectNone]);
+  }
+
+  void test_stopVisiting_nested() {
+    final innerType = typeProvider.mapType2(intNone, stringNone);
+    final outerList = typeProvider.listType2(innerType);
+    visitor.stopOnType = intNone;
+    expect(DartTypeVisitor.visit(outerList, visitor), false);
+    visitor.assertNotVisitedType(stringNone);
+  }
+
+  void test_stopVisiting_nested_parent() {
+    final innerTypeStop = typeProvider.listType2(intNone);
+    final innerTypeSkipped = typeProvider.listType2(stringNone);
+    final outerType = typeProvider.mapType2(innerTypeStop, innerTypeSkipped);
+    visitor.stopOnType = intNone;
+    expect(DartTypeVisitor.visit(outerType, visitor), false);
+    visitor.assertNotVisitedType(stringNone);
+  }
+}
+
+class _MockRecursiveVisitor extends RecursiveTypeVisitor {
+  final visitedTypes = <DartType>{};
+  DartType stopOnType;
+
+  @override
+  bool visitInterfaceType(InterfaceType type) {
+    visitedTypes.add(type);
+    if (type == stopOnType) {
+      return false;
+    }
+    return super.visitInterfaceType(type);
+  }
+
+  @override
+  bool defaultDartType(DartType type) {
+    expect(type, isNotNull);
+    visitedTypes.add(type);
+    return type != stopOnType;
+  }
+
+  void assertVisitedType(DartType type) {
+    expect(visitedTypes, contains(type));
+  }
+
+  void assertVisitedTypes(Iterable<DartType> types) =>
+      types.forEach(assertVisitedType);
+
+  void assertNotVisitedTypes(Iterable<DartType> types) =>
+      types.forEach(assertNotVisitedType);
+
+  void assertNotVisitedType(DartType type) {
+    expect(visitedTypes, isNot(contains(type)));
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
index a55f39c..8e35b70 100644
--- a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/context_root.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -75,7 +76,8 @@
           PackageMapUriResolver(resourceProvider, packageMap),
           ResourceUriResolver(resourceProvider)
         ]),
-        analysisOptions);
+        analysisOptions,
+        packages: Packages.empty);
 
     scheduler.start();
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
index 88732aa..5e42d74 100644
--- a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -42,7 +43,12 @@
   ]
 }
 ''');
-    driver.configure();
+    driver.configure(
+      packages: findPackagesFrom(
+        resourceProvider,
+        getFolder('/test'),
+      ),
+    );
 
     newFile('/aaa/lib/a.dart', content: r'''
 int a = 0;
@@ -80,7 +86,12 @@
   ]
 }
 ''');
-    driver.configure();
+    driver.configure(
+      packages: findPackagesFrom(
+        resourceProvider,
+        getFolder('/test'),
+      ),
+    );
 
     newFile('/aaa/lib/a.dart', content: r'''
 int a = 0;
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index a195ee3..39942f3 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -1725,6 +1725,40 @@
     );
   }
 
+  test_hasReceiver_interfaceQ_Function_call_checked() async {
+    await assertNoErrorsInCode(r'''
+void main(Function? foo) {
+  foo?.call();
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('foo?.call()'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
+  test_hasReceiver_interfaceQ_Function_call_unchecked() async {
+    await assertErrorsInCode(r'''
+void main(Function? foo) {
+  foo.call();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 29, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('foo.call()'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
   test_hasReceiver_interfaceTypeQ_defined() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/case_expression_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/case_expression_type_implements_equals_test.dart
index 989da35..d6b69ce 100644
--- a/pkg/analyzer/test/src/diagnostics/case_expression_type_implements_equals_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/case_expression_type_implements_equals_test.dart
@@ -2,7 +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:analyzer/dart/analysis/features.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';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CaseExpressionTypeImplementsEqualsTest);
+    defineReflectiveTests(CaseExpressionTypeImplementsEqualsWithNnbdTest);
   });
 }
 
@@ -17,24 +20,24 @@
 class CaseExpressionTypeImplementsEqualsTest extends DriverResolutionTest {
   test_declares() async {
     await assertNoErrorsInCode(r'''
-print(p) {}
+abstract class A {
+  final int value;
 
-abstract class B {
-  final id;
-  const B(this.id);
-  String toString() => 'C($id)';
-  /** Equality is identity equality, the id isn't used. */
+  const A(this.value);
+
   bool operator==(Object other);
-  }
-
-class C extends B {
-  const C(id) : super(id);
 }
 
-void doSwitch(c) {
-  switch (c) {
-  case const C(0): print('Switch: 0'); break;
-  case const C(1): print('Switch: 1'); break;
+class B extends A {
+  const B(int value) : super(value);
+}
+
+void f(e) {
+  switch (e) {
+    case const B(0):
+      break;
+    case const B(1):
+      break;
   }
 }
 ''');
@@ -42,33 +45,34 @@
 
   test_implements() async {
     await assertErrorsInCode(r'''
-class IntWrapper {
+class A {
   final int value;
-  const IntWrapper(this.value);
-  bool operator ==(Object x) {
-    return x is IntWrapper && x.value == value;
+
+  const A(this.value);
+
+  bool operator ==(Object other) {
+    return false;
   }
-  get hashCode => value;
 }
 
-f(var a) {
-  switch(a) {
-    case(const IntWrapper(1)) : return 1;
-    default: return 0;
+void f(e) {
+  switch (e) {
+    case A(0):
+      break;
   }
 }
 ''', [
       error(
-          CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 194, 6),
+          CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 128, 6),
     ]);
   }
 
   test_int() async {
     await assertNoErrorsInCode(r'''
-f(int i) {
-  switch(i) {
-    case(1) : return 1;
-    default: return 0;
+void f(e) {
+  switch (e) {
+    case 0:
+      break;
   }
 }
 ''');
@@ -76,15 +80,15 @@
 
   test_Object() async {
     await assertNoErrorsInCode(r'''
-class IntWrapper {
+class A {
   final int value;
-  const IntWrapper(this.value);
+  const A(this.value);
 }
 
-f(IntWrapper intWrapper) {
-  switch(intWrapper) {
-    case(const IntWrapper(1)) : return 1;
-    default: return 0;
+void f(e) {
+  switch (e) {
+    case A(0):
+      break;
   }
 }
 ''');
@@ -92,10 +96,106 @@
 
   test_String() async {
     await assertNoErrorsInCode(r'''
-f(String s) {
-  switch(s) {
-    case('1') : return 1;
-    default: return 0;
+void f(e) {
+  switch (e) {
+    case '0':
+      break;
+  }
+}
+''');
+  }
+}
+
+@reflectiveTest
+class CaseExpressionTypeImplementsEqualsWithNnbdTest
+    extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_declares() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  final int value;
+
+  const A(this.value);
+
+  bool operator==(Object other);
+}
+
+class B extends A {
+  const B(int value) : super(value);
+}
+
+void f(e) {
+  switch (e) {
+    case const B(0):
+      break;
+    case const B(1):
+      break;
+  }
+}
+''');
+  }
+
+  test_implements() async {
+    await assertErrorsInCode(r'''
+class A {
+  final int value;
+
+  const A(this.value);
+
+  bool operator ==(Object other) {
+    return false;
+  }
+}
+
+void f(e) {
+  switch (e) {
+    case A(0):
+      break;
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, 150, 4),
+    ]);
+  }
+
+  test_int() async {
+    await assertNoErrorsInCode(r'''
+void f(e) {
+  switch (e) {
+    case 0:
+      break;
+  }
+}
+''');
+  }
+
+  test_Object() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  final int value;
+  const A(this.value);
+}
+
+void f(e) {
+  switch (e) {
+    case A(0):
+      break;
+  }
+}
+''');
+  }
+
+  test_String() async {
+    await assertNoErrorsInCode(r'''
+void f(e) {
+  switch (e) {
+    case '0':
+      break;
   }
 }
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/case_expression_type_is_not_switch_expression_subtype_test.dart b/pkg/analyzer/test/src/diagnostics/case_expression_type_is_not_switch_expression_subtype_test.dart
new file mode 100644
index 0000000..1561646
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/case_expression_type_is_not_switch_expression_subtype_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.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(CaseExpressionTypeIsNotSswitchExpressionSubtype);
+  });
+}
+
+@reflectiveTest
+class CaseExpressionTypeIsNotSswitchExpressionSubtype
+    extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+
+  CompileTimeErrorCode get _errorCode {
+    return CompileTimeErrorCode
+        .CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE;
+  }
+
+  test_notSubtype() async {
+    await assertErrorsInCode('''
+class A {
+  const A();
+}
+
+class B {
+  final int value;
+  const B(this.value);
+}
+
+const dynamic B0 = B(0);
+
+void f(A e) {
+  switch (e) {
+    case B0:
+      break;
+    case B(1):
+      break;
+  }
+}
+''', [
+      error(_errorCode, 145, 2),
+      error(_errorCode, 171, 4),
+    ]);
+  }
+
+  test_subtype() async {
+    await assertNoErrorsInCode('''
+class A {
+  final int value;
+  const A(this.value);
+}
+
+class B extends A {
+  const B(int value) : super(value);
+}
+
+class C extends A {
+  const C(int value) : super(value);
+}
+
+void f(A e) {
+  switch (e) {
+    case B(0):
+      break;
+    case C(0):
+      break;
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/inconsistent_case_expression_types_test.dart b/pkg/analyzer/test/src/diagnostics/inconsistent_case_expression_types_test.dart
new file mode 100644
index 0000000..b092ae2
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/inconsistent_case_expression_types_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All 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(InconsistentCaseExpressionTypesTest);
+  });
+}
+
+@reflectiveTest
+class InconsistentCaseExpressionTypesTest extends DriverResolutionTest {
+  test_int() async {
+    await assertNoErrorsInCode(r'''
+void f(var e) {
+  switch (e) {
+    case 1:
+      break;
+    case 2:
+      break;
+  }
+}
+''');
+  }
+
+  test_int_String() async {
+    await assertErrorsInCode(r'''
+void f(var e) {
+  switch (e) {
+    case 1:
+      break;
+    case 'a':
+      break;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 65, 3),
+    ]);
+  }
+
+  test_repeated() async {
+    await assertErrorsInCode(r'''
+void f(var e) {
+  switch (e) {
+    case 1:
+      break;
+    case 'a':
+      break;
+    case 'b':
+      break;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 65, 3),
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 92, 3),
+    ]);
+  }
+
+  test_runtimeType() async {
+    // Even though A.S and S have a static type of "dynamic", we should see
+    // that they fail to match 3, because they are constant strings.
+    await assertErrorsInCode(r'''
+class A {
+  static const S = 'A.S';
+}
+
+const S = 'S';
+
+void f(var e) {
+  switch (e) {
+    case 3:
+      break;
+    case S:
+      break;
+    case A.S:
+      break;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 120, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES, 145, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
index 017f646..f7b7809 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
@@ -2,7 +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: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';
@@ -10,173 +12,345 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(InvalidOverrideDifferentDefaultValuesNamedTest);
+    defineReflectiveTests(
+      InvalidOverrideDifferentDefaultValuesNamedWithNnbdTest,
+    );
   });
 }
 
 @reflectiveTest
 class InvalidOverrideDifferentDefaultValuesNamedTest
     extends DriverResolutionTest {
-  test_baseClassInOtherLibrary() async {
+  test_abstract_different_base_value() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  void foo({x = 0}) {}
+}
+
+abstract class B extends A {
+  void foo({x = 1});
+}
+''', [
+      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+          86, 5),
+    ]);
+  }
+
+  test_abstract_noDefault_base_noDefault() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo({x});
+}
+
+abstract class B extends A {
+  void foo({x});
+}
+''');
+  }
+
+  test_abstract_noDefault_base_value() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo({x = 0}) {}
+}
+
+abstract class B extends A {
+  void foo({x});
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                    86,
+                    1),
+              ]);
+  }
+
+  test_abstract_noDefault_multipleBase_differentValue() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo({x = 0}) {}
+}
+
+abstract class B {
+  void foo({x = 1});
+}
+
+abstract class C extends A implements B {
+  void foo({x});
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                    142,
+                    1),
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                    142,
+                    1),
+              ]);
+  }
+
+  test_abstract_noDefault_multipleBase_sameValue() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo({x = 0});
+}
+
+abstract class B {
+  void foo({x = 0});
+}
+
+abstract class C extends A implements B {
+  void foo({x});
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                    140,
+                    1),
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                    140,
+                    1),
+              ]);
+  }
+
+  test_abstract_value_base_noDefault() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo({x});
+}
+
+abstract class B extends A {
+  void foo({x = 0});
+}
+''');
+  }
+
+  test_concrete_different() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo({x = 0}) {}
+}
+class B extends A {
+  void foo({x = 1}) {}
+}''', [
+      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+          67, 5),
+    ]);
+  }
+
+  test_concrete_equal() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo({x = 1});
+}
+
+class C extends A {
+  void foo({x = 3 - 2}) {}
+}
+''');
+  }
+
+  test_concrete_equal_function() async {
+    await assertNoErrorsInCode(r'''
+nothing() => 'nothing';
+
+class A {
+  void foo(String a, {orElse = nothing}) {}
+}
+
+class B extends A {
+  void foo(String a, {orElse = nothing}) {}
+}
+''');
+  }
+
+  test_concrete_equal_otherLibrary() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
-  foo([a = 0]) {}
+  void foo([a = 0]) {}
 }
 ''');
     await assertNoErrorsInCode(r'''
 import 'a.dart';
 
 class C extends A {
-  foo([a = 0]) {}
+  void foo([a = 0]) {}
 }
 ''');
   }
 
-  test_differentValues() async {
-    await assertErrorsInCode(r'''
-class A {
-  m({x = 0}) {}
-}
-class B extends A {
-  m({x = 1}) {}
-}''', [
-      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
-          53, 5),
-    ]);
-  }
-
-  test_equal_values_generic_different_files() async {
+  test_concrete_equal_otherLibrary_listLiteral() async {
     newFile('/test/lib/other.dart', content: '''
 class C {
-  f({x: const ['x']}) {}
+  void foo({x: const ['x']}) {}
 }
 ''');
     await assertNoErrorsInCode('''
 import 'other.dart';
 class D extends C {
-  f({x: const ['x']}) {}
+  void foo({x: const ['x']}) {}
 }
 ''');
   }
 
-  test_equal_values_generic_undefined_value_base() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m({x = Undefined.value}) {}
-}
-class B extends A {
-  m({x = 1}) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
-    ]);
-  }
-
-  test_equal_values_generic_undefined_value_both() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m({x = Undefined.value}) {}
-}
-class B extends A {
-  m({x = Undefined2.value2}) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 10),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 10),
-    ]);
-  }
-
-  test_equal_values_generic_undefined_value_derived() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m({x = 1}) {}
-}
-class B extends A {
-  m({x = Undefined.value}) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 57, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 57, 9),
-    ]);
-  }
-
-  test_equalValues() async {
-    await assertNoErrorsInCode(r'''
-abstract class A {
-  foo({x = 1});
-}
-
-class C extends A {
-  foo({x = 3 - 2}) {}
-}
-''');
-  }
-
-  test_equalValues_function() async {
-    await assertNoErrorsInCode(r'''
-nothing() => 'nothing';
-
-class A {
-  foo(String a, {orElse = nothing}) {}
-}
-
-class B extends A {
-  foo(String a, {orElse = nothing}) {}
-}
-''');
-  }
-
-  test_explicitNull_overriddenWith_implicitNull() async {
+  test_concrete_explicitNull_overriddenWith_implicitNull() async {
     // If the base class provided an explicit null value for a default
     // parameter, then it is ok for the derived class to let the default value
     // be implicit, because the implicit default value of null matches the
     // explicit default value of null.
     await assertNoErrorsInCode(r'''
 class A {
-  foo({x: null}) {}
+  void foo({x: null}) {}
 }
 class B extends A {
-  foo({x}) {}
+  void foo({x}) {}
 }
 ''');
   }
 
-  test_implicitNull_overriddenWith_value() async {
+  test_concrete_implicitNull_overriddenWith_value() async {
     // If the base class lets the default parameter be implicit, then it is ok
     // for the derived class to provide an explicit default value, even if it's
     // not null.
     await assertNoErrorsInCode(r'''
 class A {
-  foo({x}) {}
+  void foo({x}) {}
 }
 class B extends A {
-  foo({x = 1}) {}
+  void foo({x = 1}) {}
 }
 ''');
   }
 
-  test_value_overriddenWith_implicitNull() async {
+  test_concrete_undefined_base() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo({x = Undefined.value}) {}
+}
+class B extends A {
+  void foo({x = 1}) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 26, 9),
+    ]);
+  }
+
+  test_concrete_undefined_both() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo({x = Undefined.value}) {}
+}
+class B extends A {
+  void foo({x = Undefined2.value2}) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 26, 9),
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 85, 10),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 85, 10),
+    ]);
+  }
+
+  test_concrete_undefined_derived() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo({x = 1}) {}
+}
+class B extends A {
+  void foo({x = Undefined.value}) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 9),
+    ]);
+  }
+
+  test_concrete_value_overriddenWith_implicitNull() async {
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
     await assertErrorsInCode(r'''
 class A {
-  foo({x: 1}) {}
+  void foo({x: 1}) {}
 }
 class B extends A {
-  foo({x}) {}
+  void foo({x}) {}
 }
 ''', [
       error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
-          56, 1),
+          66, 1),
     ]);
   }
 }
+
+@reflectiveTest
+class InvalidOverrideDifferentDefaultValuesNamedWithNnbdTest
+    extends InvalidOverrideDifferentDefaultValuesNamedTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.non_nullable]
+    ..implicitCasts = false;
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  test_concrete_equal_optIn_extends_optOut() async {
+    newFile('/test/lib/a.dart', content: r'''
+// @dart = 2.7
+class A {
+  void foo({int a = 0}) {}
+}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'a.dart';
+
+class B extends A {
+  void foo({int a = 0}) {}
+}
+''');
+  }
+
+  test_concrete_equal_optOut_extends_optIn() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  void foo({int a = 0}) {}
+}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart = 2.7
+import 'a.dart';
+
+class B extends A {
+  void foo({int a = 0}) {}
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
index 944b726..b13721c 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
@@ -21,172 +21,299 @@
 @reflectiveTest
 class InvalidOverrideDifferentDefaultValuesPositionalTest
     extends DriverResolutionTest {
-  test_baseClassInOtherLibrary() async {
+  test_abstract_different_base_value() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  void foo([x = 0]) {}
+}
+
+abstract class B extends A {
+  void foo([x = 1]);
+}
+''', [
+      error(
+          StaticWarningCode
+              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+          86,
+          5),
+    ]);
+  }
+
+  test_abstract_noDefault_base_noDefault() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo([x]);
+}
+
+abstract class B extends A {
+  void foo([x]);
+}
+''');
+  }
+
+  test_abstract_noDefault_base_value() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo([x = 0]) {}
+}
+
+abstract class B extends A {
+  void foo([x]);
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+                    86,
+                    1),
+              ]);
+  }
+
+  test_abstract_noDefault_multipleBase_differentValue() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo([x = 0]) {}
+}
+
+abstract class B {
+  void foo([x = 1]);
+}
+
+abstract class C extends A implements B {
+  void foo([x]);
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+                    142,
+                    1),
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+                    142,
+                    1),
+              ]);
+  }
+
+  test_abstract_noDefault_multipleBase_sameValue() async {
+    await assertErrorsInCode(
+        r'''
+abstract class A {
+  void foo([x = 0]);
+}
+
+abstract class B {
+  void foo([x = 0]);
+}
+
+abstract class C extends A implements B {
+  void foo([x]);
+}
+''',
+        typeToStringWithNullability
+            ? []
+            : [
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+                    140,
+                    1),
+                error(
+                    StaticWarningCode
+                        .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+                    140,
+                    1),
+              ]);
+  }
+
+  test_abstract_value_base_noDefault() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo([x]);
+}
+
+abstract class B extends A {
+  void foo([x = 0]);
+}
+''');
+  }
+
+  test_concrete_different() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo([x = 0]) {}
+}
+class B extends A {
+  void foo([x = 1]) {}
+}
+''', [
+      error(
+          StaticWarningCode
+              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+          67,
+          5),
+    ]);
+  }
+
+  test_concrete_equal() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo([x = 1]);
+}
+
+class C extends A {
+  void foo([x = 3 - 2]) {}
+}
+''');
+  }
+
+  test_concrete_equal_function() async {
+    await assertNoErrorsInCode(r'''
+nothing() => 'nothing';
+
+class A {
+  void foo(String a, [orElse = nothing]) {}
+}
+
+class B extends A {
+  void foo(String a, [orElse = nothing]) {}
+}
+''');
+  }
+
+  test_concrete_equal_otherLibrary() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
-  foo([a = 0]) {}
+  void foo([x = 0]) {}
 }
 ''');
     await assertNoErrorsInCode(r'''
 import 'a.dart';
 
 class C extends A {
-  foo([a = 0]) {}
+  void foo([a = 0]) {}
 }
 ''');
   }
 
-  test_differentValues() async {
-    await assertErrorsInCode(r'''
-class A {
-  m([x = 0]) {}
-}
-class B extends A {
-  m([x = 1]) {}
-}''', [
-      error(
-          StaticWarningCode
-              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-          53,
-          5),
-    ]);
-  }
-
-  test_equal_values_generic_different_files() async {
+  test_concrete_equal_otherLibrary_listLiteral() async {
     newFile('/test/lib/other.dart', content: '''
 class C {
-  f([x = const ['x']]) {}
+  void foo([x = const ['x']]) {}
 }
 ''');
     await assertNoErrorsInCode('''
 import 'other.dart';
 class D extends C {
-  f([x = const ['x']]) {}
+  void foo([x = const ['x']]) {}
 }
 ''');
   }
 
-  test_equal_values_generic_undefined_value_base() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m([x = Undefined.value]) {}
-}
-class B extends A {
-  m([x = 1]) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
-    ]);
-  }
-
-  test_equal_values_generic_undefined_value_both() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m([x = Undefined.value]) {}
-}
-class B extends A {
-  m([x = Undefined2.value2]) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 19, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 19, 9),
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 10),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 10),
-    ]);
-  }
-
-  test_equal_values_generic_undefined_value_derived() async {
-    // Note: we expect some errors due to the constant referring to undefined
-    // values, but there should not be any INVALID_OVERRIDE... error.
-    await assertErrorsInCode('''
-class A {
-  m([x = 1]) {}
-}
-class B extends A {
-  m([x = Undefined.value]) {}
-}
-''', [
-      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 57, 9),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 57, 9),
-    ]);
-  }
-
-  test_equalValues() async {
-    await assertNoErrorsInCode(r'''
-abstract class A {
-  foo([x = 1]);
-}
-
-class C extends A {
-  foo([x = 3 - 2]) {}
-}
-''');
-  }
-
-  test_equalValues_function() async {
-    await assertNoErrorsInCode(r'''
-nothing() => 'nothing';
-
-class A {
-  foo(String a, [orElse = nothing]) {}
-}
-
-class B extends A {
-  foo(String a, [orElse = nothing]) {}
-}
-''');
-  }
-
-  test_explicitNull_overriddenWith_implicitNull() async {
+  test_concrete_explicitNull_overriddenWith_implicitNull() async {
     // If the base class provided an explicit null value for a default
     // parameter, then it is ok for the derived class to let the default value
     // be implicit, because the implicit default value of null matches the
     // explicit default value of null.
     await assertNoErrorsInCode(r'''
 class A {
-  foo([x = null]) {}
+  void foo([x = null]) {}
 }
 class B extends A {
-  foo([x]) {}
+  void foo([x]) {}
 }
 ''');
   }
 
-  test_implicitNull_overriddenWith_value() async {
+  test_concrete_implicitNull_overriddenWith_value() async {
     // If the base class lets the default parameter be implicit, then it is ok
     // for the derived class to provide an explicit default value, even if it's
     // not null.
     await assertNoErrorsInCode(r'''
 class A {
-  foo([x]) {}
+  void foo([x]) {}
 }
 class B extends A {
-  foo([x = 1]) {}
+  void foo([x = 1]) {}
 }
 ''');
   }
 
-  test_value_overriddenWith_implicitNull() async {
+  test_concrete_undefined_base() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo([x = Undefined.value]) {}
+}
+class B extends A {
+  void foo([x = 1]) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 26, 9),
+    ]);
+  }
+
+  test_concrete_undefined_both() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo([x = Undefined.value]) {}
+}
+class B extends A {
+  void foo([x = Undefined2.value2]) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 26, 9),
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 85, 10),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 85, 10),
+    ]);
+  }
+
+  test_concrete_undefined_derived() async {
+    // Note: we expect some errors due to the constant referring to undefined
+    // values, but there should not be any INVALID_OVERRIDE... error.
+    await assertErrorsInCode('''
+class A {
+  void foo([x = 1]) {}
+}
+class B extends A {
+  void foo([x = Undefined.value]) {}
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 9),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 71, 9),
+    ]);
+  }
+
+  test_concrete_value_overriddenWith_implicitNull() async {
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
     await assertErrorsInCode(r'''
 class A {
-  foo([x = 1]) {}
+  void foo([x = 1]) {}
 }
 class B extends A {
-  foo([x]) {}
+  void foo([x]) {}
 }
 ''', [
       error(
           StaticWarningCode
               .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-          57,
+          67,
           1),
     ]);
   }
@@ -203,7 +330,7 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  test_equal_optIn_extends_optOut() async {
+  test_concrete_equal_optIn_extends_optOut() async {
     newFile('/test/lib/a.dart', content: r'''
 // @dart = 2.7
 class A {
@@ -220,7 +347,7 @@
 ''');
   }
 
-  test_equal_optOut_extends_optIn() async {
+  test_concrete_equal_optOut_extends_optIn() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
   void foo([int a = 0]) {}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index aad1f2d..bfcaec1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -2,7 +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: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';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(InvalidOverrideTest);
+    defineReflectiveTests(InvalidOverrideWithNnbdTest);
   });
 }
 
@@ -488,3 +491,45 @@
     ]);
   }
 }
+
+@reflectiveTest
+class InvalidOverrideWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.non_nullable]
+    ..implicitCasts = false;
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  test_method_viaLegacy_returnType_notSubtype() async {
+    newFile('/test/lib/a.dart', content: r'''
+class Nullable {
+  int? foo() => 0;
+}
+
+class NonNullable {
+  int foo() => 0;
+}
+''');
+
+    newFile('/test/lib/b.dart', content: r'''
+// @dart=2.6
+import 'a.dart';
+
+class A extends Nullable implements NonNullable {}
+''');
+
+    await assertErrorsInCode('''
+import 'b.dart';
+
+class B extends A {}
+
+class C extends A {   
+  int? foo() => 0;
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 70, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart b/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart
new file mode 100644
index 0000000..8e7ff2e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_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:analyzer/dart/analysis/features.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(MissingEnumConstantInSwitchTest);
+    defineReflectiveTests(MissingEnumConstantInSwitchWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class MissingEnumConstantInSwitchTest extends DriverResolutionTest {
+  test_default() async {
+    await assertNoErrorsInCode('''
+enum E { one, two, three }
+
+void f(E e) {
+  switch (e) {
+    case E.one:
+      break;
+    default:
+      break;
+  }
+}
+''');
+  }
+
+  test_first() async {
+    await assertErrorsInCode('''
+enum E { one, two, three }
+
+void f(E e) {
+  switch (e) {
+    case E.two:
+    case E.three:
+      break;
+  }
+}
+''', [
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 44, 10),
+    ]);
+  }
+
+  test_last() async {
+    await assertErrorsInCode('''
+enum E { one, two, three }
+
+void f(E e) {
+  switch (e) {
+    case E.one:
+    case E.two:
+      break;
+  }
+}
+''', [
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 44, 10),
+    ]);
+  }
+
+  test_middle() async {
+    await assertErrorsInCode('''
+enum E { one, two, three }
+
+void f(E e) {
+  switch (e) {
+    case E.one:
+    case E.three:
+      break;
+  }
+}
+''', [
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 44, 10),
+    ]);
+  }
+}
+
+@reflectiveTest
+class MissingEnumConstantInSwitchWithNnbdTest
+    extends MissingEnumConstantInSwitchTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_nullable() async {
+    await assertErrorsInCode('''
+enum E { one, two }
+
+void f(E? e) {
+  switch (e) {
+    case E.one:
+    case E.two:
+      break;
+  }
+}
+''', [
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 38, 10),
+    ]);
+  }
+
+  test_nullable_default() async {
+    await assertNoErrorsInCode('''
+enum E { one, two }
+
+void f(E? e) {
+  switch (e) {
+    case E.one:
+      break;
+    default:
+      break;
+  }
+}
+''');
+  }
+
+  test_nullable_null() async {
+    await assertNoErrorsInCode('''
+enum E { one, two }
+
+void f(E? e) {
+  switch (e) {
+    case E.one:
+      break;
+    case E.two:
+      break;
+    case null:
+      break;
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_enum_value_in_switch_test.dart b/pkg/analyzer/test/src/diagnostics/missing_enum_value_in_switch_test.dart
deleted file mode 100644
index 6ad7d34..0000000
--- a/pkg/analyzer/test/src/diagnostics/missing_enum_value_in_switch_test.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/driver_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(MissingEnumConstantInSwitchTest);
-  });
-}
-
-@reflectiveTest
-class MissingEnumConstantInSwitchTest extends DriverResolutionTest {
-  test_first() async {
-    await assertErrorsInCode('''
-enum E { ONE, TWO, THREE }
-bool odd(E e) {
-  switch (e) {
-    case E.TWO:
-    case E.THREE: return true;
-  }
-  return false;
-}''', [
-      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 45, 10),
-    ]);
-  }
-
-  test_last() async {
-    await assertErrorsInCode('''
-enum E { ONE, TWO, THREE }
-bool odd(E e) {
-  switch (e) {
-    case E.ONE:
-    case E.TWO: return true;
-  }
-  return false;
-}''', [
-      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 45, 10),
-    ]);
-  }
-
-  test_middle() async {
-    await assertErrorsInCode('''
-enum E { ONE, TWO, THREE }
-bool odd(E e) {
-  switch (e) {
-    case E.ONE:
-    case E.THREE: return true;
-  }
-  return false;
-}''', [
-      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 45, 10),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart
new file mode 100644
index 0000000..f0de552
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All 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(NonConstantCaseExpressionFromDeferredLibraryTest);
+  });
+}
+
+@reflectiveTest
+class NonConstantCaseExpressionFromDeferredLibraryTest
+    extends DriverResolutionTest {
+  test_nested() async {
+    newFile('/test/lib/a.dart', content: '''
+const int c = 0;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart' deferred as a;
+
+void f(int e) {
+  switch (e) {
+    case a.c + 1:
+      break;
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+          72,
+          7),
+    ]);
+  }
+
+  test_simple() async {
+    newFile('/test/lib/a.dart', content: '''
+const int c = 0;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart' deferred as a;
+
+void f(int e) {
+  switch (e) {
+    case a.c:
+      break;
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+          72,
+          3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_test.dart
new file mode 100644
index 0000000..4203442
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_test.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.
+
+import 'package:analyzer/dart/analysis/features.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(NonConstantCaseExpressionTest);
+    defineReflectiveTests(NonConstantCaseExpressionWithNnbdTest);
+  });
+}
+
+@reflectiveTest
+class NonConstantCaseExpressionTest extends DriverResolutionTest {
+  test_constField() async {
+    await assertNoErrorsInCode(r'''
+void f(C e) {
+  switch (e) {
+    case C.zero:
+      break;
+    default:
+      break;
+  }
+}
+
+class C {
+  static const zero = C(0);
+
+  final int a;
+  const C(this.a);
+}
+''');
+  }
+
+  test_parameter() async {
+    await assertErrorsInCode(r'''
+void f(var e, int a) {
+  switch (e) {
+    case 3 + a:
+      break;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION, 51, 1),
+    ]);
+  }
+
+  test_typeLiteral() async {
+    await assertNoErrorsInCode(r'''
+void f(var e) {
+  switch (e) {
+    case bool:
+    case int:
+      break;
+    default:
+      break;
+  }
+}
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantCaseExpressionWithNnbdTest
+    extends NonConstantCaseExpressionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_default_value_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_default_value_test.dart
new file mode 100644
index 0000000..e3ba1db
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_default_value_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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/test_support.dart';
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonConstantDefaultValueTest);
+  });
+}
+
+@reflectiveTest
+class NonConstantDefaultValueTest extends DriverResolutionTest {
+  test_appliedTypeParameter_defaultConstructorValue() async {
+    await assertErrorsInCode(r'''
+void f<T>(T t) => t;
+
+class C<T> {
+  final void Function(T) p;
+  const C({this.p = f});
+}
+''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 83, 1)]);
+  }
+
+  test_appliedTypeParameter_defaultFunctionValue() async {
+    await assertErrorsInCode(r'''
+void f<T>(T t) => t;
+
+void bar<T>([void Function(T) p = f]) {}
+''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 56, 1)]);
+  }
+
+  test_appliedTypeParameter_defaultMethodValue() async {
+    await assertErrorsInCode(r'''
+void f<T>(T t) => t;
+
+class C<T> {
+  void foo([void Function(T) p = f]) {}
+}
+''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 68, 1)]);
+  }
+
+  test_appliedTypeParameter_nested() async {
+    await assertErrorsInCode(r'''
+void f<T>(T t) => t;
+
+void bar<T>([void Function(List<T>) p = f]) {}
+''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 62, 1)]);
+  }
+
+  test_appliedTypeParameter_nestedFunction() async {
+    await assertErrorsInCode(r'''
+void f<T>(T t) => t;
+
+void bar<T>([void Function(T Function()) p = f]) {}
+''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 67, 1)]);
+  }
+
+  test_noAppliedTypeParameters_defaultConstructorValue_dynamic() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T t) => t;
+
+class C<T> {
+  final dynamic p;
+  const C({this.p = f});
+}
+''');
+  }
+
+  test_noAppliedTypeParameters_defaultConstructorValue_genericFn() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T t) => t;
+
+class C<T> {
+  final void Function<T>(T) p;
+  const C({this.p = f});
+}
+''');
+  }
+
+  test_noAppliedTypeParameters_defaultFunctionValue_genericFn() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T t) => t;
+
+void bar<T>([void Function<T>(T) p = f]) {}
+''');
+  }
+
+  test_noAppliedTypeParameters_defaultMethodValue_genericFn() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T t) => t;
+
+class C<T> {
+  void foo([void Function<T>(T) p = f]) {}
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 7411a24..5223e54 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -33,6 +33,8 @@
 import 'case_block_not_terminated_test.dart' as case_block_not_terminated;
 import 'case_expression_type_implements_equals_test.dart'
     as case_expression_type_implements_equals;
+import 'case_expression_type_is_not_switch_expression_subtype_test.dart'
+    as case_expression_type_is_not_switch_expression_subtype;
 import 'cast_to_non_type_test.dart' as cast_to_non_type;
 import 'concrete_class_with_abstract_member_test.dart'
     as concrete_class_with_abstract_member;
@@ -158,6 +160,8 @@
 import 'import_duplicated_library_named_test.dart'
     as import_duplicated_library_named;
 import 'import_of_non_library_test.dart' as import_of_non_library;
+import 'inconsistent_case_expression_types_test.dart'
+    as inconsistent_case_expression_types;
 import 'inference_failure_on_collection_literal_test.dart'
     as inference_failure_on_collection_literal;
 import 'inference_failure_on_function_return_type_test.dart'
@@ -249,7 +253,8 @@
     as missing_annotation_on_struct_field;
 import 'missing_default_value_for_parameter_test.dart'
     as missing_default_value_for_parameter;
-import 'missing_enum_value_in_switch_test.dart' as missing_enum_value_in_switch;
+import 'missing_enum_constant_in_switch_test.dart'
+    as missing_enum_constant_in_switch;
 import 'missing_exception_value_test.dart' as missing_exception_value;
 import 'missing_field_type_in_struct_test.dart' as missing_field_type_in_struct;
 import 'missing_js_lib_annotation_test.dart' as missing_js_lib_annotation;
@@ -283,6 +288,10 @@
 import 'non_bool_condition_test.dart' as non_bool_condition;
 import 'non_bool_negation_expression_test.dart' as non_bool_negation_expression;
 import 'non_bool_operand_test.dart' as non_bool_operand;
+import 'non_constant_case_expression_from_deferred_library_test.dart'
+    as non_constant_case_expression_from_deferred_library;
+import 'non_constant_case_expression_test.dart' as non_constant_case_expression;
+import 'non_constant_default_value_test.dart' as non_constant_default_value;
 import 'non_constant_list_element_from_deferred_library_test.dart'
     as non_constant_list_element_from_deferred_library;
 import 'non_constant_list_element_test.dart' as non_constant_list_element;
@@ -513,6 +522,7 @@
     can_be_null_after_null_aware.main();
     case_block_not_terminated.main();
     case_expression_type_implements_equals.main();
+    case_expression_type_is_not_switch_expression_subtype.main();
     cast_to_non_type.main();
     concrete_class_with_abstract_member.main();
     conflicting_generic_interfaces.main();
@@ -594,6 +604,7 @@
     implicit_this_reference_in_initializer.main();
     import_deferred_library_with_load_function.main();
     import_duplicated_library_named.main();
+    inconsistent_case_expression_types.main();
     import_of_non_library.main();
     inference_failure_on_collection_literal.main();
     inference_failure_on_function_return_type.main();
@@ -655,7 +666,7 @@
     mismatched_annotation_on_struct_field.main();
     missing_annotation_on_struct_field.main();
     missing_default_value_for_parameter.main();
-    missing_enum_value_in_switch.main();
+    missing_enum_constant_in_switch.main();
     missing_exception_value.main();
     missing_field_type_in_struct.main();
     missing_js_lib_annotation.main();
@@ -682,6 +693,8 @@
     non_bool_negation_expression.main();
     non_bool_operand.main();
     non_constant_list_element.main();
+    non_constant_case_expression_from_deferred_library.main();
+    non_constant_case_expression.main();
     non_constant_list_element_from_deferred_library.main();
     non_constant_map_key.main();
     non_constant_map_key_from_deferred_library.main();
@@ -800,6 +813,7 @@
     undefined_prefixed_name.main();
     undefined_setter.main();
     undefined_shown_name.main();
+    non_constant_default_value.main();
     unnecessary_cast.main();
     unnecessary_no_such_method.main();
     unnecessary_non_null_assertion.main();
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 494a90d..bce1949 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -15,6 +15,9 @@
     defineReflectiveTests(
       TypeArgumentNotMatchingBoundsWithExtensionMethodsTest,
     );
+    defineReflectiveTests(
+      TypeArgumentNotMatchingBoundsWithNnbdTest,
+    );
   });
 }
 
@@ -32,22 +35,6 @@
     ]);
   }
 
-  test_not_matching_bounds() async {
-    // There should be an error, because Bar's type argument T is Foo, which
-    // doesn't extends Foo<T>.
-    await assertErrorsInCode('''
-class Foo<T> {}
-class Bar<T extends Foo<T>> {}
-class Baz extends Bar {}
-void main() {}
-''', [
-      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
-    ]);
-    // Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
-    assertType(result.unit.declaredElement.getType('Baz').supertype,
-        'Bar<Foo<dynamic>>');
-  }
-
   test_const() async {
     await assertErrorsInCode(r'''
 class A {}
@@ -112,7 +99,7 @@
 class A {}
 class B {}
 class G<E extends A> {}
-G<B> f() { return null; }
+G<B> f() => throw 0;
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
     ]);
@@ -223,7 +210,7 @@
 class B {}
 class G<E extends A> {}
 class C {
-  G<B> m() { return null; }
+  G<B> m() => throw 0;
 }
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 60, 1),
@@ -262,12 +249,28 @@
     ]);
   }
 
+  test_not_matching_bounds() async {
+    // There should be an error, because Bar's type argument T is Foo, which
+    // doesn't extends Foo<T>.
+    await assertErrorsInCode('''
+class Foo<T> {}
+class Bar<T extends Foo<T>> {}
+class Baz extends Bar {}
+void main() {}
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
+    ]);
+    // Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
+    assertType(result.unit.declaredElement.getType('Baz').supertype,
+        'Bar<Foo<dynamic>>');
+  }
+
   test_ofFunctionTypeAlias() async {
     await assertErrorsInCode(r'''
 class A {}
 class B {}
 typedef F<T extends A>();
-F<B> fff;
+F<B> fff = (throw 42);
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 50, 1),
     ]);
@@ -278,7 +281,7 @@
 class MyClass<T> {}
 typedef MyFunction<T, P extends MyClass<T>>();
 class A<T, P extends MyClass<T>> {
-  MyFunction<T, P> f;
+  MyFunction<T, P> f = (throw 0);
 }
 ''');
   }
@@ -288,16 +291,16 @@
 class A {}
 class B extends A {}
 typedef F<T extends A>();
-F<A> fa;
-F<B> fb;
+F<A> fa = (throw 0);
+F<B> fb = (throw 0);
 ''');
   }
 
   test_ofFunctionTypeAlias_noBound_matching() async {
     await assertNoErrorsInCode(r'''
 typedef F<T>();
-F<int> f1;
-F<String> f2;
+F<int> f1 = (throw 0);
+F<String> f2 = (throw 0);
 ''');
   }
 
@@ -332,7 +335,7 @@
 class B {}
 class C<E> {}
 class D<E extends A> {}
-C<D<B>> Var;
+C<D<B>> c = (throw 0);
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 64, 1),
     ]);
@@ -355,7 +358,7 @@
 class A {}
 class B {}
 class G<E extends A> {}
-G<B> g;
+G<B> g = (throw 0);
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
     ]);
@@ -409,3 +412,25 @@
     ]);
   }
 }
+
+@reflectiveTest
+class TypeArgumentNotMatchingBoundsWithNnbdTest
+    extends TypeArgumentNotMatchingBoundsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_extends_optIn_fromOptOut_Null() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A<X extends int> {}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+class A1<T extends Null> extends A<T> {}
+''');
+  }
+}
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 fe4e047..1e73007d 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
@@ -7,6 +7,7 @@
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/lint/linter.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -17,6 +18,7 @@
     defineReflectiveTests(CanBeConstConstructorTest);
     defineReflectiveTests(CanBeConstTest);
     defineReflectiveTests(EvaluateExpressionTest);
+    defineReflectiveTests(PubDependencyTest);
   });
 }
 
@@ -289,3 +291,32 @@
     return context.evaluateConstant(node);
   }
 }
+
+@reflectiveTest
+class PubDependencyTest extends AbstractLinterContextTest {
+  test_dependencies() async {
+    newFile('/test/pubspec.yaml', content: '''
+name: test
+
+dependencies:
+  args: '>=0.12.1 <2.0.0'
+  charcode: ^1.1.0
+''');
+    await resolve(r'''
+/// Dummy class.
+class C { }
+''');
+
+    expect(context.package, TypeMatcher<PubWorkspacePackage>());
+    final pubPackage = context.package as PubWorkspacePackage;
+    final pubspec = pubPackage.pubspec;
+
+    final argsDep = pubspec.dependencies
+        .singleWhere((element) => element.name.text == 'args');
+    expect(argsDep.version.value.text, '>=0.12.1 <2.0.0');
+
+    final charCodeDep = pubspec.dependencies
+        .singleWhere((element) => element.name.text == 'charcode');
+    expect(charCodeDep.version.value.text, '^1.1.0');
+  }
+}
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 0e6fd9b..5936f6b 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -303,7 +304,8 @@
         fileContentOverlay,
         null,
         sourceFactory,
-        analysisOptions);
+        analysisOptions,
+        packages: Packages.empty);
     scheduler.start();
 
     mainUnit = (await _driver.getResult(mainFile.path)).unit;
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 5081ede..babb02e 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -146,6 +147,7 @@
         ResourceUriResolver(resourceProvider)
       ]),
       analysisOptions,
+      packages: Packages.empty,
       retainDataForTesting: true);
   scheduler.start();
   var result = await driver
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index dd2c150..00dbad9 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -6737,10 +6737,15 @@
 is used and type arguments are provided, but the number of type arguments
 isn't the same as the number of type parameters.
 
+The analyzer also produces this diagnostic when a constructor is invoked
+and the number of type arguments doesn't match the number of type
+parameters declared for the class.
+
 #### Examples
 
 The following code produces this diagnostic because `C` has one type
-parameter but two type arguments are provided:
+parameter but two type arguments are provided when it is used as a type
+annotation:
 
 {% prettify dart %}
 class C<E> {}
@@ -6748,6 +6753,15 @@
 void f([!C<int, int>!] x) {}
 {% endprettify %}
 
+The following code produces this diagnostic because `C` declares one type
+parameter, but two type arguments are provided when creating an instance:
+
+{% prettify dart %}
+class C<E> {}
+
+var c = [!C<int, int>!]();
+{% endprettify %}
+
 #### Common fixes
 
 Add or remove type arguments, as necessary, to match the number of type
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 48d9d71..6ad947b 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.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/cache.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -422,6 +423,8 @@
       summaryDataStore.addBundle(null, sdkBundle);
     });
 
+    var packages = _findPackages(rootPath);
+
     sourceFactory = SourceFactory(<UriResolver>[
       DartUriResolver(sdk),
       TrackingInSummaryUriResolver(
@@ -435,15 +438,17 @@
 
     AnalysisDriverScheduler scheduler = AnalysisDriverScheduler(logger);
     analysisDriver = AnalysisDriver(
-        scheduler,
-        logger,
-        resourceProvider,
-        MemoryByteStore(),
-        FileContentOverlay(),
-        null,
-        sourceFactory,
-        analysisOptions,
-        externalSummaries: summaryDataStore);
+      scheduler,
+      logger,
+      resourceProvider,
+      MemoryByteStore(),
+      FileContentOverlay(),
+      null,
+      sourceFactory,
+      analysisOptions,
+      externalSummaries: summaryDataStore,
+      packages: packages,
+    );
 
     declaredVariables = DeclaredVariables.fromMap(options.definedVariables);
     analysisDriver.declaredVariables = declaredVariables;
@@ -494,6 +499,14 @@
     return uriToFileMap;
   }
 
+  Packages _findPackages(String path) {
+    if (path != null) {
+      return findPackagesFrom(resourceProvider, resourceProvider.getFile(path));
+    } else {
+      return Packages.empty;
+    }
+  }
+
   /// Ensure that the parsed unit for [absoluteUri] is available.
   ///
   /// If the unit is in the input [summaryDataStore], do nothing.
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index e92cb2c..9bbde0a 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -581,7 +581,8 @@
         FileContentOverlay(),
         ContextRoot(source, [], pathContext: resourceProvider.pathContext),
         sourceFactory,
-        analysisOptions);
+        analysisOptions,
+        packages: packageInfo.packages);
     analysisDriver.results.listen((_) {});
     analysisDriver.exceptions.listen((_) {});
     scheduler.start();
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 2275192..7bef44e 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -9,6 +9,7 @@
 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';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/exception/exception.dart';
@@ -1090,6 +1091,9 @@
     // Write the simple name.
     String name = element.displayName;
     write(name);
+    if (type.nullabilitySuffix == NullabilitySuffix.question) {
+      write('?');
+    }
 
     // Write type arguments.
     if (type is ParameterizedType) {
diff --git a/pkg/analyzer_plugin/test/plugin/mocks.dart b/pkg/analyzer_plugin/test/plugin/mocks.dart
index ee54ad3..93409de 100644
--- a/pkg/analyzer_plugin/test/plugin/mocks.dart
+++ b/pkg/analyzer_plugin/test/plugin/mocks.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/generated/engine.dart'
@@ -34,7 +35,8 @@
             FileContentOverlay(),
             null,
             SourceFactory([]),
-            AnalysisOptionsImpl());
+            AnalysisOptionsImpl(),
+            packages: Packages.empty);
 
   @override
   bool get hasFilesToAnalyze => false;
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index c91a030..5742018 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -183,7 +183,6 @@
     'dart:io',
     'dart:js',
     'dart:js_util',
-    'dart:mirrors',
     'dart:svg',
     'dart:web_audio',
     'dart:web_gl',
@@ -202,7 +201,6 @@
     'dart:io',
     'dart:js',
     'dart:js_util',
-    'dart:mirrors',
   ]
 };
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 3e73acb..102bb1a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -2735,7 +2735,8 @@
         : namedTypes.add(param));
     var allNamedTypes = type.namedParameters;
 
-    var returnType = _emitType(type.returnType);
+    var returnType = _emitNullabilityWrapper(
+        _emitType(type.returnType), type.returnType.nullability);
     var requiredArgs = _emitTypeNames(requiredTypes, requiredParams, member);
 
     List<js_ast.Expression> typeParts;
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 8295e95..b3168b6 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -45,7 +45,6 @@
         'dart:_internal',
         'dart:_isolate_helper',
         'dart:_js_helper',
-        'dart:_js_mirrors',
         'dart:_js_primitives',
         'dart:_metadata',
         'dart:_native_typed_data',
@@ -58,7 +57,6 @@
         'dart:js',
         'dart:js_util',
         'dart:math',
-        'dart:mirrors',
         'dart:typed_data',
         'dart:indexed_db',
         'dart:html',
diff --git a/pkg/dev_compiler/tool/check_nnbd_sdk.dart b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
index 1dc3bde..8f4ccb3 100644
--- a/pkg/dev_compiler/tool/check_nnbd_sdk.dart
+++ b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
@@ -46,11 +46,60 @@
     '--nnbd',
   ]);
 
-  var emptyProgramUri = baseUri.resolve('empty_program.dart');
-  File.fromUri(emptyProgramUri).writeAsStringSync('''
+  var isWeb = false;
+  var isNative = false;
+  switch (target) {
+    case 'dartdevc':
+    case 'dart2js':
+      isWeb = true;
+      break;
+    case 'flutter':
+    case 'vm':
+      isNative = true;
+      break;
+  }
+
+  var core = '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:core';
+import 'dart:developer';
+import 'dart:math';
+import 'dart:typed_data';
+''';
+
+  var web = !isWeb
+      ? ''
+      : '''
 import 'dart:js';
 import 'dart:js_util';
+import 'dart:indexed_db';
 import 'dart:html';
+import 'dart:html_common';
+import 'dart:svg';
+import 'dart:web_audio';
+import 'dart:web_gl';
+import 'dart:web_sql';
+''';
+
+  var native = !isNative
+      ? '''
+import 'dart:io';
+import 'dart:isolate';
+'''
+      : '''
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:mirrors';
+''';
+
+  var emptyProgramUri = baseUri.resolve('empty_program.dart');
+  File.fromUri(emptyProgramUri).writeAsStringSync('''
+$core
+$web
+$native
 
 main() {}
 ''');
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 65bb306..41fd8e5 100644
--- a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
@@ -18,31 +18,31 @@
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|15319|3|15|All final variables must be initialized, but 'elements', 'form', and 4 others are not.
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|15992|3|11|All final variables must be initialized, but 'length' is not.
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|1760|3|13|All final variables must be initialized, but 'form', 'labels', and 3 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|17995|3|13|All final variables must be initialized, but '_get_contentWindow' and 'sandbox' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|18185|3|12|All final variables must be initialized, but 'complete', 'currentSrc', and 2 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|18294|3|12|All final variables must be initialized, but '_get_valueAsDate', 'entries', and 6 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19245|3|12|All final variables must be initialized, but 'control' and 'form' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19274|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19324|3|11|All final variables must be initialized, but 'import', 'relList', and 2 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19455|3|10|All final variables must be initialized, but 'areas' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19559|3|12|All final variables must be initialized, but 'audioDecodedByteCount', 'audioTracks', and 18 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20673|3|12|All final variables must be initialized, but 'labels' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|22075|3|4|All final variables must be initialized, but 'baseUri', 'childNodes', and 11 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|22804|3|13|All final variables must be initialized, but '_get_contentWindow', 'form', and 3 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|23190|3|13|All final variables must be initialized, but 'form' and 'index' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|23241|3|13|All final variables must be initialized, but 'form', 'htmlFor', and 5 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|24751|3|15|All final variables must be initialized, but 'labels' and 'position' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|26240|3|13|All final variables must be initialized, but 'form', 'labels', and 4 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|27806|3|12|All final variables must be initialized, but 'sheet' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|27976|3|16|All final variables must be initialized, but 'cellIndex' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28075|3|12|All final variables must be initialized, but '_rows' and '_tBodies' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28161|3|15|All final variables must be initialized, but '_cells', 'rowIndex', and 1 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28217|3|19|All final variables must be initialized, but '_rows' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28271|3|15|All final variables must be initialized, but 'content' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28344|3|15|All final variables must be initialized, but 'form', 'labels', and 5 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|29082|3|12|All final variables must be initialized, but 'readyState' and 'track' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|29888|3|12|All final variables must be initialized, but 'decodedFrameCount', 'droppedFrameCount', and 2 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|38892|3|8|All final variables must be initialized, but 'sourceCapabilities' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|17990|3|13|All final variables must be initialized, but '_get_contentWindow' and 'sandbox' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|18180|3|12|All final variables must be initialized, but 'complete', 'currentSrc', and 2 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|18289|3|12|All final variables must be initialized, but '_get_valueAsDate', 'entries', and 6 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19240|3|12|All final variables must be initialized, but 'control' and 'form' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19269|3|13|All final variables must be initialized, but 'form' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19319|3|11|All final variables must be initialized, but 'import', 'relList', and 2 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19450|3|10|All final variables must be initialized, but 'areas' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19554|3|12|All final variables must be initialized, but 'audioDecodedByteCount', 'audioTracks', and 18 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20668|3|12|All final variables must be initialized, but 'labels' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|22070|3|4|All final variables must be initialized, but 'baseUri', 'childNodes', and 11 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|22794|3|13|All final variables must be initialized, but '_get_contentWindow', 'form', and 3 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|23180|3|13|All final variables must be initialized, but 'form' and 'index' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|23231|3|13|All final variables must be initialized, but 'form', 'htmlFor', and 5 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|24741|3|15|All final variables must be initialized, but 'labels' and 'position' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|26230|3|13|All final variables must be initialized, but 'form', 'labels', and 4 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|27796|3|12|All final variables must be initialized, but 'sheet' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|27966|3|16|All final variables must be initialized, but 'cellIndex' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28065|3|12|All final variables must be initialized, but '_rows' and '_tBodies' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28151|3|15|All final variables must be initialized, but '_cells', 'rowIndex', and 1 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28207|3|19|All final variables must be initialized, but '_rows' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28261|3|15|All final variables must be initialized, but 'content' is not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|28334|3|15|All final variables must be initialized, but 'form', 'labels', and 5 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|29065|3|12|All final variables must be initialized, but 'readyState' and 'track' are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|29871|3|12|All final variables must be initialized, but 'decodedFrameCount', 'droppedFrameCount', and 2 others are not.
+ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|38875|3|8|All final variables must be initialized, but 'sourceCapabilities' is not.
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|453|3|13|All final variables must be initialized, but 'origin' is not.
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|8511|3|15|All final variables must be initialized, but 'options' is not.
 ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|972|3|11|All final variables must be initialized, but 'origin' is not.
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 2aae401..8b13789 100644
--- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
@@ -1,281 +1 @@
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|10434|18|18|'DocumentFragment._firstElementChild' ('Element? Function()') isn't a valid override of 'ParentNode._firstElementChild' ('Element Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|10437|18|17|'DocumentFragment._lastElementChild' ('Element? Function()') isn't a valid override of 'ParentNode._lastElementChild' ('Element Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|14819|18|18|'Element._firstElementChild' ('Element? Function()') isn't a valid override of 'ParentNode._firstElementChild' ('Element Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|14822|18|17|'Element._lastElementChild' ('Element? Function()') isn't a valid override of 'ParentNode._lastElementChild' ('Element Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|17761|12|16|'HtmlDocument.registerElement2' ('Function Function(String, [Map<dynamic, dynamic>])') isn't a valid override of 'Document.registerElement2' ('Function Function(String, [Map<dynamic, dynamic>?])').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|19243|15|5|'InputElement.files' ('List<File>? Function()') isn't a valid override of 'FileUploadInputElement.files' ('List<File> Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|19361|11|18|'InputElement.selectionDirection' ('String? Function()') isn't a valid override of 'TextInputElementBase.selectionDirection' ('String Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|19363|8|12|'InputElement.selectionEnd' ('int? Function()') isn't a valid override of 'TextInputElementBase.selectionEnd' ('int Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|19365|8|14|'InputElement.selectionStart' ('int? Function()') isn't a valid override of 'TextInputElementBase.selectionStart' ('int Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|34277|7|18|'_WrappedEvent._selector' ('String? Function()') isn't a valid override of 'Event._selector' ('String Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|34300|29|9|'_BeforeUnloadEventStreamProvider.forTarget' ('Stream<BeforeUnloadEvent> Function(EventTarget, {bool useCapture})') isn't a valid override of 'EventStreamProvider.forTarget' ('Stream<BeforeUnloadEvent> Function(EventTarget?, {bool useCapture})').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|40984|7|8|'_WrappedEvent._selector' ('String? Function()') isn't a valid override of 'Event._selector' ('String Function()').
-ERROR|COMPILE_TIME_ERROR|INVALID_OVERRIDE|lib/html/dart2js/html_dart2js.dart|41230|11|9|'_WrappedEvent._selector' ('String? Function()') isn't a valid override of 'Event._selector' ('String Function()').
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10275|15|10|The parameter 'extendsTag' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10281|49|13|The parameter 'typeExtension' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10298|15|13|The parameter 'typeExtension' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10305|16|10|The parameter 'whatToShow' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10305|39|6|The parameter 'filter' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10310|16|10|The parameter 'whatToShow' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10310|39|6|The parameter 'filter' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10336|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10336|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10342|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10342|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10395|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10395|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10414|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|10414|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|1179|32|3|The parameter 'src' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|12604|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|12604|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|12653|43|13|The parameter 'typeExtention' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13055|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13055|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13208|40|9|The parameter 'alignment' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13303|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13303|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13558|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13558|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13693|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|13693|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|15730|13|10|The parameter 'useCapture' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|15740|13|10|The parameter 'useCapture' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|1586|40|4|The parameter 'type' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|1586|53|7|The parameter 'endings' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|17389|14|6|The parameter 'oldUrl' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|17390|14|6|The parameter 'newUrl' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|17761|46|7|The parameter 'options' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|17767|62|10|The parameter 'extendsTag' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|17811|60|10|The parameter 'extendsTag' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18045|13|15|The parameter 'withCredentials' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18046|14|12|The parameter 'responseType' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18047|27|14|The parameter 'requestHeaders' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18048|12|10|The parameter 'onProgress' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18126|15|6|The parameter 'method' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18127|12|15|The parameter 'withCredentials' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18128|14|12|The parameter 'responseType' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18129|14|8|The parameter 'mimeType' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18130|27|14|The parameter 'requestHeaders' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18132|12|10|The parameter 'onProgress' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18236|15|6|The parameter 'method' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|18236|30|8|The parameter 'sendData' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|20074|15|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|20077|11|8|The parameter 'location' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|20078|11|11|The parameter 'keyLocation' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|21667|14|4|The parameter 'data' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|21668|14|6|The parameter 'origin' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|21669|14|11|The parameter 'lastEventId' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|21670|14|6|The parameter 'source' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|21764|13|10|The parameter 'useCapture' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22344|15|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22357|19|13|The parameter 'relatedTarget' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22652|13|9|The parameter 'childList' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22653|12|10|The parameter 'attributes' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22654|12|13|The parameter 'characterData' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22655|12|7|The parameter 'subtree' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22656|12|17|The parameter 'attributeOldValue' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|22657|12|21|The parameter 'characterDataOldValue' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|2269|52|7|The parameter 'quality' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|25265|66|7|The parameter 'options' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|27107|53|16|The parameter 'mediaConstraints' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|27149|61|8|The parameter 'selector' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|2845|18|10|The parameter 'sourceRect' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29465|14|3|The parameter 'key' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29466|14|8|The parameter 'oldValue' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29467|14|8|The parameter 'newValue' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29468|14|3|The parameter 'url' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29469|15|11|The parameter 'storageArea' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29835|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29835|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29919|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29919|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29982|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|29982|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|30077|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|30077|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|30306|14|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|30307|14|4|The parameter 'data' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|3035|49|8|The parameter 'maxWidth' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|31175|15|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|3213|27|4|The parameter 'data' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|3233|14|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|3234|14|4|The parameter 'data' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|32354|15|4|The parameter 'view' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|3235|14|6|The parameter 'locale' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|32371|19|13|The parameter 'relatedTarget' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|32606|52|7|The parameter 'options' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|34231|25|16|The parameter 'creationCallback' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|4113|63|8|The parameter 'priority' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|5292|63|8|The parameter 'priority' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/html/dart2js/html_dart2js.dart|8836|60|6|The parameter 'detail' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|234|21|3|The parameter 'key' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|308|61|13|The parameter 'autoIncrement' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|473|12|7|The parameter 'version' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|474|12|15|The parameter 'onUpgradeNeeded' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|475|12|9|The parameter 'onBlocked' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|500|56|9|The parameter 'onBlocked' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|604|22|5|The parameter 'range' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|604|36|9|The parameter 'direction' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|604|52|11|The parameter 'autoAdvance' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|632|22|5|The parameter 'range' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|632|36|9|The parameter 'direction' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|632|52|11|The parameter 'autoAdvance' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|847|22|5|The parameter 'range' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|847|36|9|The parameter 'direction' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|847|52|11|The parameter 'autoAdvance' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|868|49|6|The parameter 'unique' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/indexed_db/dart2js/indexed_db_dart2js.dart|868|62|10|The parameter 'multiEntry' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3109|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3109|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3155|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3155|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3184|22|9|The parameter 'validator' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|MISSING_DEFAULT_VALUE_FOR_PARAMETER|lib/svg/dart2js/svg_dart2js.dart|3184|51|13|The parameter 'treeSanitizer' can't have a value of 'null' because of its type, so it must either be a required parameter or have a default value.
-ERROR|COMPILE_TIME_ERROR|NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE|lib/html/dart2js/html_dart2js.dart|16895|18|7|The non-nullable local variable 'watchId' must be assigned before it can be used.
-ERROR|COMPILE_TIME_ERROR|NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE|lib/html/dart2js/html_dart2js.dart|16897|13|10|The non-nullable local variable 'controller' must be assigned before it can be used.
-ERROR|COMPILE_TIME_ERROR|NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE|lib/html/dart2js/html_dart2js.dart|16899|13|10|The non-nullable local variable 'controller' must be assigned before it can be used.
-ERROR|COMPILE_TIME_ERROR|NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE|lib/html/dart2js/html_dart2js.dart|16903|18|7|The non-nullable local variable 'watchId' must be assigned before it can be used.
-ERROR|COMPILE_TIME_ERROR|NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE|lib/html/dart2js/html_dart2js.dart|16904|23|7|The non-nullable local variable 'watchId' must be assigned before it can be used.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|115|3|11|Non-nullable instance field 'nonce' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|Non-nullable instance field '_defaultSanitizer' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|Non-nullable instance field '_defaultValidator' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|Non-nullable instance field '_parseDocument' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|Non-nullable instance field '_parseRange' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|Non-nullable instance field 'innerText' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|34280|3|18|Non-nullable instance field '_returnValue' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|5283|3|23|Non-nullable instance field '_elementCssStyleDeclarationSetIterable' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19472|8|9|Non-nullable instance field 'autofocus' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19474|8|8|Non-nullable instance field 'disabled' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19476|8|11|Non-nullable instance field 'incremental' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19478|8|13|Non-nullable instance field 'indeterminate' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19482|10|4|Non-nullable instance field 'name' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19488|10|5|Non-nullable instance field 'value' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19508|10|12|Non-nullable instance field 'autocomplete' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19510|7|9|Non-nullable instance field 'maxLength' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19512|10|7|Non-nullable instance field 'pattern' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19514|10|11|Non-nullable instance field 'placeholder' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19516|8|8|Non-nullable instance field 'readOnly' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19518|8|8|Non-nullable instance field 'required' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19520|7|4|Non-nullable instance field 'size' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19524|10|18|Non-nullable instance field 'selectionDirection' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19526|7|12|Non-nullable instance field 'selectionEnd' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19528|7|14|Non-nullable instance field 'selectionStart' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19661|10|3|Non-nullable instance field 'max' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19663|10|3|Non-nullable instance field 'min' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19665|10|4|Non-nullable instance field 'step' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD|lib/html/dart2js/html_dart2js.dart|19667|7|13|Non-nullable instance field 'valueAsNumber' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_VARIABLE|lib/html/dart2js/html_dart2js.dart|13532|23|14|The non-nullable variable '_parseDocument' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_VARIABLE|lib/html/dart2js/html_dart2js.dart|13533|16|11|The non-nullable variable '_parseRange' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_VARIABLE|lib/html/dart2js/html_dart2js.dart|13534|31|17|The non-nullable variable '_defaultValidator' must be initialized.
-ERROR|COMPILE_TIME_ERROR|NOT_INITIALIZED_NON_NULLABLE_VARIABLE|lib/html/dart2js/html_dart2js.dart|13535|35|17|The non-nullable variable '_defaultSanitizer' must be initialized.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|11762|22|27|A value of type 'Element?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|11768|22|26|A value of type 'Element?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|12817|25|10|A value of type 'String?' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|12991|19|10|A value of type 'String?' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|13383|14|11|A value of type 'Element?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|13590|29|36|A value of type 'Element' can't be assigned to a variable of type 'BodyElement'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|15453|29|18|A value of type 'EventTarget?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|15454|22|11|A value of type 'EventTarget?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|15458|16|13|A value of type 'Element?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|19154|22|31|A value of type 'Element' can't be assigned to a variable of type 'InputElement'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|20087|23|38|A value of type 'Event' can't be assigned to a variable of type 'KeyboardEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|21690|26|37|A value of type 'Event' can't be assigned to a variable of type 'MessageEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|22361|24|35|A value of type 'Event' can't be assigned to a variable of type 'MouseEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|22543|24|11|A value of type 'EventTarget?' can't be assigned to a variable of type 'Element'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23270|18|16|A value of type 'Node?' can't be assigned to a variable of type 'Node'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23272|24|14|A value of type 'Node?' can't be assigned to a variable of type 'Node'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23367|27|15|A value of type 'Node?' can't be assigned to a variable of type 'Node'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23377|27|15|A value of type 'Node?' can't be assigned to a variable of type 'Node'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23419|20|9|A value of type 'String?' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23863|20|4|A value of type 'Null' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23864|20|4|A value of type 'Null' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23865|20|4|A value of type 'Null' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23866|19|4|A value of type 'Null' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|23867|20|4|A value of type 'Null' can't be assigned to a variable of type 'String'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|29470|22|37|A value of type 'Event' can't be assigned to a variable of type 'StorageEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|30311|19|34|A value of type 'Event' can't be assigned to a variable of type 'TextEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|31182|17|32|A value of type 'Event' can't be assigned to a variable of type 'UIEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|3239|26|41|A value of type 'Event' can't be assigned to a variable of type 'CompositionEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/html/dart2js/html_dart2js.dart|8837|27|36|A value of type 'Event' can't be assigned to a variable of type 'CustomEvent'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/svg/dart2js/svg_dart2js.dart|3138|31|16|A value of type 'Node' can't be assigned to a variable of type 'SvgElement'.
-ERROR|STATIC_TYPE_WARNING|INVALID_ASSIGNMENT|lib/svg/dart2js/svg_dart2js.dart|3145|31|16|A value of type 'Node' can't be assigned to a variable of type 'SvgElement'.
-ERROR|STATIC_TYPE_WARNING|NON_BOOL_CONDITION|lib/html/dart2js/html_dart2js.dart|15464|7|36|Conditions must have a static type of 'bool'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE_FROM_CLOSURE|lib/html/dart2js/html_dart2js.dart|30825|26|4|The return type 'Null' isn't a 'TouchList', as required by the closure's context.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE_FROM_CLOSURE|lib/svg/dart2js/svg_dart2js.dart|3557|12|2|The return type 'SvgElement' isn't a 'SvgSvgElement', as required by the closure's context.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|10582|12|9|A value of type 'Object?' can't be returned from function 'name' because it has a return type of 'String'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|11395|12|4|A value of type 'Null' can't be returned from method 'intersection' because it has a return type of 'Rectangle<num>'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|11643|12|21|A value of type 'Node' can't be returned from method '[]' because it has a return type of 'Element'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|12174|31|16|A value of type 'Node' can't be returned from method '[]' because it has a return type of 'E'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|12192|18|15|A value of type 'Node' can't be returned from function 'first' because it has a return type of 'E'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|12194|17|14|A value of type 'Node' can't be returned from function 'last' because it has a return type of 'E'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|12196|19|16|A value of type 'Node' can't be returned from function 'single' because it has a return type of 'E'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|12608|12|48|A value of type 'Node' can't be returned from function 'html' because it has a return type of 'Element'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|13180|30|13|A value of type 'String?' can't be returned from function 'namespaceUri' because it has a return type of 'String'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|16127|12|3|A value of type 'Object?' can't be returned from function 'result' because it has a return type of 'Object'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|17681|27|5|A value of type 'HeadElement?' can't be returned from function 'head' because it has a return type of 'HeadElement'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|17685|40|23|A value of type 'String?' can't be returned from function 'preferredStylesheetSet' because it has a return type of 'String'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|17689|39|22|A value of type 'String?' can't be returned from function 'selectedStylesheetSet' because it has a return type of 'String'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|2225|12|7|A value of type 'Object' can't be returned from method 'getContext3d' because it has a return type of 'RenderingContext'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|29386|12|9|A value of type 'String?' can't be returned from method 'putIfAbsent' because it has a return type of 'String'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|29828|12|5|A value of type 'Element' can't be returned from method '_createTBody' because it has a return type of 'TableSectionElement'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|29916|45|18|A value of type 'HtmlElement' can't be returned from method 'insertCell' because it has a return type of 'TableCellElement'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|29979|43|17|A value of type 'HtmlElement' can't be returned from method 'insertRow' because it has a return type of 'TableRowElement'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/html/dart2js/html_dart2js.dart|35143|12|4|A value of type 'Null' can't be returned from method 'intersection' because it has a return type of 'Rectangle<num>'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/svg/dart2js/svg_dart2js.dart|3107|7|59|A value of type 'Element' can't be returned from function 'tag' because it has a return type of 'SvgElement'.
-ERROR|STATIC_TYPE_WARNING|RETURN_OF_INVALID_TYPE|lib/web_audio/dart2js/web_audio_dart2js.dart|249|14|59|A value of type 'Future<dynamic>' can't be returned from method 'decodeAudioData' because it has a return type of 'Future<AudioBuffer>'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|13066|60|4|The argument type 'Null' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|13498|40|24|The argument type 'Element?' can't be assigned to the parameter type 'Element'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|16933|48|13|The argument type 'void Function(PositionError)?' can't be assigned to the parameter type 'void Function(PositionError)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|16960|50|13|The argument type 'void Function(PositionError)?' can't be assigned to the parameter type 'void Function(PositionError)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|18015|13|32|The argument type 'bool?' can't be assigned to the parameter type 'bool'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|18015|47|22|The argument type 'void Function(ProgressEvent)?' can't be assigned to the parameter type 'void Function(ProgressEvent)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|18254|30|8|The argument type 'Object?' can't be assigned to the parameter type 'FutureOr<String>?'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|22537|24|1|The argument type 'Object?' can't be assigned to the parameter type 'num'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|22537|27|1|The argument type 'Object?' can't be assigned to the parameter type 'num'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|23208|24|26|The argument type 'Node?' can't be assigned to the parameter type 'Node'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|23400|27|26|The argument type 'Node?' can't be assigned to the parameter type 'Node'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|23411|20|10|The argument type 'Node?' can't be assigned to the parameter type 'Node'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|23728|59|4|The argument type 'Null' can't be assigned to the parameter type 'NodeFilter'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|26570|37|7|The argument type 'num' can't be assigned to the parameter type 'int'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|26570|46|7|The argument type 'num' can't be assigned to the parameter type 'int'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|29376|45|3|The argument type 'Object?' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|29391|17|3|The argument type 'Object?' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|29402|14|9|The argument type 'String?' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|31084|57|4|The argument type 'Null' can't be assigned to the parameter type 'NodeFilter'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|34222|13|3|The argument type 'num' can't be assigned to the parameter type 'int'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|34222|18|3|The argument type 'num' can't be assigned to the parameter type 'int'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|36378|34|14|The argument type 'String?' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|36426|48|14|The argument type 'String?' can't be assigned to the parameter type 'String'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|37894|45|7|The argument type 'dynamic Function(Event)?' can't be assigned to the parameter type 'dynamic Function(Event)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|37900|48|7|The argument type 'dynamic Function(Event)?' can't be assigned to the parameter type 'dynamic Function(Event)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|9520|41|15|The argument type 'void Function(Entry)?' can't be assigned to the parameter type 'void Function(Entry)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|9564|36|15|The argument type 'void Function(Entry)?' can't be assigned to the parameter type 'void Function(Entry)'.
-ERROR|STATIC_WARNING|ARGUMENT_TYPE_NOT_ASSIGNABLE|lib/svg/dart2js/svg_dart2js.dart|3172|26|15|The argument type 'Node?' can't be assigned to the parameter type 'Node'.
-ERROR|STATIC_WARNING|FIELD_INITIALIZER_NOT_ASSIGNABLE|lib/html/dart2js/html_dart2js.dart|11629|26|17|The initializer type 'List<Node>' can't be assigned to the field type 'HtmlCollection'.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|12627|3|7|All final variables must be initialized, but '_firstElementChild', '_lastElementChild', and 8 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|15934|3|15|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|18791|3|13|All final variables must be initialized, but '_get_contentWindow' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|19173|3|12|All final variables must be initialized, but '_get_valueAsDate', 'form', and 1 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|1919|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20284|3|12|All final variables must be initialized, but 'control' and 'form' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20317|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20367|3|11|All final variables must be initialized, but 'import' and 'sheet' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|20686|3|12|All final variables must be initialized, but 'error' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|23341|3|4|All final variables must be initialized, but 'childNodes', 'firstChild', and 7 others are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|24089|3|13|All final variables must be initialized, but '_get_contentWindow' and 'form' are not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|24597|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|24668|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|27859|3|13|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|29564|3|12|All final variables must be initialized, but 'sheet' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/html/dart2js/html_dart2js.dart|30135|3|15|All final variables must be initialized, but 'form' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/svg/dart2js/svg_dart2js.dart|3043|3|12|All final variables must be initialized, but 'sheet' is not.
-ERROR|STATIC_WARNING|FINAL_NOT_INITIALIZED_CONSTRUCTOR|lib/svg/dart2js/svg_dart2js.dart|3392|3|10|All final variables must be initialized, but 'ownerSvgElement' and 'viewportElement' are not.
-ERROR|STATIC_WARNING|GETTER_NOT_SUBTYPE_SETTER_TYPES|lib/html/dart2js/html_dart2js.dart|33119|19|6|The return type of getter 'opener' is 'WindowBase?' which isn't a subtype of the type 'Window' of its setter 'opener'.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/html/dart2js/html_dart2js.dart|13342|9|15|The expression is nullable and must be null-checked before it can be used.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/html/dart2js/html_dart2js.dart|13352|9|15|The expression is nullable and must be null-checked before it can be used.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/html/dart2js/html_dart2js.dart|23368|7|10|The expression is nullable and must be null-checked before it can be used.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/html/dart2js/html_dart2js.dart|34260|9|24|The expression is nullable and must be null-checked before it can be used.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/html/dart2js/html_dart2js.dart|34274|9|24|The expression is nullable and must be null-checked before it can be used.
-ERROR|STATIC_WARNING|UNCHECKED_USE_OF_NULLABLE_VALUE|lib/svg/dart2js/svg_dart2js.dart|3116|26|14|The expression is nullable and must be null-checked before it can be used.
-WARNING|STATIC_WARNING|UNNECESSARY_NON_NULL_ASSERTION|lib/html/dart2js/html_dart2js.dart|37453|33|1|The '!' will have no effect because the target expression cannot be 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 e6bd782..3668b87 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -46,6 +46,8 @@
         findTypeArgumentIssues,
         getGenericTypeName;
 
+import 'package:kernel/src/legacy_erasure.dart';
+
 import 'package:kernel/text/text_serialization_verifier.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
@@ -1166,6 +1168,11 @@
       declaredType = declaredSubstitution.substituteType(declaredType);
     }
 
+    if (!declaredMember.isNonNullableByDefault &&
+        interfaceMember.isNonNullableByDefault) {
+      interfaceType = legacyErasure(types.hierarchy.coreTypes, interfaceType);
+    }
+
     bool inParameter = declaredParameter != null || asIfDeclaredParameter;
     DartType subtype = inParameter ? interfaceType : declaredType;
     DartType supertype = inParameter ? declaredType : interfaceType;
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index c6b8eb2..8ebde46 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -119,11 +119,12 @@
       Constructor referenceFrom,
       [String nativeMethodName])
       : _constructor = new Constructor(null,
-            fileUri: compilationUnit?.fileUri,
+            fileUri: compilationUnit.fileUri,
             reference: referenceFrom?.reference)
           ..startFileOffset = startCharOffset
           ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset,
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
 
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 6dbdd64..42b871e 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -12,10 +12,7 @@
 
 import '../constant_context.dart' show ConstantContext;
 
-import '../fasta_codes.dart'
-    show
-        messageInternalProblemAlreadyInitialized,
-        templateCantInferTypeDueToCircularity;
+import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
 
 import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/class_hierarchy_builder.dart' show ClassMember;
@@ -35,11 +32,6 @@
 import '../type_inference/type_inference_engine.dart'
     show IncludesTypeParametersNonCovariantly;
 
-import '../type_inference/type_inferrer.dart'
-    show ExpressionInferenceResult, TypeInferrerImpl;
-
-import '../type_inference/type_schema.dart' show UnknownType;
-
 import 'class_builder.dart';
 import 'extension_builder.dart';
 import 'library_builder.dart';
@@ -176,8 +168,8 @@
       assert(lateIsSetReferenceFrom == null);
       assert(getterReferenceFrom == null);
       assert(setterReferenceFrom == null);
-      _fieldEncoding = new RegularFieldEncoding(
-          fileUri, charOffset, charEndOffset, reference);
+      _fieldEncoding = new RegularFieldEncoding(fileUri, charOffset,
+          charEndOffset, reference, library.isNonNullableByDefault);
     }
   }
 
@@ -337,41 +329,9 @@
       // We have already inferred a type.
       return fieldType;
     }
-    ImplicitFieldType type = fieldType;
-    if (type.fieldBuilder != this) {
-      // The implicit type was inherited.
-      return fieldType = type.inferType();
-    }
-    if (type.isStarted) {
-      library.addProblem(
-          templateCantInferTypeDueToCircularity.withArguments(name),
-          charOffset,
-          name.length,
-          fileUri);
-      return fieldType = const InvalidType();
-    }
-    type.isStarted = true;
-    InterfaceType enclosingClassThisType = field.enclosingClass == null
-        ? null
-        : library.loader.typeInferenceEngine.coreTypes.thisInterfaceType(
-            field.enclosingClass, field.enclosingLibrary.nonNullable);
-    TypeInferrerImpl typeInferrer = library.loader.typeInferenceEngine
-        .createTopLevelTypeInferrer(fileUri, enclosingClassThisType, library,
-            dataForTesting?.inferenceData);
-    BodyBuilder bodyBuilder =
-        library.loader.createBodyBuilderForField(this, typeInferrer);
-    bodyBuilder.constantContext =
-        isConst ? ConstantContext.inferred : ConstantContext.none;
-    Expression initializer =
-        bodyBuilder.parseFieldInitializer(type.initializerToken);
-    type.initializerToken = null;
 
-    ExpressionInferenceResult result = typeInferrer.inferExpression(
-        initializer, const UnknownType(), true,
-        isVoidAllowed: true);
-    DartType inferredType =
-        typeInferrer.inferDeclarationType(result.inferredType);
-
+    ImplicitFieldType implicitFieldType = fieldType;
+    DartType inferredType = implicitFieldType.computeType();
     if (fieldType is ImplicitFieldType) {
       // `fieldType` may have changed if a circularity was detected when
       // [inferredType] was computed.
@@ -379,7 +339,7 @@
         inferredType = legacyErasure(
             library.loader.typeInferenceEngine.coreTypes, inferredType);
       }
-      fieldType = inferredType;
+      fieldType = implicitFieldType.checkInferred(inferredType);
 
       IncludesTypeParametersNonCovariantly needsCheckVisitor;
       if (parent is ClassBuilder) {
@@ -511,11 +471,12 @@
 class RegularFieldEncoding implements FieldEncoding {
   Field _field;
 
-  RegularFieldEncoding(
-      Uri fileUri, int charOffset, int charEndOffset, Field reference) {
+  RegularFieldEncoding(Uri fileUri, int charOffset, int charEndOffset,
+      Field reference, bool isNonNullableByDefault) {
     _field = new Field(null, fileUri: fileUri, reference: reference?.reference)
       ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset;
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = isNonNullableByDefault;
   }
 
   @override
@@ -645,15 +606,18 @@
     _field =
         new Field(null, fileUri: fileUri, reference: referenceFrom?.reference)
           ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset;
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = true;
     _lateIsSetField = new Field(null,
         fileUri: fileUri, reference: lateIsSetReferenceFrom?.reference)
       ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset;
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = true;
     _lateGetter = new Procedure(
         null, ProcedureKind.Getter, new FunctionNode(null),
         fileUri: fileUri, reference: getterReferenceFrom?.reference)
-      ..fileOffset = charOffset;
+      ..fileOffset = charOffset
+      ..isNonNullableByDefault = true;
     _lateSetter = _createSetter(name, fileUri, charOffset, setterReferenceFrom);
   }
 
@@ -751,7 +715,8 @@
             positionalParameters: [parameter], returnType: const VoidType()),
         fileUri: fileUri,
         reference: referenceFrom?.reference)
-      ..fileOffset = charOffset;
+      ..fileOffset = charOffset
+      ..isNonNullableByDefault = true;
   }
 
   Statement _createSetterBody(
@@ -762,17 +727,20 @@
 
   @override
   void set type(DartType value) {
-    assert(_type == null, "Type has already been computed for field $name.");
+    assert(_type == null || _type is ImplicitFieldType,
+        "Type has already been computed for field $name.");
     _type = value;
-    _field.type = value.withNullability(Nullability.nullable);
-    _lateGetter.function.returnType = value;
-    if (_lateSetter != null) {
-      _lateSetter.function.positionalParameters.single.type = value;
-    }
-    if (!_type.isPotentiallyNullable) {
-      // We only need the is-set field if the field is potentially nullable.
-      //  Otherwise we use `null` to signal that the field is uninitialized.
-      _lateIsSetField = null;
+    if (value is! ImplicitFieldType) {
+      _field.type = value.withNullability(Nullability.nullable);
+      _lateGetter.function.returnType = value;
+      if (_lateSetter != null) {
+        _lateSetter.function.positionalParameters.single.type = value;
+      }
+      if (!_type.isPotentiallyNullable) {
+        // We only need the is-set field if the field is potentially nullable.
+        //  Otherwise we use `null` to signal that the field is uninitialized.
+        _lateIsSetField = null;
+      }
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index c1191f5..4670d12 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -109,11 +109,12 @@
       this._tearOffReferenceFrom,
       [String nativeMethodName])
       : _procedure = new Procedure(null, kind, null,
-            fileUri: compilationUnit?.fileUri,
+            fileUri: compilationUnit.fileUri,
             reference: referenceFrom?.reference)
           ..startFileOffset = startCharOffset
           ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset,
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
 
@@ -453,7 +454,8 @@
       _extensionTearOff ??= new Procedure(null, ProcedureKind.Method, null,
           isStatic: true,
           isExtensionMember: true,
-          reference: _tearOffReferenceFrom?.reference);
+          reference: _tearOffReferenceFrom?.reference)
+        ..isNonNullableByDefault = library.isNonNullableByDefault;
     }
     return _extensionTearOff;
   }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 2afe2b3..a51997c 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -115,6 +115,9 @@
   /// superclass.
   bool get isMixinApplication => cls.isMixinApplication;
 
+  @override
+  bool get hasConstConstructor => cls.hasConstConstructor;
+
   TypeBuilder get mixedInType {
     return computeTypeBuilder(library, cls.mixedInType);
   }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 562615e..818480a 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -32,6 +32,7 @@
 import '../builder/class_builder.dart';
 import '../builder/dynamic_type_builder.dart';
 import '../builder/extension_builder.dart';
+import '../builder/modifier_builder.dart';
 import '../builder/never_type_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
@@ -89,7 +90,7 @@
   /// [../kernel/kernel_library_builder.dart].
   Map<String, String> unserializableExports;
 
-  // TODO(jensj): These 4 booleans could potentially be merged into a single
+  // TODO(jensj): These 5 booleans could potentially be merged into a single
   // state field.
   bool isReadyToBuild = false;
   bool isReadyToFinalizeExports = false;
@@ -294,53 +295,75 @@
       exportScopeBuilder.addMember(name, declaration);
     });
 
+    Map<Reference, Builder> sourceBuildersMap =
+        loader.currentSourceLoader?.buildersCreatedWithReferences;
     for (Reference reference in library.additionalExports) {
       NamedNode node = reference.node;
-      Uri libraryUri;
-      String name;
-      bool isSetter = false;
-      if (node is Class) {
-        libraryUri = node.enclosingLibrary.importUri;
-        name = node.name;
-      } else if (node is Procedure) {
-        libraryUri = node.enclosingLibrary.importUri;
-        name = node.name.name;
-        isSetter = node.isSetter;
-      } else if (node is Member) {
-        libraryUri = node.enclosingLibrary.importUri;
-        name = node.name.name;
-      } else if (node is Typedef) {
-        libraryUri = node.enclosingLibrary.importUri;
-        name = node.name;
-      } else if (node is Extension) {
-        libraryUri = node.enclosingLibrary.importUri;
-        name = node.name;
-      } else {
-        unhandled("${node.runtimeType}", "finalizeExports", -1, fileUri);
-      }
-      DillLibraryBuilder library = loader.builders[libraryUri];
-      if (library == null) {
-        internalProblem(
-            templateUnspecified.withArguments("No builder for '$libraryUri'."),
-            -1,
-            fileUri);
-      }
       Builder declaration;
-      if (isSetter) {
-        declaration = library.exportScope.lookupLocalMember(name, setter: true);
-        exportScopeBuilder.addSetter(name, declaration);
+      String name;
+      if (sourceBuildersMap?.containsKey(reference) == true) {
+        declaration = sourceBuildersMap[reference];
+        assert(declaration != null);
+        if (declaration is ModifierBuilder) {
+          name = declaration.name;
+        } else {
+          throw new StateError(
+              "Unexpected: $declaration (${declaration.runtimeType}");
+        }
+
+        if (declaration.isSetter) {
+          exportScopeBuilder.addSetter(name, declaration);
+        } else {
+          exportScopeBuilder.addMember(name, declaration);
+        }
       } else {
-        declaration =
-            library.exportScope.lookupLocalMember(name, setter: false);
-        exportScopeBuilder.addMember(name, declaration);
+        Uri libraryUri;
+        bool isSetter = false;
+        if (node is Class) {
+          libraryUri = node.enclosingLibrary.importUri;
+          name = node.name;
+        } else if (node is Procedure) {
+          libraryUri = node.enclosingLibrary.importUri;
+          name = node.name.name;
+          isSetter = node.isSetter;
+        } else if (node is Member) {
+          libraryUri = node.enclosingLibrary.importUri;
+          name = node.name.name;
+        } else if (node is Typedef) {
+          libraryUri = node.enclosingLibrary.importUri;
+          name = node.name;
+        } else if (node is Extension) {
+          libraryUri = node.enclosingLibrary.importUri;
+          name = node.name;
+        } else {
+          unhandled("${node.runtimeType}", "finalizeExports", -1, fileUri);
+        }
+        LibraryBuilder library = loader.builders[libraryUri];
+        if (library == null) {
+          internalProblem(
+              templateUnspecified
+                  .withArguments("No builder for '$libraryUri'."),
+              -1,
+              fileUri);
+        }
+        if (isSetter) {
+          declaration =
+              library.exportScope.lookupLocalMember(name, setter: true);
+          exportScopeBuilder.addSetter(name, declaration);
+        } else {
+          declaration =
+              library.exportScope.lookupLocalMember(name, setter: false);
+          exportScopeBuilder.addMember(name, declaration);
+        }
+        if (declaration == null) {
+          internalProblem(
+              templateUnspecified.withArguments(
+                  "Exported element '$name' not found in '$libraryUri'."),
+              -1,
+              fileUri);
+        }
       }
-      if (declaration == null) {
-        internalProblem(
-            templateUnspecified.withArguments(
-                "Exported element '$name' not found in '$libraryUri'."),
-            -1,
-            fileUri);
-      }
+
       assert(
           (declaration is ClassBuilder && node == declaration.cls) ||
               (declaration is TypeAliasBuilder &&
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index 3d91dbd..0ce2b66 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -21,6 +21,8 @@
 
 import '../problems.dart' show unhandled;
 
+import '../source/source_loader.dart' show SourceLoader;
+
 import '../target_implementation.dart' show TargetImplementation;
 
 import 'dill_library_builder.dart' show DillLibraryBuilder;
@@ -28,6 +30,8 @@
 import 'dill_target.dart' show DillTarget;
 
 class DillLoader extends Loader {
+  SourceLoader currentSourceLoader;
+
   DillLoader(TargetImplementation target) : super(target);
 
   Template<SummaryTemplate> get outlineSummaryTemplate =>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 5edb792..8085b94 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -2048,6 +2048,42 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(
+            String name, DartType _type, bool isNonNullableByDefault)>
+    templateNonNullableInNullAware = const Template<
+            Message Function(
+                String name, DartType _type, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""Operand of null-aware operation '#name' has type '#type' which excludes null.""",
+        withArguments: _withArgumentsNonNullableInNullAware);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            String name, DartType _type, bool isNonNullableByDefault)>
+    codeNonNullableInNullAware = const Code<
+            Message Function(
+                String name, DartType _type, bool isNonNullableByDefault)>(
+        "NonNullableInNullAware", templateNonNullableInNullAware,
+        severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonNullableInNullAware(
+    String name, DartType _type, bool isNonNullableByDefault) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeNonNullableInNullAware,
+      message:
+          """Operand of null-aware operation '${name}' has type '${type}' which excludes null.""" +
+              labeler.originMessages,
+      arguments: {'name': name, 'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
     templateNullableExpressionCallError = const Template<
             Message Function(DartType _type, bool isNonNullableByDefault)>(
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 8599429..3711466 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -129,7 +129,7 @@
   List<LibraryBuilder> platformBuilders;
   Map<Uri, LibraryBuilder> userBuilders;
   final Uri initializeFromDillUri;
-  final Component componentToInitializeFrom;
+  Component componentToInitializeFrom;
   bool initializedFromDill = false;
   bool initializedIncrementalSerializer = false;
   Uri previousPackagesUri;
@@ -213,13 +213,14 @@
       KernelTarget userCodeOld = userCode;
       setupNewUserCode(c, uriTranslator, hierarchy, reusedLibraries,
           experimentalInvalidation, entryPoints.first);
-      Map<LibraryBuilder, List<SourceLibraryBuilder>> rebuildBodiesMap =
+      Map<LibraryBuilder, List<LibraryBuilder>> rebuildBodiesMap =
           experimentalInvalidationCreateRebuildBodiesBuilders(
               experimentalInvalidation, uriTranslator);
       entryPoints = userCode.setEntryPoints(entryPoints);
       await userCode.loader.buildOutlines();
       experimentalInvalidationPatchUpScopes(
           experimentalInvalidation, rebuildBodiesMap);
+      rebuildBodiesMap = null;
 
       // Checkpoint: Build the actual outline.
       // Note that the [Component] is not the "full" component.
@@ -277,10 +278,14 @@
       if (componentWithDill == null) {
         userCode.loader.builders.clear();
         userCode = userCodeOld;
+        dillLoadedData.loader.currentSourceLoader = userCode.loader;
       } else {
-        previousSourceBuilders = await convertSourceLibraryBuildersToDill();
+        previousSourceBuilders =
+            await convertSourceLibraryBuildersToDill(experimentalInvalidation);
       }
 
+      experimentalInvalidation = null;
+
       // Output result.
       Procedure mainMethod = componentWithDill == null
           ? data.userLoadedUriMain
@@ -295,11 +300,17 @@
   /// Convert every SourceLibraryBuilder to a DillLibraryBuilder.
   /// As we always do this, this will only be the new ones.
   ///
+  /// If doing experimental invalidation that means that some of the old dill
+  /// library builders might have links (via export scopes) to the
+  /// source builders and they will thus be patched up here too.
+  ///
   /// Returns the set of Libraries that now has new (dill) builders.
-  Future<Set<Library>> convertSourceLibraryBuildersToDill() async {
+  Future<Set<Library>> convertSourceLibraryBuildersToDill(
+      ExperimentalInvalidation experimentalInvalidation) async {
     bool changed = false;
     Set<Library> newDillLibraryBuilders = new Set<Library>();
     userBuilders ??= <Uri, LibraryBuilder>{};
+    Map<LibraryBuilder, List<LibraryBuilder>> convertedLibraries;
     for (MapEntry<Uri, LibraryBuilder> entry
         in userCode.loader.builders.entries) {
       if (entry.value is SourceLibraryBuilder) {
@@ -309,14 +320,53 @@
         userCode.loader.builders[entry.key] = dillBuilder;
         userBuilders[entry.key] = dillBuilder;
         newDillLibraryBuilders.add(builder.library);
+        if (userCode.loader.first == builder) {
+          userCode.loader.first = dillBuilder;
+        }
         changed = true;
+        if (experimentalInvalidation != null) {
+          convertedLibraries ??=
+              new Map<LibraryBuilder, List<LibraryBuilder>>();
+          convertedLibraries[builder] = [dillBuilder];
+        }
       }
     }
     if (changed) {
       // We suppress finalization errors because they have already been
       // reported.
       await dillLoadedData.buildOutlines(suppressFinalizationErrors: true);
+
+      if (experimentalInvalidation != null) {
+        /// If doing experimental invalidation that means that some of the old
+        /// dill library builders might have links (via export scopes) to the
+        /// source builders. Patch that up.
+
+        // Maps from old library builder to map of new content.
+        Map<LibraryBuilder, Map<String, Builder>> replacementMap = {};
+
+        // Maps from old library builder to map of new content.
+        Map<LibraryBuilder, Map<String, Builder>> replacementSettersMap = {};
+
+        experimentalInvalidationFillReplacementMaps(
+            convertedLibraries, replacementMap, replacementSettersMap);
+
+        for (LibraryBuilder builder
+            in experimentalInvalidation.originalNotReusedLibraries) {
+          DillLibraryBuilder dillBuilder = builder;
+          if (dillBuilder.isBuilt) {
+            dillBuilder.exportScope
+                .patchUpScope(replacementMap, replacementSettersMap);
+          }
+        }
+        replacementMap = null;
+        replacementSettersMap = null;
+      }
     }
+    userCode.loader.buildersCreatedWithReferences.clear();
+    userCode.loader.builderHierarchy.nodes.clear();
+    userCode.loader.referenceFromIndex = null;
+    convertedLibraries = null;
+    experimentalInvalidation = null;
     if (userBuilders.isEmpty) userBuilders = null;
     return newDillLibraryBuilders;
   }
@@ -415,17 +465,17 @@
   /// Fill in the replacement maps that describe the replacements that need to
   /// happen because of experimental invalidation.
   void experimentalInvalidationFillReplacementMaps(
-      Map<LibraryBuilder, List<SourceLibraryBuilder>> rebuildBodiesMap,
+      Map<LibraryBuilder, List<LibraryBuilder>> rebuildBodiesMap,
       Map<LibraryBuilder, Map<String, Builder>> replacementMap,
       Map<LibraryBuilder, Map<String, Builder>> replacementSettersMap) {
-    for (MapEntry<LibraryBuilder, List<SourceLibraryBuilder>> entry
+    for (MapEntry<LibraryBuilder, List<LibraryBuilder>> entry
         in rebuildBodiesMap.entries) {
       Map<String, Builder> childReplacementMap = {};
       Map<String, Builder> childReplacementSettersMap = {};
-      List<SourceLibraryBuilder> builders = rebuildBodiesMap[entry.key];
+      List<LibraryBuilder> builders = rebuildBodiesMap[entry.key];
       replacementMap[entry.key] = childReplacementMap;
       replacementSettersMap[entry.key] = childReplacementSettersMap;
-      for (SourceLibraryBuilder builder in builders) {
+      for (LibraryBuilder builder in builders) {
         NameIterator iterator = builder.nameIterator;
         while (iterator.moveNext()) {
           Builder childBuilder = iterator.current;
@@ -450,22 +500,22 @@
   /// When doing experimental invalidation, we have some builders that needs to
   /// be rebuild special, namely they have to be [userCode.loader.read] with
   /// references from the original [Library] for things to work.
-  Map<LibraryBuilder, List<SourceLibraryBuilder>>
+  Map<LibraryBuilder, List<LibraryBuilder>>
       experimentalInvalidationCreateRebuildBodiesBuilders(
           ExperimentalInvalidation experimentalInvalidation,
           UriTranslator uriTranslator) {
     // Any builder(s) in [rebuildBodies] should be semi-reused: Create source
     // builders based on the underlying libraries.
     // Maps from old library builder to list of new library builder(s).
-    Map<LibraryBuilder, List<SourceLibraryBuilder>> rebuildBodiesMap =
-        new Map<LibraryBuilder, List<SourceLibraryBuilder>>.identity();
+    Map<LibraryBuilder, List<LibraryBuilder>> rebuildBodiesMap =
+        new Map<LibraryBuilder, List<LibraryBuilder>>.identity();
     if (experimentalInvalidation != null) {
       for (LibraryBuilder library in experimentalInvalidation.rebuildBodies) {
         LibraryBuilder newBuilder = userCode.loader.read(library.importUri, -1,
             accessor: userCode.loader.first,
             fileUri: library.fileUri,
             referencesFrom: library.library);
-        List<SourceLibraryBuilder> builders = [newBuilder];
+        List<LibraryBuilder> builders = [newBuilder];
         rebuildBodiesMap[library] = builders;
         for (LibraryPart part in library.library.parts) {
           // We need to pass the reference to make any class, procedure etc
@@ -492,7 +542,7 @@
   /// didn't do anything special.
   void experimentalInvalidationPatchUpScopes(
       ExperimentalInvalidation experimentalInvalidation,
-      Map<LibraryBuilder, List<SourceLibraryBuilder>> rebuildBodiesMap) {
+      Map<LibraryBuilder, List<LibraryBuilder>> rebuildBodiesMap) {
     if (experimentalInvalidation != null) {
       // Maps from old library builder to map of new content.
       Map<LibraryBuilder, Map<String, Builder>> replacementMap = {};
@@ -557,8 +607,16 @@
               }
             }
           }
+        } else if (builder is DillLibraryBuilder) {
+          DillLibraryBuilder dillBuilder = builder;
+          // There's only something to patch up if it was build already.
+          if (dillBuilder.isBuilt) {
+            dillBuilder.exportScope
+                .patchUpScope(replacementMap, replacementSettersMap);
+          }
         } else {
-          throw "Currently unsupported";
+          throw new StateError(
+              "Unexpected builder: $builder (${builder.runtimeType})");
         }
       }
     }
@@ -581,6 +639,7 @@
         dillLoadedData,
         uriTranslator);
     userCode.loader.hierarchy = hierarchy;
+    dillLoadedData.loader.currentSourceLoader = userCode.loader;
 
     // Re-use the libraries we've deemed re-usable.
     for (LibraryBuilder library in reusedLibraries) {
@@ -754,6 +813,10 @@
     // rebuild the bodies.
     for (int i = 0; i < reusedResult.directlyInvalidated.length; i++) {
       LibraryBuilder builder = reusedResult.directlyInvalidated[i];
+      if (builder.library.problemsAsJson != null) {
+        assert(builder.library.problemsAsJson.isNotEmpty);
+        return null;
+      }
       Iterator<Builder> iterator = builder.iterator;
       while (iterator.moveNext()) {
         Builder childBuilder = iterator.current;
@@ -866,6 +929,7 @@
         // If initializing from a component it has to include the sdk,
         // so we explicitly don't load it here.
         initializeFromComponent(uriTranslator, c, data);
+        componentToInitializeFrom = null;
       } else {
         List<int> summaryBytes = await c.options.loadSdkSummaryBytes();
         bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
@@ -1518,7 +1582,8 @@
 
       Procedure procedure = new Procedure(
           new Name(syntheticProcedureName), ProcedureKind.Method, parameters,
-          isStatic: isStatic);
+          isStatic: isStatic)
+        ..isNonNullableByDefault = debugLibrary.isNonNullableByDefault;
 
       parameters.body = new ReturnStatement(compiledExpression)
         ..parent = parameters;
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 889090f..88cc4a8 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
@@ -16,6 +16,7 @@
 import 'package:kernel/src/future_or.dart';
 import 'package:kernel/src/legacy_erasure.dart';
 import 'package:kernel/src/nnbd_top_merge.dart';
+import 'package:kernel/src/norm.dart';
 
 import '../../testing/id_testing_utils.dart' show typeToText;
 
@@ -551,8 +552,10 @@
           debug?.log("supertypes: checkValidOverride("
               "${classBuilder.fullNameForErrors}, "
               "${fullName(a)}, ${fullName(b)})");
-          checkValidOverride(a, b);
-          if (a is DelayedMember && !a.isInheritableConflict) {
+          if (a is! DelayedMember) {
+            checkValidOverride(a, b);
+          }
+          if (a is DelayedMember) {
             if (b is DelayedMember) {
               b.addAllDeclarationsTo(a.declarations);
             } else {
@@ -913,6 +916,9 @@
     }
   }
 
+  /// Infers the field type of [a] based on [b]. Returns `true` if the type of
+  /// [a] is known to be a valid override of [b], meaning that no additional
+  /// override checks are needed.
   bool inferFieldTypes(ClassMember a, ClassMember b) {
     debug?.log("Trying to infer field types for ${fullName(a)} "
         "based on ${fullName(b)}");
@@ -972,8 +978,13 @@
       debug?.log("${classBuilder.fullNameForErrors} -> "
           "${bClassBuilder.fullNameForErrors} $bSubstitution");
     }
-    if (bSubstitution != null && inheritedType is! ImplicitFieldType) {
-      inheritedType = bSubstitution.substituteType(inheritedType);
+    if (inheritedType is! ImplicitFieldType) {
+      if (bSubstitution != null) {
+        inheritedType = bSubstitution.substituteType(inheritedType);
+      }
+      if (!a.classBuilder.library.isNonNullableByDefault) {
+        inheritedType = legacyErasure(hierarchy.coreTypes, inheritedType);
+      }
     }
 
     Field aField = a.member;
@@ -983,26 +994,33 @@
     }
     if (declaredType == inheritedType) return true;
 
-    bool result = false;
+    bool isValidOverride = false;
     if (a is FieldBuilder) {
       if (a.parent == classBuilder && a.type == null) {
-        if (a.hadTypesInferred) {
-          reportCantInferFieldType(classBuilder, a);
-          inheritedType = const InvalidType();
+        DartType declaredType = a.fieldType;
+        if (declaredType is ImplicitFieldType) {
+          if (inheritedType is ImplicitFieldType) {
+            declaredType.addOverride(inheritedType);
+          } else {
+            // The concrete type has already been inferred.
+            a.hadTypesInferred = true;
+            a.fieldType = inheritedType;
+            isValidOverride = true;
+          }
+        } else if (a.hadTypesInferred) {
+          if (inheritedType is! ImplicitFieldType) {
+            // A different type has already been inferred.
+            reportCantInferFieldType(classBuilder, a);
+            a.fieldType = const InvalidType();
+          }
         } else {
-          result = true;
+          isValidOverride = true;
           a.hadTypesInferred = true;
-        }
-        if (inheritedType is ImplicitFieldType) {
-          SourceLibraryBuilder library = classBuilder.library;
-          (library.implicitlyTypedFields ??= <FieldBuilder>[]).add(a);
-          a.fieldType = inheritedType.createAlias(a);
-        } else {
           a.fieldType = inheritedType;
         }
       }
     }
-    return result;
+    return isValidOverride;
   }
 
   void copyParameterCovariance(Builder parent, VariableDeclaration aParameter,
@@ -1519,7 +1537,10 @@
           superclass.classNode == type.classNode) {
         // This is a potential conflict.
         if (classBuilder.library.isNonNullableByDefault) {
-          superclass = nnbdTopMerge(hierarchy.coreTypes, superclass, type);
+          superclass = nnbdTopMerge(
+              hierarchy.coreTypes,
+              norm(hierarchy.coreTypes, superclass),
+              norm(hierarchy.coreTypes, type));
           if (superclass == null) {
             // This is a conflict.
             // TODO(johnniwinther): Report errors here instead of through
@@ -1539,7 +1560,10 @@
               interface.classNode == type.classNode) {
             // This is a potential conflict.
             if (classBuilder.library.isNonNullableByDefault) {
-              interface = nnbdTopMerge(hierarchy.coreTypes, interface, type);
+              interface = nnbdTopMerge(
+                  hierarchy.coreTypes,
+                  norm(hierarchy.coreTypes, interface),
+                  norm(hierarchy.coreTypes, type));
               if (interface == null) {
                 // This is a conflict.
                 // TODO(johnniwinther): Report errors here instead of through
@@ -2125,49 +2149,21 @@
       : super.subclassing(typeParameters, currentLibrary);
 
   @override
+  CoreTypes get coreTypes => hierarchy.coreTypes;
+
+  @override
   Class get objectClass => hierarchy.objectClass;
 
   @override
   Class get functionClass => hierarchy.functionClass;
 
   @override
-  Class get futureClass => hierarchy.futureClass;
-
-  @override
   Class get futureOrClass => hierarchy.futureOrClass;
 
   @override
   Class get nullClass => hierarchy.nullClass;
 
   @override
-  InterfaceType get nullType => hierarchy.coreTypes.nullType;
-
-  @override
-  InterfaceType get objectLegacyRawType {
-    return hierarchy.coreTypes.objectLegacyRawType;
-  }
-
-  @override
-  InterfaceType get objectNonNullableRawType {
-    return hierarchy.coreTypes.objectNonNullableRawType;
-  }
-
-  @override
-  InterfaceType objectRawType(Nullability nullability) {
-    return hierarchy.coreTypes.objectRawType(nullability);
-  }
-
-  @override
-  InterfaceType get functionLegacyRawType {
-    return hierarchy.coreTypes.functionLegacyRawType;
-  }
-
-  @override
-  InterfaceType functionRawType(Nullability nullability) {
-    return hierarchy.coreTypes.functionRawType(nullability);
-  }
-
-  @override
   void addLowerBound(
       TypeConstraint constraint, DartType lower, Library clientLibrary) {
     constraint.lower =
@@ -2315,6 +2311,9 @@
                       b.member.enclosingClass,
                       classBuilder.library.library))
               .substituteType(type);
+          if (!a.classBuilder.library.isNonNullableByDefault) {
+            type = legacyErasure(hierarchy.coreTypes, type);
+          }
           if (type != a.fieldType) {
             if (a.hadTypesInferred) {
               if (b.isSetter &&
@@ -2432,7 +2431,7 @@
     return parent == this.classBuilder
         ? this
         : new InheritedImplementationInterfaceConflict(
-            parent, declarations, isSetter, modifyKernel);
+            parent, declarations.toList(), isSetter, modifyKernel);
   }
 
   static ClassMember combined(
@@ -2497,9 +2496,13 @@
       unhandled("${member.runtimeType}", "$member", classBuilder.charOffset,
           classBuilder.fileUri);
     }
-    return Substitution.fromInterfaceType(hierarchy.getKernelTypeAsInstanceOf(
-            thisType, member.enclosingClass, classBuilder.library.library))
-        .substituteType(type);
+    InterfaceType instance = hierarchy.getKernelTypeAsInstanceOf(
+        thisType, member.enclosingClass, classBuilder.library.library);
+    assert(
+        instance != null,
+        "No instance of $thisType as ${member.enclosingClass} found for "
+        "$member.");
+    return Substitution.fromInterfaceType(instance).substituteType(type);
   }
 
   bool isMoreSpecific(ClassHierarchyBuilder hierarchy, DartType a, DartType b) {
@@ -2628,7 +2631,8 @@
   DelayedMember withParent(ClassBuilder parent) {
     return parent == this.classBuilder
         ? this
-        : new InterfaceConflict(parent, declarations, isSetter, modifyKernel);
+        : new InterfaceConflict(
+            parent, declarations.toList(), isSetter, modifyKernel);
   }
 
   static ClassMember combined(ClassBuilder parent, ClassMember a, ClassMember b,
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 6b03c5b..f1c505b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -456,7 +456,9 @@
         reference: referenceFrom?.reference)
       ..startFileOffset = enclosingClass.fileOffset
       ..fileOffset = enclosingClass.fileOffset
-      ..parent = enclosingClass;
+      ..parent = enclosingClass
+      ..isNonNullableByDefault =
+          enclosingClass.enclosingLibrary.isNonNullableByDefault;
   }
 
   /// Returns the [i]th element of [_candidates], finalizing it if necessary.
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index 589e3a7..f0c3651 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -6,22 +6,21 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
-import 'package:kernel/ast.dart'
-    show DartType, DartTypeVisitor, DartTypeVisitor1, Nullability, Visitor;
+import 'package:kernel/ast.dart' hide MapEntry;
 
 import 'package:kernel/src/assumptions.dart';
 import 'package:kernel/src/legacy_erasure.dart';
 
 import '../builder/field_builder.dart';
-
+import '../constant_context.dart';
+import '../fasta_codes.dart';
 import '../problems.dart' show unsupported;
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+import 'body_builder.dart';
 
 abstract class ImplicitFieldType extends DartType {
   SourceFieldBuilder get fieldBuilder;
-  Token get initializerToken;
-  void set initializerToken(Token value);
-  bool get isStarted;
-  void set isStarted(bool value);
 
   ImplicitFieldType._();
 
@@ -54,8 +53,9 @@
         "withNullability", fieldBuilder.charOffset, fieldBuilder.fileUri);
   }
 
-  ImplicitFieldType createAlias(SourceFieldBuilder target) =>
-      new _ImplicitFieldTypeAlias(this, target);
+  void addOverride(ImplicitFieldType other);
+
+  DartType checkInferred(DartType type);
 
   @override
   bool operator ==(Object other) => equals(other, null);
@@ -70,45 +70,109 @@
   int get hashCode => fieldBuilder.hashCode;
 
   DartType inferType();
+
+  DartType computeType();
 }
 
 class _ImplicitFieldTypeRoot extends ImplicitFieldType {
   final SourceFieldBuilder fieldBuilder;
+  List<ImplicitFieldType> _overriddenFields;
   Token initializerToken;
   bool isStarted = false;
 
   _ImplicitFieldTypeRoot(this.fieldBuilder, this.initializerToken) : super._();
 
-  DartType inferType() => fieldBuilder.inferType();
-}
-
-class _ImplicitFieldTypeAlias extends ImplicitFieldType {
-  final ImplicitFieldType _root;
-  final SourceFieldBuilder _targetFieldBuilder;
-
-  _ImplicitFieldTypeAlias(this._root, this._targetFieldBuilder)
-      : assert(_root.fieldBuilder != _targetFieldBuilder),
-        super._();
-
-  SourceFieldBuilder get fieldBuilder => _root.fieldBuilder;
-
-  Token get initializerToken => _root.initializerToken;
-
-  void set initializerToken(Token value) {
-    _root.initializerToken = value;
-  }
-
-  bool get isStarted => _root.isStarted;
-
-  void set isStarted(bool value) {
-    _root.isStarted = value;
-  }
-
   DartType inferType() {
-    DartType type = _root.inferType();
-    if (!_targetFieldBuilder.library.isNonNullableByDefault) {
-      type = legacyErasure(_targetFieldBuilder.library.loader.coreTypes, type);
-    }
-    return _targetFieldBuilder.fieldType = type;
+    return fieldBuilder.inferType();
   }
+
+  DartType computeType() {
+    if (isStarted) {
+      fieldBuilder.library.addProblem(
+          templateCantInferTypeDueToCircularity
+              .withArguments(fieldBuilder.name),
+          fieldBuilder.charOffset,
+          fieldBuilder.name.length,
+          fieldBuilder.fileUri);
+      return fieldBuilder.fieldType = const InvalidType();
+    }
+    isStarted = true;
+    DartType inferredType;
+    if (_overriddenFields != null) {
+      for (ImplicitFieldType overridden in _overriddenFields) {
+        DartType overriddenType = overridden.inferType();
+        if (!fieldBuilder.library.isNonNullableByDefault) {
+          overriddenType = legacyErasure(
+              fieldBuilder.library.loader.coreTypes, overriddenType);
+        }
+        if (inferredType == null) {
+          inferredType = overriddenType;
+        } else if (inferredType != overriddenType) {
+          inferredType = const InvalidType();
+        }
+      }
+      return inferredType;
+    } else if (initializerToken != null) {
+      InterfaceType enclosingClassThisType =
+          fieldBuilder.field.enclosingClass == null
+              ? null
+              : fieldBuilder.library.loader.typeInferenceEngine.coreTypes
+                  .thisInterfaceType(fieldBuilder.field.enclosingClass,
+                      fieldBuilder.field.enclosingLibrary.nonNullable);
+      TypeInferrerImpl typeInferrer = fieldBuilder
+          .library.loader.typeInferenceEngine
+          .createTopLevelTypeInferrer(
+              fieldBuilder.fileUri,
+              enclosingClassThisType,
+              fieldBuilder.library,
+              fieldBuilder.dataForTesting?.inferenceData);
+      BodyBuilder bodyBuilder = fieldBuilder.library.loader
+          .createBodyBuilderForField(fieldBuilder, typeInferrer);
+      bodyBuilder.constantContext = fieldBuilder.isConst
+          ? ConstantContext.inferred
+          : ConstantContext.none;
+      Expression initializer =
+          bodyBuilder.parseFieldInitializer(initializerToken);
+      initializerToken = null;
+
+      ExpressionInferenceResult result = typeInferrer.inferExpression(
+          initializer, const UnknownType(), true,
+          isVoidAllowed: true);
+      inferredType = typeInferrer.inferDeclarationType(result.inferredType);
+    } else {
+      inferredType = const DynamicType();
+    }
+    return inferredType;
+  }
+
+  void addOverride(ImplicitFieldType other) {
+    _overriddenFields ??= [];
+    _overriddenFields.add(other);
+  }
+
+  DartType checkInferred(DartType type) {
+    if (_overriddenFields != null) {
+      for (ImplicitFieldType overridden in _overriddenFields) {
+        DartType overriddenType = overridden.inferType();
+        if (!fieldBuilder.library.isNonNullableByDefault) {
+          overriddenType = legacyErasure(
+              fieldBuilder.library.loader.coreTypes, overriddenType);
+        }
+        if (type != overriddenType) {
+          String name = fieldBuilder.fullNameForErrors;
+          fieldBuilder.classBuilder.addProblem(
+              templateCantInferTypeDueToInconsistentOverrides
+                  .withArguments(name),
+              fieldBuilder.charOffset,
+              name.length,
+              wasHandled: true);
+          return const InvalidType();
+        }
+      }
+    }
+    return type;
+  }
+
+  @override
+  String toString() => 'ImplicitFieldType($fieldBuilder)';
 }
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 a96fb3e..ac0da6b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -352,6 +352,10 @@
     ExpressionInferenceResult result = inferrer.inferExpression(
         node.variable.initializer, typeContext, true,
         isVoidAllowed: false);
+    if (node.isNullAware) {
+      reportNonNullableInNullAwareWarningIfNeeded(
+          result.inferredType, "?..", node.fileOffset);
+    }
 
     node.variable.initializer = result.expression..parent = node.variable;
     node.variable.type = result.inferredType;
@@ -1087,6 +1091,8 @@
     ExpressionInferenceResult lhsResult = inferrer.inferExpression(
         node.left, inferrer.computeNullable(typeContext), true,
         isVoidAllowed: false);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        lhsResult.inferredType, "??", node.left.fileOffset);
 
     Member equalsMember = inferrer
         .findInterfaceMember(
@@ -1280,6 +1286,10 @@
               <DartType>[inferredTypeArgument]),
           inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
+      if (element.isNullAware) {
+        reportNonNullableInNullAwareWarningIfNeeded(
+            spreadResult.inferredType, "...?", element.expression.fileOffset);
+      }
       element.expression = spreadResult.expression..parent = element;
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[element.expression] = spreadType;
@@ -1689,6 +1699,10 @@
       ExpressionInferenceResult spreadResult = inferrer.inferExpression(
           entry.expression, spreadContext, inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
+      if (entry.isNullAware) {
+        reportNonNullableInNullAwareWarningIfNeeded(
+            spreadResult.inferredType, "...?", entry.expression.fileOffset);
+      }
       entry.expression = spreadResult.expression..parent = entry;
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[entry.expression] = spreadType;
@@ -2325,7 +2339,9 @@
         typeContext,
         isExpressionInvocation: true);
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (receiverType is! DynamicType && receiverType.isPotentiallyNullable) {
+      if (receiverType is! DynamicType &&
+          receiverType is! InvalidType &&
+          receiverType.isPotentiallyNullable) {
         if (inferrer.nnbdStrongMode) {
           return new ExpressionInferenceResult(
               invocationResult.inferredType,
@@ -2376,8 +2392,8 @@
     ExpressionInferenceResult operandResult = inferrer.inferExpression(
         node.operand, inferrer.computeNullable(typeContext), true);
     node.operand = operandResult.expression..parent = node;
-    // TODO(johnniwinther): Check that the inferred type is potentially
-    //  nullable.
+    reportNonNullableInNullAwareWarningIfNeeded(
+        operandResult.inferredType, "!", node.operand.fileOffset);
     inferrer.flowAnalysis.nonNullAssert_end(node.operand);
     DartType nonNullableResultType =
         inferrer.computeNonNullable(operandResult.inferredType);
@@ -2388,6 +2404,8 @@
       NullAwareMethodInvocation node, DartType typeContext) {
     Link<NullAwareGuard> nullAwareGuards =
         inferrer.inferSyntheticVariableNullAware(node.variable);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        node.variable.type, "?.", node.variable.fileOffset);
     NullAwareGuard nullAwareGuard =
         inferrer.createNullAwareGuard(node.variable);
     ExpressionInferenceResult invocationResult = inferrer.inferExpression(
@@ -2403,6 +2421,8 @@
       NullAwarePropertyGet node, DartType typeContext) {
     Link<NullAwareGuard> nullAwareGuards =
         inferrer.inferSyntheticVariableNullAware(node.variable);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        node.variable.type, "?.", node.variable.fileOffset);
     NullAwareGuard nullAwareGuard =
         inferrer.createNullAwareGuard(node.variable);
     ExpressionInferenceResult readResult =
@@ -2417,6 +2437,8 @@
       NullAwarePropertySet node, DartType typeContext) {
     Link<NullAwareGuard> nullAwareGuards =
         inferrer.inferSyntheticVariableNullAware(node.variable);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        node.variable.type, "?.", node.variable.fileOffset);
     NullAwareGuard nullAwareGuard =
         inferrer.createNullAwareGuard(node.variable);
     ExpressionInferenceResult writeResult =
@@ -2430,6 +2452,8 @@
   ExpressionInferenceResult visitNullAwareExtension(
       NullAwareExtension node, DartType typeContext) {
     inferrer.inferSyntheticVariable(node.variable);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        node.variable.type, "?.", node.variable.fileOffset);
     NullAwareGuard nullAwareGuard =
         inferrer.createNullAwareGuard(node.variable);
     ExpressionInferenceResult expressionResult =
@@ -2572,6 +2596,8 @@
     ExpressionInferenceResult readResult = inferrer.inferExpression(
         node.read, const UnknownType(), true,
         isVoidAllowed: true);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        readResult.inferredType, "??=", node.read.fileOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
@@ -2633,6 +2659,8 @@
       IfNullSet node, DartType typeContext) {
     ExpressionInferenceResult readResult =
         inferrer.inferExpression(node.read, const UnknownType(), true);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        readResult.inferredType, "??=", node.read.fileOffset);
     Link<NullAwareGuard> nullAwareGuards;
     Expression read;
     DartType readType;
@@ -2995,6 +3023,8 @@
 
     ExpressionInferenceResult readResult = _computeIndexGet(node.readOffset,
         readReceiver, receiverType, readTarget, readIndex, checkKind);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
     inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
@@ -3114,6 +3144,8 @@
         : const ObjectAccessTarget.missing();
 
     DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        readType, "??=", node.readOffset);
     DartType readIndexType =
         inferrer.getIndexKeyType(readTarget, inferrer.thisType);
 
@@ -3314,6 +3346,8 @@
         readTarget,
         readIndex,
         MethodContravarianceCheckKind.none);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
     inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
@@ -3713,7 +3747,9 @@
       }
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (receiverType is! DynamicType && receiverType.isPotentiallyNullable) {
+      if (receiverType is! DynamicType &&
+          receiverType is! InvalidType &&
+          receiverType.isPotentiallyNullable) {
         if (inferrer.nnbdStrongMode) {
           return new ExpressionInferenceResult(
               readType,
@@ -3894,6 +3930,7 @@
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
       if (receiverType is! DynamicType &&
+          receiverType is! InvalidType &&
           receiverType.isPotentiallyNullable &&
           !inferrer.matchesObjectMemberCall(
               propertyName, const [], const [], const [])) {
@@ -4157,6 +4194,8 @@
     ExpressionInferenceResult receiverResult = inferrer.inferExpression(
         node.receiver, const UnknownType(), true,
         isVoidAllowed: true);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        receiverResult.inferredType, "?.", node.receiver.fileOffset);
 
     Expression receiver;
     DartType receiverType;
@@ -4666,6 +4705,8 @@
     ExpressionInferenceResult receiverResult = inferrer.inferExpression(
         node.receiver, const UnknownType(), true,
         isVoidAllowed: false);
+    reportNonNullableInNullAwareWarningIfNeeded(
+        receiverResult.inferredType, "?.", node.receiver.fileOffset);
 
     Link<NullAwareGuard> nullAwareGuards;
     Expression receiver;
@@ -5436,6 +5477,30 @@
     bool isUnassigned = !inferrer.flowAnalysis.isAssigned(variable);
     if (isUnassigned) {
       inferrer.dataForTesting?.flowAnalysisResult?.unassignedNodes?.add(node);
+      if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+        // Synthetic variables aren't checked.
+        if (variable.name != null &&
+            !variable.isLocalFunction &&
+            variable.type is! InvalidType &&
+            variable.type.isPotentiallyNonNullable) {
+          if (inferrer.nnbdStrongMode) {
+            return new ExpressionInferenceResult(
+                new InvalidType(),
+                inferrer.helper.wrapInProblem(
+                    node,
+                    templateNonNullableNotAssignedError
+                        .withArguments(node.variable.name),
+                    node.variable.name.length));
+          } else {
+            inferrer.library.addProblem(
+                templateNonNullableNotAssignedWarning
+                    .withArguments(node.variable.name),
+                node.fileOffset,
+                node.variable.name.length,
+                inferrer.library.fileUri);
+          }
+        }
+      }
     }
 
     DartType promotedType;
@@ -5659,6 +5724,20 @@
     return new ExpressionInferenceResult(
         result.inferredType, result.expression);
   }
+
+  void reportNonNullableInNullAwareWarningIfNeeded(
+      DartType operandType, String operationName, int offset) {
+    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+      if (operandType is! InvalidType && !operandType.isPotentiallyNullable) {
+        inferrer.library.addProblem(
+            templateNonNullableInNullAware.withArguments(
+                operationName, operandType, inferrer.isNonNullableByDefault),
+            offset,
+            noLength,
+            inferrer.library.fileUri);
+      }
+    }
+  }
 }
 
 class ForInResult {
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 abf58ad..ab93096 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -612,7 +612,8 @@
         initializers: <Initializer>[initializer],
         isSynthetic: true,
         isConst: constructor.isConst && mixin.fields.isEmpty,
-        reference: referenceFrom?.reference);
+        reference: referenceFrom?.reference)
+      ..isNonNullableByDefault = cls.enclosingLibrary.isNonNullableByDefault;
   }
 
   void finishClonedParameters() {
@@ -643,7 +644,9 @@
             returnType: makeConstructorReturnType(enclosingClass)),
         name: new Name(""),
         isSynthetic: true,
-        reference: referenceFrom?.reference);
+        reference: referenceFrom?.reference)
+      ..isNonNullableByDefault =
+          enclosingClass.enclosingLibrary.isNonNullableByDefault;
   }
 
   DartType makeConstructorReturnType(Class enclosingClass) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
index a766916..4196292 100644
--- a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
@@ -62,7 +62,8 @@
         isStatic: true,
         reference: referencesFrom?.reference)
       ..startFileOffset = charOffset
-      ..fileOffset = charOffset;
+      ..fileOffset = charOffset
+      ..isNonNullableByDefault = parent.isNonNullableByDefault;
     return tearoff;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
index 8f443ff..0ef9bba 100644
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/types.dart
@@ -886,7 +886,8 @@
 
   IsSubtypeOf isInterfaceRelated(InterfaceType s, NeverType t, Types types) {
     if (s.classNode == types.hierarchy.nullClass) {
-      if (t.nullability == Nullability.nullable) {
+      if (t.nullability == Nullability.nullable ||
+          t.nullability == Nullability.legacy) {
         return const IsSubtypeOf.always();
       }
       if (t.nullability == Nullability.nonNullable) {
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 ea4acbe..575cd9b 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
@@ -170,7 +170,9 @@
         referencesFrom = referencesFrom,
         referencesFromIndexed = referencesFromIndexed,
         super(metadata, modifiers, name, typeVariables, supertype, interfaces,
-            onTypes, scope, constructors, parent, nameOffset);
+            onTypes, scope, constructors, parent, nameOffset) {
+    actualCls.hasConstConstructor = hasConstConstructor;
+  }
 
   @override
   Class get cls => origin.actualCls;
@@ -450,7 +452,8 @@
             returnType: substitution.substituteType(field.type)),
         fileUri: field.fileUri,
         reference: referenceFrom?.reference)
-      ..fileOffset = field.fileOffset;
+      ..fileOffset = field.fileOffset
+      ..isNonNullableByDefault = cls.enclosingLibrary.isNonNullableByDefault;
     transformProcedureToNoSuchMethodForwarder(noSuchMethod, target, getter);
     cls.procedures.add(getter);
     getter.parent = cls;
@@ -482,7 +485,8 @@
             returnType: const VoidType()),
         fileUri: field.fileUri,
         reference: referenceFrom?.reference)
-      ..fileOffset = field.fileOffset;
+      ..fileOffset = field.fileOffset
+      ..isNonNullableByDefault = cls.enclosingLibrary.isNonNullableByDefault;
     transformProcedureToNoSuchMethodForwarder(noSuchMethod, target, setter);
     cls.procedures.add(setter);
     setter.parent = cls;
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 dc904d8..3659c69 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
@@ -39,13 +39,14 @@
         Nullability,
         Procedure,
         ProcedureKind,
+        Reference,
         SetLiteral,
         StaticInvocation,
         StringLiteral,
         Supertype,
-        Typedef,
         TypeParameter,
         TypeParameterType,
+        Typedef,
         VariableDeclaration,
         VoidType;
 
@@ -261,7 +262,7 @@
   /// the error message is the corresponding value in the map.
   Map<String, String> unserializableExports;
 
-  List<FieldBuilder> implicitlyTypedFields;
+  List<FieldBuilder> _implicitlyTypedFields;
 
   LanguageVersion _languageVersion = const ImplicitLanguageVersion();
 
@@ -774,13 +775,18 @@
     }
   }
 
-  Builder addBuilder(String name, Builder declaration, int charOffset) {
+  @override
+  Builder addBuilder(String name, Builder declaration, int charOffset,
+      {Reference reference}) {
     // TODO(ahe): Set the parent correctly here. Could then change the
     // implementation of MemberBuilder.isTopLevel to test explicitly for a
     // LibraryBuilder.
     if (name == null) {
       unhandled("null", "name", charOffset, fileUri);
     }
+    if (reference != null) {
+      loader.buildersCreatedWithReferences[reference] = declaration;
+    }
     if (currentTypeParameterScopeBuilder == libraryDeclaration) {
       if (declaration is MemberBuilder) {
         declaration.parent = this;
@@ -1134,9 +1140,12 @@
         // DietListener can find them.
         for (int i = duplicated.length; i > 0; i--) {
           Builder declaration = duplicated[i - 1];
+          // No reference: There should be no duplicates when using references.
           addBuilder(name, declaration, declaration.charOffset);
         }
       } else {
+        // No reference: The part is in the same loader so the reference
+        // - if needed - was already added.
         addBuilder(name, declaration, declaration.charOffset);
       }
     }
@@ -1157,10 +1166,10 @@
     List<FieldBuilder> partImplicitlyTypedFields =
         part.takeImplicitlyTypedFields();
     if (partImplicitlyTypedFields != null) {
-      if (implicitlyTypedFields == null) {
-        implicitlyTypedFields = partImplicitlyTypedFields;
+      if (_implicitlyTypedFields == null) {
+        _implicitlyTypedFields = partImplicitlyTypedFields;
       } else {
-        implicitlyTypedFields.addAll(partImplicitlyTypedFields);
+        _implicitlyTypedFields.addAll(partImplicitlyTypedFields);
       }
     }
     return true;
@@ -1553,7 +1562,8 @@
     members.forEach(setParentAndCheckConflicts);
     constructors.forEach(setParentAndCheckConflicts);
     setters.forEach(setParentAndCheckConflicts);
-    addBuilder(className, classBuilder, nameOffset);
+    addBuilder(className, classBuilder, nameOffset,
+        reference: referencesFromClass?.reference);
   }
 
   Map<String, TypeVariableBuilder> checkTypeVariables(
@@ -1668,7 +1678,8 @@
     members.forEach(setParentAndCheckConflicts);
     constructors.forEach(setParentAndCheckConflicts);
     setters.forEach(setParentAndCheckConflicts);
-    addBuilder(extensionName, extensionBuilder, nameOffset);
+    addBuilder(extensionName, extensionBuilder, nameOffset,
+        reference: referenceFrom?.reference);
   }
 
   TypeBuilder applyMixins(TypeBuilder type, int startCharOffset, int charOffset,
@@ -1906,7 +1917,8 @@
         // pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
         // handle that :(
         application.cls.isAnonymousMixin = !isNamedMixinApplication;
-        addBuilder(fullname, application, charOffset);
+        addBuilder(fullname, application, charOffset,
+            reference: referencesFromClass?.reference);
         supertype = addNamedType(fullname, const NullabilityBuilder.omitted(),
             applicationTypeArguments, charOffset);
       }
@@ -2062,13 +2074,22 @@
         getterReferenceFrom,
         setterReferenceFrom);
     fieldBuilder.constInitializerToken = constInitializerToken;
-    addBuilder(name, fieldBuilder, charOffset);
-    if (type == null && initializerToken != null && fieldBuilder.next == null) {
+    addBuilder(name, fieldBuilder, charOffset,
+        reference: referenceFrom?.reference);
+    if (type == null && fieldBuilder.next == null) {
       // Only the first one (the last one in the linked list of next pointers)
       // are added to the tree, had parent pointers and can infer correctly.
-      fieldBuilder.fieldType =
-          new ImplicitFieldType(fieldBuilder, initializerToken);
-      (implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
+      if (initializerToken == null && fieldBuilder.isStatic) {
+        // A static field without type and initializer will always be inferred
+        // to have type `dynamic`.
+        fieldBuilder.fieldType = const DynamicType();
+      } else {
+        // A field with no type and initializer or an instance field without
+        // type and initializer need to have the type inferred.
+        fieldBuilder.fieldType =
+            new ImplicitFieldType(fieldBuilder, initializerToken);
+        registerImplicitlyTypedField(fieldBuilder);
+      }
     }
     loader.target.metadataCollector
         ?.setDocumentationComment(fieldBuilder.field, documentationComment);
@@ -2114,7 +2135,8 @@
     metadataCollector?.setConstructorNameOffset(
         constructorBuilder.constructor, name);
     checkTypeVariables(typeVariables, constructorBuilder);
-    addBuilder(constructorName, constructorBuilder, charOffset);
+    addBuilder(constructorName, constructorBuilder, charOffset,
+        reference: referenceFrom?.reference);
     if (nativeMethodName != null) {
       addNativeMethod(constructorBuilder);
     }
@@ -2219,7 +2241,8 @@
     metadataCollector?.setDocumentationComment(
         procedureBuilder.procedure, documentationComment);
     checkTypeVariables(typeVariables, procedureBuilder);
-    addBuilder(name, procedureBuilder, charOffset);
+    addBuilder(name, procedureBuilder, charOffset,
+        reference: referenceFrom?.reference);
     if (nativeMethodName != null) {
       addNativeMethod(procedureBuilder);
     }
@@ -2319,7 +2342,8 @@
     currentTypeParameterScopeBuilder = savedDeclaration;
 
     factoryDeclaration.resolveTypes(procedureBuilder.typeVariables, this);
-    addBuilder(procedureName, procedureBuilder, charOffset);
+    addBuilder(procedureName, procedureBuilder, charOffset,
+        reference: referenceFrom?.reference);
     if (nativeMethodName != null) {
       addNativeMethod(procedureBuilder);
     }
@@ -2352,7 +2376,8 @@
         charEndOffset,
         referencesFromClass,
         referencesFromIndexedClass);
-    addBuilder(name, builder, charOffset);
+    addBuilder(name, builder, charOffset,
+        reference: referencesFromClass?.reference);
     metadataCollector?.setDocumentationComment(
         builder.cls, documentationComment);
   }
@@ -2379,7 +2404,8 @@
     // Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
     endNestedDeclaration(TypeParameterScopeKind.typedef, "#typedef")
         .resolveTypes(typeVariables, this);
-    addBuilder(name, typedefBuilder, charOffset);
+    addBuilder(name, typedefBuilder, charOffset,
+        reference: referenceFrom?.reference);
   }
 
   FunctionTypeBuilder addFunctionType(
@@ -3387,10 +3413,14 @@
     inferredTypes.clear();
   }
 
+  void registerImplicitlyTypedField(FieldBuilder fieldBuilder) {
+    (_implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
+  }
+
   @override
   List<FieldBuilder> takeImplicitlyTypedFields() {
-    List<FieldBuilder> result = implicitlyTypedFields;
-    implicitlyTypedFields = null;
+    List<FieldBuilder> result = _implicitlyTypedFields;
+    _implicitlyTypedFields = null;
     return result;
   }
 
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 9a79867..9d3b7d3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -40,6 +40,7 @@
         LibraryDependency,
         Nullability,
         ProcedureKind,
+        Reference,
         Supertype,
         TreeNode;
 
@@ -152,6 +153,11 @@
   ClassHierarchy hierarchy;
   CoreTypes _coreTypes;
 
+  /// For builders created with a reference, this maps from that reference to
+  /// that builder. This is used for looking up source builders when finalizing
+  /// exports in dill builders.
+  Map<Reference, Builder> buildersCreatedWithReferences = {};
+
   /// Used when checking whether a return type of an async function is valid.
   ///
   /// The said return type is valid if it's a subtype of [futureOfBottom].
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 084889f..6257581 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
@@ -23,6 +23,8 @@
         Variance,
         VoidType;
 
+import 'package:kernel/core_types.dart';
+
 import 'package:kernel/type_algebra.dart';
 
 import 'package:kernel/type_environment.dart';
@@ -34,16 +36,7 @@
 import '../problems.dart';
 
 abstract class StandardBounds {
-  Class get functionClass;
-  Class get futureClass;
-  Class get futureOrClass;
-  Class get objectClass;
-  InterfaceType get nullType;
-  InterfaceType get objectLegacyRawType;
-  InterfaceType get objectNonNullableRawType;
-  InterfaceType get functionLegacyRawType;
-  InterfaceType functionRawType(Nullability nullability);
-  InterfaceType objectRawType(Nullability nullability);
+  CoreTypes get coreTypes;
 
   bool isSubtypeOf(DartType subtype, DartType supertype, SubtypeCheckMode mode);
 
@@ -52,118 +45,13 @@
   InterfaceType getLegacyLeastUpperBound(
       InterfaceType type1, InterfaceType type2, Library clientLibrary);
 
-  /// Checks if [type] satisfies the TOP predicate.
-  ///
-  /// For the definition of TOP see the following:
-  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
-  bool _isTop(DartType type) {
-    if (type is InvalidType) return false;
-
-    // TOP(dynamic) is true.
-    if (type is DynamicType) return true;
-
-    // TOP(void) is true.
-    if (type is VoidType) return true;
-
-    // TOP(T?) is true iff TOP(T) or OBJECT(T).
-    // TOP(T*) is true iff TOP(T) or OBJECT(T).
-    if (type.nullability == Nullability.nullable ||
-        type.nullability == Nullability.legacy) {
-      DartType nonNullableType = type.withNullability(Nullability.nonNullable);
-      assert(type != nonNullableType);
-      return _isTop(nonNullableType) || _isObject(nonNullableType);
-    }
-
-    // TOP(FutureOr<T>) is TOP(T).
-    if (type is InterfaceType && type.classNode == futureOrClass) {
-      return _isTop(type.typeArguments.single);
-    }
-
-    return false;
-  }
-
-  /// Checks if [type] satisfies the OBJECT predicate.
-  ///
-  /// For the definition of OBJECT see the following:
-  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
-  bool _isObject(DartType type) {
-    if (type is InvalidType) return false;
-
-    // OBJECT(Object) is true.
-    if (type is InterfaceType &&
-        type.classNode == objectClass &&
-        type.nullability == Nullability.nonNullable) {
-      return true;
-    }
-
-    // OBJECT(FutureOr<T>) is OBJECT(T).
-    if (type is InterfaceType &&
-        type.classNode == futureOrClass &&
-        type.nullability == Nullability.nonNullable) {
-      return _isObject(type.typeArguments.single);
-    }
-
-    return false;
-  }
-
-  /// Checks if [type] satisfies the BOTTOM predicate.
-  ///
-  /// For the definition of BOTTOM see the following:
-  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
-  bool _isBottom(DartType type) {
-    if (type is InvalidType) return false;
-
-    // BOTTOM(Never) is true.
-    if (type is NeverType && type.nullability == Nullability.nonNullable) {
-      return true;
-    }
-
-    // BOTTOM(X&T) is true iff BOTTOM(T).
-    if (type is TypeParameterType &&
-        type.promotedBound != null &&
-        type.isPotentiallyNonNullable) {
-      return _isBottom(type.promotedBound);
-    }
-
-    // BOTTOM(X extends T) is true iff BOTTOM(T).
-    if (type is TypeParameterType && type.isPotentiallyNonNullable) {
-      assert(type.promotedBound == null);
-      return _isBottom(type.parameter.bound);
-    }
-
-    if (type is BottomType) return true;
-
-    return false;
-  }
-
-  /// Checks if [type] satisfies the NULL predicate.
-  ///
-  /// For the definition of NULL see the following:
-  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
-  bool _isNull(DartType type) {
-    if (type is InvalidType) return false;
-
-    // NULL(Null) is true.
-    if (type == nullType) return true;
-
-    // NULL(T?) is true iff NULL(T) or BOTTOM(T).
-    // NULL(T*) is true iff NULL(T) or BOTTOM(T).
-    if (type.nullability == Nullability.nullable ||
-        type.nullability == Nullability.legacy) {
-      DartType nonNullableType = type.withNullability(Nullability.nonNullable);
-      return _isBottom(nonNullableType);
-    }
-
-    return false;
-  }
-
   /// Checks the value of the MORETOP predicate for [s] and [t].
   ///
   /// For the definition of MORETOP see the following:
   /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
   bool moretop(DartType s, DartType t) {
-    assert(_isTop(s) || _isObject(s));
-    assert(_isTop(t) || _isObject(t));
+    assert(coreTypes.isTop(s) || coreTypes.isObject(s));
+    assert(coreTypes.isTop(t) || coreTypes.isObject(t));
 
     // MORETOP(void, T) = true.
     if (s is VoidType) return true;
@@ -179,14 +67,14 @@
 
     // MORETOP(Object, T) = true.
     if (s is InterfaceType &&
-        s.classNode == objectClass &&
+        s.classNode == coreTypes.objectClass &&
         s.nullability == Nullability.nonNullable) {
       return true;
     }
 
     // MORETOP(S, Object) = false.
     if (t is InterfaceType &&
-        t.classNode == objectClass &&
+        t.classNode == coreTypes.objectClass &&
         t.nullability == Nullability.nonNullable) {
       return false;
     }
@@ -247,10 +135,10 @@
 
     // MORETOP(FutureOr<S>, FutureOr<T>) = MORETOP(S, T).
     if (s is InterfaceType &&
-        s.classNode == futureOrClass &&
+        s.classNode == coreTypes.futureOrClass &&
         s.nullability == Nullability.nonNullable &&
         t is InterfaceType &&
-        t.classNode == futureOrClass &&
+        t.classNode == coreTypes.futureOrClass &&
         t.nullability == Nullability.nonNullable) {
       return moretop(s.typeArguments.single, t.typeArguments.single);
     }
@@ -266,8 +154,8 @@
   /// For the definition of MOREBOTTOM see the following:
   /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
   bool morebottom(DartType s, DartType t) {
-    assert(_isBottom(s) || _isNull(s));
-    assert(_isBottom(t) || _isNull(t));
+    assert(coreTypes.isBottom(s) || coreTypes.isNull(s));
+    assert(coreTypes.isBottom(t) || coreTypes.isNull(t));
 
     // MOREBOTTOM(Never, T) = true.
     if (s is NeverType && s.nullability == Nullability.nonNullable) {
@@ -280,12 +168,12 @@
     }
 
     // MOREBOTTOM(Null, T) = true.
-    if (s == nullType) {
+    if (s == coreTypes.nullType) {
       return true;
     }
 
     // MOREBOTTOM(S, Null) = false.
-    if (t == nullType) {
+    if (t == coreTypes.nullType) {
       return false;
     }
 
@@ -402,10 +290,10 @@
     //   T2 otherwise
     // DOWN(T1, T2) = T2 if TOP(T1)
     // DOWN(T1, T2) = T1 if TOP(T2)
-    if (_isTop(type1)) {
-      if (_isTop(type2)) return moretop(type2, type1) ? type1 : type2;
+    if (coreTypes.isTop(type1)) {
+      if (coreTypes.isTop(type2)) return moretop(type2, type1) ? type1 : type2;
       return type2;
-    } else if (_isTop(type2)) {
+    } else if (coreTypes.isTop(type2)) {
       return type1;
     }
 
@@ -414,10 +302,12 @@
     //   T2 otherwise
     // DOWN(T1, T2) = T2 if BOTTOM(T2)
     // DOWN(T1, T2) = T1 if BOTTOM(T1)
-    if (_isBottom(type1)) {
-      if (_isBottom(type2)) return morebottom(type1, type2) ? type1 : type2;
+    if (coreTypes.isBottom(type1)) {
+      if (coreTypes.isBottom(type2)) {
+        return morebottom(type1, type2) ? type1 : type2;
+      }
       return type1;
-    } else if (_isBottom(type2)) {
+    } else if (coreTypes.isBottom(type2)) {
       return type2;
     }
 
@@ -430,16 +320,20 @@
     // DOWN(T1, Null) =
     //  Null if Null <: T1
     //  Never otherwise
-    if (_isNull(type1)) {
-      if (_isNull(type2)) return morebottom(type1, type2) ? type1 : type2;
-      Nullability type2Nullability = computeNullability(type2, futureOrClass);
+    if (coreTypes.isNull(type1)) {
+      if (coreTypes.isNull(type2)) {
+        return morebottom(type1, type2) ? type1 : type2;
+      }
+      Nullability type2Nullability =
+          computeNullability(type2, coreTypes.futureOrClass);
       if (type2Nullability == Nullability.legacy ||
           type2Nullability == Nullability.nullable) {
         return type1;
       }
       return const NeverType(Nullability.nonNullable);
-    } else if (_isNull(type2)) {
-      Nullability type1Nullability = computeNullability(type1, futureOrClass);
+    } else if (coreTypes.isNull(type2)) {
+      Nullability type1Nullability =
+          computeNullability(type1, coreTypes.futureOrClass);
       if (type1Nullability == Nullability.legacy ||
           type1Nullability == Nullability.nullable) {
         return type2;
@@ -458,25 +352,29 @@
     //   T1 if T1 is non-nullable
     //   NonNull(T1) if NonNull(T1) is non-nullable
     //   Never otherwise
-    if (_isObject(type1)) {
-      if (_isObject(type2)) return moretop(type2, type1) ? type1 : type2;
-      Nullability type2Nullability = computeNullability(type2, futureOrClass);
+    if (coreTypes.isObject(type1)) {
+      if (coreTypes.isObject(type2)) {
+        return moretop(type2, type1) ? type1 : type2;
+      }
+      Nullability type2Nullability =
+          computeNullability(type2, coreTypes.futureOrClass);
       if (type2Nullability == Nullability.nonNullable) {
         return type2;
       }
       type2 = type2.withNullability(Nullability.nonNullable);
-      type2Nullability = computeNullability(type2, futureOrClass);
+      type2Nullability = computeNullability(type2, coreTypes.futureOrClass);
       if (type2Nullability == Nullability.nonNullable) {
         return type2;
       }
       return const NeverType(Nullability.nonNullable);
-    } else if (_isObject(type2)) {
-      Nullability type1Nullability = computeNullability(type1, futureOrClass);
+    } else if (coreTypes.isObject(type2)) {
+      Nullability type1Nullability =
+          computeNullability(type1, coreTypes.futureOrClass);
       if (type1Nullability == Nullability.nonNullable) {
         return type1;
       }
       type1 = type1.withNullability(Nullability.nonNullable);
-      type1Nullability = computeNullability(type1, futureOrClass);
+      type1Nullability = computeNullability(type1, coreTypes.futureOrClass);
       if (type1Nullability == Nullability.nonNullable) {
         return type1;
       }
@@ -554,18 +452,18 @@
     }
 
     // SLB(Object, T) = SLB(T, Object) = T if T is not void or dynamic.
-    if (type1 == objectLegacyRawType) {
+    if (type1 == coreTypes.objectLegacyRawType) {
       return type2;
     }
-    if (type2 == objectLegacyRawType) {
+    if (type2 == coreTypes.objectLegacyRawType) {
       return type1;
     }
 
     // SLB(bottom, T) = SLB(T, bottom) = bottom.
     if (type1 is BottomType) return type1;
     if (type2 is BottomType) return type2;
-    if (type1 == nullType) return type1;
-    if (type2 == nullType) return type2;
+    if (type1 == coreTypes.nullType) return type1;
+    if (type2 == coreTypes.nullType) return type2;
 
     // Function types have structural lower bounds.
     if (type1 is FunctionType && type2 is FunctionType) {
@@ -584,21 +482,21 @@
     }
 
     // See https://github.com/dart-lang/sdk/issues/37439#issuecomment-519654959.
-    if (type1 is InterfaceType && type1.classNode == futureOrClass) {
+    if (type1 is InterfaceType && type1.classNode == coreTypes.futureOrClass) {
       if (type2 is InterfaceType) {
-        if (type2.classNode == futureOrClass) {
+        if (type2.classNode == coreTypes.futureOrClass) {
           // GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
           DartType argument = getStandardLowerBound(
               type1.typeArguments[0], type2.typeArguments[0], clientLibrary);
-          return new InterfaceType(
-              futureOrClass, argument.nullability, <DartType>[argument]);
+          return new InterfaceType(coreTypes.futureOrClass,
+              argument.nullability, <DartType>[argument]);
         }
-        if (type2.classNode == futureClass) {
+        if (type2.classNode == coreTypes.futureClass) {
           // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
           return new InterfaceType(
-              futureClass,
+              coreTypes.futureClass,
               intersectNullabilities(
-                  computeNullabilityOfFutureOr(type1, futureOrClass),
+                  computeNullabilityOfFutureOr(type1, coreTypes.futureOrClass),
                   type2.nullability),
               <DartType>[
                 getStandardLowerBound(type1.typeArguments[0],
@@ -615,13 +513,13 @@
     // It's broken down into sub-cases instead of making a recursive call to
     // avoid making the checks that were already made above.  Note that at this
     // point it's not possible for type1 to be a FutureOr.
-    if (type2 is InterfaceType && type2.classNode == futureOrClass) {
-      if (type1 is InterfaceType && type1.classNode == futureClass) {
+    if (type2 is InterfaceType && type2.classNode == coreTypes.futureOrClass) {
+      if (type1 is InterfaceType && type1.classNode == coreTypes.futureClass) {
         // GLB(Future<A>, FutureOr<B>) == Future<GLB(B, A)>
         return new InterfaceType(
-            futureClass,
+            coreTypes.futureClass,
             intersectNullabilities(type1.nullability,
-                computeNullabilityOfFutureOr(type2, futureOrClass)),
+                computeNullabilityOfFutureOr(type2, coreTypes.futureOrClass)),
             <DartType>[
               getStandardLowerBound(
                   type2.typeArguments[0], type1.typeArguments[0], clientLibrary)
@@ -664,10 +562,10 @@
     //   T2 otherwise
     // UP(T1, T2) = T1 if TOP(T1)
     // UP(T1, T2) = T2 if TOP(T2)
-    if (_isTop(type1)) {
-      if (_isTop(type2)) return moretop(type1, type2) ? type1 : type2;
+    if (coreTypes.isTop(type1)) {
+      if (coreTypes.isTop(type2)) return moretop(type1, type2) ? type1 : type2;
       return type1;
-    } else if (_isTop(type2)) {
+    } else if (coreTypes.isTop(type2)) {
       return type2;
     }
 
@@ -676,10 +574,12 @@
     //   T1 otherwise
     // UP(T1, T2) = T2 if BOTTOM(T1)
     // UP(T1, T2) = T1 if BOTTOM(T2)
-    if (_isBottom(type1)) {
-      if (_isBottom(type2)) return morebottom(type1, type2) ? type2 : type1;
+    if (coreTypes.isBottom(type1)) {
+      if (coreTypes.isBottom(type2)) {
+        return morebottom(type1, type2) ? type2 : type1;
+      }
       return type2;
-    } else if (_isBottom(type2)) {
+    } else if (coreTypes.isBottom(type2)) {
       return type1;
     }
 
@@ -692,10 +592,12 @@
     // UP(T1, T2) where NULL(T2) =
     //   T1 if T1 is nullable
     //   T1? otherwise
-    if (_isNull(type1)) {
-      if (_isNull(type2)) return morebottom(type1, type2) ? type2 : type1;
+    if (coreTypes.isNull(type1)) {
+      if (coreTypes.isNull(type2)) {
+        return morebottom(type1, type2) ? type2 : type1;
+      }
       return type2.withNullability(Nullability.nullable);
-    } else if (_isNull(type2)) {
+    } else if (coreTypes.isNull(type2)) {
       return type1.withNullability(Nullability.nullable);
     }
 
@@ -708,14 +610,18 @@
     // UP(T1, T2) where OBJECT(T2) =
     //   T2 if T1 is non-nullable
     //   T2? otherwise
-    if (_isObject(type1)) {
-      if (_isObject(type2)) return moretop(type1, type2) ? type1 : type2;
-      if (computeNullability(type2, futureOrClass) == Nullability.nonNullable) {
+    if (coreTypes.isObject(type1)) {
+      if (coreTypes.isObject(type2)) {
+        return moretop(type1, type2) ? type1 : type2;
+      }
+      if (computeNullability(type2, coreTypes.futureOrClass) ==
+          Nullability.nonNullable) {
         return type1;
       }
       return type1.withNullability(Nullability.nullable);
-    } else if (_isObject(type2)) {
-      if (computeNullability(type1, futureOrClass) == Nullability.nonNullable) {
+    } else if (coreTypes.isObject(type2)) {
+      if (computeNullability(type1, coreTypes.futureOrClass) ==
+          Nullability.nonNullable) {
         return type2;
       }
       return type2.withNullability(Nullability.nullable);
@@ -748,24 +654,26 @@
             type1, type2, clientLibrary);
       }
 
-      if (type2 is InterfaceType && type2.classNode == functionClass) {
+      if (type2 is InterfaceType &&
+          type2.classNode == coreTypes.functionClass) {
         // UP(T Function<...>(...), Function) = Function
-        return functionRawType(
+        return coreTypes.functionRawType(
             uniteNullabilities(type1.nullability, type2.nullability));
       }
 
       // UP(T Function<...>(...), T2) = Object
-      return objectRawType(
+      return coreTypes.objectRawType(
           uniteNullabilities(type1.nullability, type2.nullability));
     } else if (type2 is FunctionType) {
-      if (type1 is InterfaceType && type1.classNode == functionClass) {
+      if (type1 is InterfaceType &&
+          type1.classNode == coreTypes.functionClass) {
         // UP(Function, T Function<...>(...)) = Function
-        return functionRawType(
+        return coreTypes.functionRawType(
             uniteNullabilities(type1.nullability, type2.nullability));
       }
 
       // UP(T1, T Function<...>(...)) = Object
-      return objectRawType(
+      return coreTypes.objectRawType(
           uniteNullabilities(type1.nullability, type2.nullability));
     }
 
@@ -1034,8 +942,8 @@
 
     // The return value for whenever the following applies:
     //     UP(T Function<...>(...), S Function<...>(...)) = Function otherwise
-    final DartType fallbackResult =
-        functionRawType(uniteNullabilities(f.nullability, g.nullability));
+    final DartType fallbackResult = coreTypes
+        .functionRawType(uniteNullabilities(f.nullability, g.nullability));
 
     if (haveNamed && haveOptionalPositional) return fallbackResult;
     if (!haveNamed && f.requiredParameterCount != g.requiredParameterCount) {
@@ -1171,7 +1079,7 @@
             uniteNullabilities(type1.nullability, type2.nullability));
       }
       Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
-        type1.parameter: objectNonNullableRawType
+        type1.parameter: coreTypes.objectNonNullableRawType
       };
       return getNullabilityAwareStandardUpperBound(
               substitute(type1.parameter.bound, substitution),
@@ -1195,7 +1103,7 @@
             uniteNullabilities(type1.nullability, type2.nullability));
       }
       Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
-        type1.parameter: objectNonNullableRawType
+        type1.parameter: coreTypes.objectNonNullableRawType
       };
       return getNullabilityAwareStandardUpperBound(
               substitute(type1.promotedBound, substitution),
@@ -1241,18 +1149,18 @@
     }
 
     // SUB(Object, T) = SUB(T, Object) = Object if T is not void or dynamic.
-    if (type1 == objectLegacyRawType) {
+    if (type1 == coreTypes.objectLegacyRawType) {
       return type1;
     }
-    if (type2 == objectLegacyRawType) {
+    if (type2 == coreTypes.objectLegacyRawType) {
       return type2;
     }
 
     // SUB(bottom, T) = SUB(T, bottom) = T.
     if (type1 is BottomType) return type2;
     if (type2 is BottomType) return type1;
-    if (type1 == nullType) return type2;
-    if (type2 == nullType) return type1;
+    if (type1 == coreTypes.nullType) return type2;
+    if (type2 == coreTypes.nullType) return type1;
 
     if (type1 is TypeParameterType || type2 is TypeParameterType) {
       return _getNullabilityObliviousTypeParameterStandardUpperBound(
@@ -1262,10 +1170,10 @@
     // The standard upper bound of a function type and an interface type T is
     // the standard upper bound of Function and T.
     if (type1 is FunctionType && type2 is InterfaceType) {
-      type1 = functionLegacyRawType;
+      type1 = coreTypes.functionLegacyRawType;
     }
     if (type2 is FunctionType && type1 is InterfaceType) {
-      type2 = functionLegacyRawType;
+      type2 = coreTypes.functionLegacyRawType;
     }
 
     // At this point type1 and type2 should both either be interface types or
@@ -1405,7 +1313,7 @@
     //   SUB(([int]) -> void, (int) -> void) = (int) -> void
     if (f.requiredParameterCount != g.requiredParameterCount) {
       return new InterfaceType(
-          functionClass,
+          coreTypes.functionClass,
           uniteNullabilities(f.nullability, g.nullability),
           const <DynamicType>[]);
     }
@@ -1565,14 +1473,14 @@
       // C<T extends U, U extends List>, T gets resolved directly to List.  Do
       // we need to replicate that behavior?
       return getStandardUpperBound(
-          Substitution.fromMap({type1.parameter: objectLegacyRawType})
+          Substitution.fromMap({type1.parameter: coreTypes.objectLegacyRawType})
               .substituteType(type1.parameter.bound),
           type2,
           clientLibrary);
     } else if (type2 is TypeParameterType) {
       return getStandardUpperBound(
           type1,
-          Substitution.fromMap({type2.parameter: objectLegacyRawType})
+          Substitution.fromMap({type2.parameter: coreTypes.objectLegacyRawType})
               .substituteType(type2.parameter.bound),
           clientLibrary);
     } else {
diff --git a/pkg/front_end/lib/src/fasta/util/textual_outline.dart b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
index a6c7251..7cb4916 100644
--- a/pkg/front_end/lib/src/fasta/util/textual_outline.dart
+++ b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
@@ -9,6 +9,9 @@
 import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
     show ClassMemberParser;
 
+import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart'
+    show DeclarationKind;
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ErrorToken, LanguageVersionToken, Scanner;
 
@@ -47,9 +50,12 @@
     if (token is ErrorToken) {
       return null;
     }
-    if (printed && token.offset > endOfLast) {
+    if (addLinebreak) {
+      sb.write("\n");
+    } else if (printed && token.offset > endOfLast) {
       sb.write(" ");
     }
+    addLinebreak = false;
 
     sb.write(token.lexeme);
     printed = true;
@@ -58,19 +64,19 @@
       if (token.lexeme == ";") {
         addLinebreak = true;
       } else if (token.endGroup != null &&
-          listener.endOffsets.contains(token.endGroup.offset)) {
+          (listener.nonClassEndOffsets.contains(token.endGroup.offset) ||
+              listener.classEndOffsets.contains(token.endGroup.offset))) {
         addLinebreak = true;
-      } else if (listener.endOffsets.contains(token.offset)) {
+      } else if (listener.nonClassEndOffsets.contains(token.offset) ||
+          listener.classEndOffsets.contains(token.offset)) {
         addLinebreak = true;
       }
     }
 
-    if (addLinebreak) sb.write("\n");
-    addLinebreak = false;
     if (token.isEof) break;
 
     if (token.endGroup != null &&
-        listener.endOffsets.contains(token.endGroup.offset)) {
+        listener.nonClassEndOffsets.contains(token.endGroup.offset)) {
       token = token.endGroup;
     } else {
       token = token.next;
@@ -86,17 +92,30 @@
 }
 
 class EndOffsetListener extends DirectiveListener {
-  Set<int> endOffsets = new Set<int>();
+  Set<int> nonClassEndOffsets = new Set<int>();
+  Set<int> classEndOffsets = new Set<int>();
 
   @override
   void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
       Token beginInitializers, Token endToken) {
-    endOffsets.add(endToken.offset);
+    nonClassEndOffsets.add(endToken.offset);
   }
 
   @override
   void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
-    endOffsets.add(endToken.offset);
+    nonClassEndOffsets.add(endToken.offset);
+  }
+
+  @override
+  void endClassFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    nonClassEndOffsets.add(endToken.offset);
+  }
+
+  @override
+  void endClassOrMixinBody(
+      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+    classEndOffsets.add(endToken.offset);
   }
 
   @override
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 4ea9e45..b92c7eb6 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -465,6 +465,12 @@
 NonConstFactory/example: Fail
 NonInstanceTypeVariableUse/example: Fail
 NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
+NonNullableInNullAware/analyzerCode: Fail
+NonNullableInNullAware/example: Fail
+NonNullableNotAssignedError/analyzerCode: Fail
+NonNullableNotAssignedError/example: Fail
+NonNullableNotAssignedWarning/analyzerCode: Fail
+NonNullableNotAssignedWarning/example: Fail
 NonNullableOptOut/analyzerCode: Fail
 NonNullableOptOut/example: Fail
 NonPartOfDirectiveInPart/part_wrapped_script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index b81fef3..8bc06a4 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -3906,3 +3906,14 @@
   template: "Using the default List constructor."
   tip: "Try using List.filled instead."
   severity: WARNING
+
+NonNullableInNullAware:
+  template: "Operand of null-aware operation '#name' has type '#type' which excludes null."
+  severity: WARNING
+
+NonNullableNotAssignedError:
+  template: "Non-nullable variable '#name' must be assigned before it can be used."
+
+NonNullableNotAssignedWarning:
+  template: "Non-nullable variable '#name' is used before it's assigned."
+  severity: WARNING
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 14828d3..2efcb99 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
@@ -257,7 +257,7 @@
     "Wn*": "Wn extends Tn, Tn extends Never",
 
     // Null.
-    "Null?": null,
+    "Null": null,
   };
 
   static String joinTypeParameters(
@@ -425,8 +425,8 @@
 
     testLower("<X extends dynamic>() -> void", "<Y extends Object?>() -> void",
         "<Z extends dynamic>() -> void");
-    testLower("<X extends Null?>() -> void", "<Y extends Never?>() -> void",
-        "<Z extends Null?>() -> void");
+    testLower("<X extends Null>() -> void", "<Y extends Never?>() -> void",
+        "<Z extends Null>() -> void");
     testLower(
         "<X extends FutureOr<dynamic>?>() -> void",
         "<Y extends FutureOr<Object?>>() -> void",
@@ -786,8 +786,8 @@
 
     testUpper("<X extends dynamic>() -> void", "<Y extends Object?>() -> void",
         "<Z extends dynamic>() -> void");
-    testUpper("<X extends Null?>() -> void", "<Y extends Never?>() -> void",
-        "<Z extends Null?>() -> void");
+    testUpper("<X extends Null>() -> void", "<Y extends Never?>() -> void",
+        "<Z extends Null>() -> void");
     testUpper(
         "<X extends FutureOr<dynamic>?>() -> void",
         "<Y extends FutureOr<Object?>>() -> void",
@@ -1077,7 +1077,7 @@
     expect(
         env.solveTypeConstraint(_makeConstraint(lower: toType("A<unknown>*")),
             grounded: true),
-        toType("A<Null?>*"));
+        toType("A<Null>*"));
 
     // Solve(? <: T <: A*) => A*
     expect(
@@ -1155,7 +1155,7 @@
             _makeConstraint(
                 lower: toType("B<unknown>*"), upper: toType("A<unknown>*")),
             grounded: true),
-        toType("B<Null?>*"));
+        toType("B<Null>*"));
   }
 
   void test_typeConstraint_default() {
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 caed22b..f05c548 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -61,8 +61,8 @@
     isSubtype('double*', 'num*');
     isSubtype('num', 'Object');
     isSubtype('num*', 'Object');
-    isSubtype('Null?', 'num*');
-    isSubtype('Null?', 'num?');
+    isSubtype('Null', 'num*');
+    isSubtype('Null', 'num?');
     isSubtype('Never', 'num');
     isSubtype('Never', 'num*');
     isSubtype('Never', 'num?');
@@ -75,7 +75,7 @@
     isNotSubtype('int*', 'Iterable<int*>*');
     isNotSubtype('Comparable<int*>*', 'Iterable<int*>*');
     isObliviousSubtype('num?', 'Object');
-    isObliviousSubtype('Null?', 'num');
+    isObliviousSubtype('Null', 'num');
     isNotSubtype('num', 'Never');
 
     // Tests for subtypes and supertypes of List.
@@ -91,8 +91,8 @@
     isSubtype('List<int*>*', 'List<Comparable<Comparable<num*>*>*>*');
     isSubtype('List<int*>', 'Object');
     isSubtype('List<int*>*', 'Object');
-    isSubtype('Null?', 'List<int*>*');
-    isSubtype('Null?', 'List<int*>?');
+    isSubtype('Null', 'List<int*>*');
+    isSubtype('Null', 'List<int*>?');
     isSubtype('Never', 'List<int*>');
     isSubtype('Never', 'List<int*>*');
     isSubtype('Never', 'List<int*>?');
@@ -130,7 +130,7 @@
     isNotSubtype('List<int*>*', 'List<Comparable<int*>*>*');
     isNotSubtype('List<int*>*', 'List<Comparable<Comparable<int*>*>*>*');
     isObliviousSubtype('List<int*>?', 'Object');
-    isObliviousSubtype('Null?', 'List<int*>');
+    isObliviousSubtype('Null', 'List<int*>');
     isNotSubtype('List<int*>', 'Never');
 
     isObliviousSubtype('T?', 'List<int>',
@@ -141,8 +141,8 @@
     isSubtype('(num*) ->* int*', '(num*) ->* num*');
     isSubtype('(num*) ->* int*', '(int*) ->* num*');
     isNotSubtype('(int*) ->* int*', '(num*) ->* num*');
-    isSubtype('Null?', '(int*) ->* num*');
-    isSubtype('Null?', '(int*) ->? num*');
+    isSubtype('Null', '(int*) ->* num*');
+    isSubtype('Null', '(int*) ->? num*');
     isSubtype('Never', '(int*) -> num*');
     isSubtype('Never', '(int*) ->* num*');
     isSubtype('Never', '(int*) ->? num*');
@@ -152,7 +152,7 @@
     isSubtype('(num*) ->* num*', 'Object');
     isSubtype('(num*) -> num*', 'Object');
     isObliviousSubtype('(num*) ->? num*', 'Object');
-    isObliviousSubtype('Null?', '(int*) -> num*');
+    isObliviousSubtype('Null', '(int*) -> num*');
     isNotSubtype('(int*) -> num*', 'Never');
     isNotSubtype('num', '(num) -> num');
     isNotSubtype('Object', '(num) -> num');
@@ -248,8 +248,8 @@
     isSubtype('FutureOr<int*>*', 'FutureOr<int*>*');
     isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
     isSubtype('FutureOr<int*>*', 'Object*');
-    isSubtype('Null?', 'FutureOr<num?>');
-    isSubtype('Null?', 'FutureOr<num>?');
+    isSubtype('Null', 'FutureOr<num?>');
+    isSubtype('Null', 'FutureOr<num>?');
     isSubtype('num?', 'FutureOr<num?>');
     isSubtype('num?', 'FutureOr<num>?');
     isSubtype('Future<num>', 'FutureOr<num?>');
@@ -317,8 +317,8 @@
     isNotSubtype('FutureOr<double*>*', 'int*');
     isNotSubtype('FutureOr<int*>*', 'Future<num*>*');
     isNotSubtype('FutureOr<int*>*', 'num*');
-    isSubtype('Null?', 'FutureOr<int*>*');
-    isSubtype('Null?', 'Future<int*>*');
+    isSubtype('Null', 'FutureOr<int*>*');
+    isSubtype('Null', 'Future<int*>*');
     isSubtype('dynamic', 'FutureOr<dynamic>*');
     isNotSubtype('dynamic', 'FutureOr<String*>*');
     isSubtype('void', 'FutureOr<void>*');
@@ -450,13 +450,12 @@
     isNotSubtype('FutureOr<num>', 'Never');
 
     // Testing bottom types against an intersection type.
-    isSubtype('Null?', 'T* & num*', typeParameters: 'T extends Object*');
+    isSubtype('Null', 'T* & num*', typeParameters: 'T extends Object*');
     isSubtype('Never', 'T* & num*', typeParameters: 'T extends Object*');
-    isObliviousSubtype('Null?', 'T & num', typeParameters: 'T extends Object?');
-    isObliviousSubtype('Null?', 'T & num?',
-        typeParameters: 'T extends Object?');
-    isObliviousSubtype('Null?', 'T & num', typeParameters: 'T extends Object');
-    isObliviousSubtype('Null?', 'T & S',
+    isObliviousSubtype('Null', 'T & num', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null', 'T & num?', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null', 'T & num', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null', 'T & S',
         typeParameters: 'T extends Object?, S extends T');
     isNotSubtype('T* & num*', 'Never', typeParameters: 'T extends Object*');
     isSubtype('T', 'Never', typeParameters: 'T extends Never');
@@ -464,19 +463,19 @@
     isSubtype('bottom', 'T & int', typeParameters: 'T extends Object');
 
     // Testing bottom types against type-parameter types.
-    isSubtype('Null?', 'T?', typeParameters: 'T extends Object');
-    isSubtype('Null?', 'T?', typeParameters: 'T extends Object?');
-    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object');
-    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object?');
+    isSubtype('Null', 'T?', typeParameters: 'T extends Object');
+    isSubtype('Null', 'T?', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null', 'T', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null', 'T', typeParameters: 'T extends Object?');
     isSubtype('Never', 'T?', typeParameters: 'T extends Object');
     isSubtype('Never', 'T?', typeParameters: 'T extends Object?');
     isSubtype('Never', 'T', typeParameters: 'T extends Object');
     isSubtype('Never', 'T', typeParameters: 'T extends Object?');
     isObliviousSubtype('Never?', 'T', typeParameters: 'T extends Object?');
-    isSubtype('T', 'Null?', typeParameters: 'T extends Null?');
-    isSubtype('T?', 'Null?', typeParameters: 'T extends Null?');
-    isNotSubtype('T', 'Null?', typeParameters: 'T extends Object');
-    isNotSubtype('T', 'Null?', typeParameters: 'T extends Object?');
+    isSubtype('T', 'Null', typeParameters: 'T extends Null');
+    isSubtype('T?', 'Null', typeParameters: 'T extends Null');
+    isNotSubtype('T', 'Null', typeParameters: 'T extends Object');
+    isNotSubtype('T', 'Null', typeParameters: 'T extends Object?');
     isSubtype('T', 'Never', typeParameters: 'T extends Never');
     isObliviousSubtype('T', 'Never', typeParameters: 'T extends Never?');
     isObliviousSubtype('T?', 'Never', typeParameters: 'T extends Never');
@@ -653,31 +652,31 @@
     isSubtype('() ->? int*', 'Object*');
     isSubtype('() ->? int*', 'Object?');
 
-    // Tests for "Null?".
-    isSubtype('Null?', 'double*');
-    isSubtype('Null?', 'Comparable<Object*>*');
-    isSubtype('Null?', 'Comparable<Object*>?');
-    isSubtype('Null?', 'Typedef<Object*>*');
-    isSubtype('Null?', 'Typedef<Object*>?');
-    isSubtype('Null?', 'T', typeParameters: 'T extends Object*');
-    isSubtype('Null?', 'T?', typeParameters: 'T extends Object');
-    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object?');
-    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object');
-    isObliviousSubtype('Null?', 'Object');
+    // Tests for "Null".
+    isSubtype('Null', 'double*');
+    isSubtype('Null', 'Comparable<Object*>*');
+    isSubtype('Null', 'Comparable<Object*>?');
+    isSubtype('Null', 'Typedef<Object*>*');
+    isSubtype('Null', 'Typedef<Object*>?');
+    isSubtype('Null', 'T', typeParameters: 'T extends Object*');
+    isSubtype('Null', 'T?', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null', 'T', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null', 'T', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null', 'Object');
 
     // Tests for bottom and top types.
-    isSubtype('Null?', 'Null?');
-    isNotSubtype('Null?', 'bottom');
-    isNotSubtype('Null?', 'Never');
-    isSubtype('bottom', 'Null?');
+    isSubtype('Null', 'Null');
+    isNotSubtype('Null', 'bottom');
+    isNotSubtype('Null', 'Never');
+    isSubtype('bottom', 'Null');
     isSubtype('bottom', 'bottom');
     isSubtype('bottom', 'Never');
-    isSubtype('Never', 'Null?');
+    isSubtype('Never', 'Null');
     isNotSubtype('Never', 'bottom');
     isSubtype('Never', 'Never');
 
-    isSubtype('Null?', 'Never?');
-    isSubtype('Never?', 'Null?');
+    isSubtype('Null', 'Never?');
+    isSubtype('Never?', 'Null');
     isSubtype('Never', 'Never?');
     isObliviousSubtype('Never?', 'Never');
 
@@ -706,23 +705,23 @@
     isSubtype('bottom', 'Object*');
     isSubtype('bottom', 'dynamic');
     isSubtype('bottom', 'void');
-    isSubtype('Null?', 'Object?');
-    isSubtype('Null?', 'Object*');
-    isSubtype('Null?', 'dynamic');
-    isSubtype('Null?', 'void');
+    isSubtype('Null', 'Object?');
+    isSubtype('Null', 'Object*');
+    isSubtype('Null', 'dynamic');
+    isSubtype('Null', 'void');
 
     isNotSubtype('Object?', 'Never');
     isNotSubtype('Object?', 'bottom');
-    isNotSubtype('Object?', 'Null?');
+    isNotSubtype('Object?', 'Null');
     isNotSubtype('Object*', 'Never');
     isNotSubtype('Object*', 'bottom');
-    isNotSubtype('Object*', 'Null?');
+    isNotSubtype('Object*', 'Null');
     isNotSubtype('dynamic', 'Never');
     isNotSubtype('dynamic', 'bottom');
-    isNotSubtype('dynamic', 'Null?');
+    isNotSubtype('dynamic', 'Null');
     isNotSubtype('void', 'Never');
     isNotSubtype('void', 'bottom');
-    isNotSubtype('void', 'Null?');
+    isNotSubtype('void', 'Null');
 
     // Tests for Object against the top and the bottom types.
     isSubtype('bottom', 'Object');
@@ -734,7 +733,7 @@
     isSubtype('Object*', 'Object');
 
     isNotSubtype('Object', 'bottom');
-    isNotSubtype('Object', 'Null?');
+    isNotSubtype('Object', 'Null');
     isNotSubtype('Object', 'Never');
     isObliviousSubtype('dynamic', 'Object');
     isObliviousSubtype('void', 'Object');
@@ -857,12 +856,12 @@
     isSubtype('Id<Object>', 'dynamic');
     isObliviousSubtype('void', 'Id<Object>');
     isSubtype('Id<Object>', 'void');
-    isObliviousSubtype('Null?', 'Id<Object>');
+    isObliviousSubtype('Null', 'Id<Object>');
     isSubtype('Never', 'Id<Object>');
     isSubtype('Never', 'Id<Never>');
     isSubtype('Id<Never>', 'Never');
-    isNotSubtype('Null?', 'Id<Never>');
-    isSubtype('Id<Never>', 'Null?');
+    isNotSubtype('Null', 'Id<Never>');
+    isSubtype('Id<Never>', 'Null');
     isNotSubtype('Id<Object>', 'Never');
     isSubtype('Id<int>', 'num');
     isObliviousSubtype('Id<int?>', 'num');
@@ -952,7 +951,7 @@
     isNotSubtype('Id<() ->* Object*>*', 'Id<() ->* int*>*');
 
     isSubtype('void', 'Id<void>*');
-    isNotSubtype('void', 'Id<Null?>*');
+    isNotSubtype('void', 'Id<Null>*');
 
     // The following function type tests are derived from
     // ../../../../../tests/compiler/dart2js/model/subtype_test.dart.
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index 542d5ab..98389b7 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -28,8 +28,7 @@
             experimentalFlags: const {ExperimentalFlag.nonNullable: true},
             librariesSpecificationUri: createUriForFileName('libraries.json'),
             compileSdk: true),
-        new TestConfig(
-            cfeFromBuilderMarker, 'cfe from builder',
+        new TestConfig(cfeFromBuilderMarker, 'cfe from builder',
             experimentalFlags: const {ExperimentalFlag.nonNullable: true},
             librariesSpecificationUri: createUriForFileName('libraries.json'),
             compileSdk: true)
diff --git a/pkg/front_end/test/incremental_dart2js_tester.dart b/pkg/front_end/test/incremental_dart2js_tester.dart
index 0eb21c7..b8f8b47 100644
--- a/pkg/front_end/test/incremental_dart2js_tester.dart
+++ b/pkg/front_end/test/incremental_dart2js_tester.dart
@@ -31,58 +31,50 @@
     }
   }
 
-  Stopwatch stopwatch = new Stopwatch()..start();
-  Uri input = Platform.script.resolve("../../compiler/bin/dart2js.dart");
-  CompilerOptions options = helper.getOptions(targetName: "VM");
-  helper.TestIncrementalCompiler compiler =
-      new helper.TestIncrementalCompiler(options, input);
-  compiler.useExperimentalInvalidation = useExperimentalInvalidation;
-  Component c = await compiler.computeDelta();
-  print("Compiled dart2js to Component with ${c.libraries.length} libraries "
-      "in ${stopwatch.elapsedMilliseconds} ms.");
-  stopwatch.reset();
+  Dart2jsTester dart2jsTester =
+      new Dart2jsTester(useExperimentalInvalidation, fast, addDebugBreaks);
+  await dart2jsTester.test();
+}
+
+class Dart2jsTester {
+  final bool useExperimentalInvalidation;
+  final bool fast;
+  final bool addDebugBreaks;
+
+  Stopwatch stopwatch = new Stopwatch();
   List<int> firstCompileData;
   Map<Uri, List<int>> libToData;
-  if (fast) {
-    libToData = {};
-    c.libraries.sort((l1, l2) {
-      return "${l1.fileUri}".compareTo("${l2.fileUri}");
-    });
-
-    c.problemsAsJson?.sort();
-
-    c.computeCanonicalNames();
-
-    for (Library library in c.libraries) {
-      library.additionalExports.sort((Reference r1, Reference r2) {
-        return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
-      });
-      library.problemsAsJson?.sort();
-
-      List<int> libSerialized =
-          serializeComponent(c, filter: (l) => l == library);
-      libToData[library.importUri] = libSerialized;
-    }
-  } else {
-    firstCompileData = util.postProcess(c);
-  }
-  print("Serialized in ${stopwatch.elapsedMilliseconds} ms");
-  stopwatch.reset();
-
-  List<Uri> uris = c.uriToSource.values
-      .map((s) => s != null ? s.importUri : null)
-      .where((u) => u != null && u.scheme != "dart")
-      .toSet()
-      .toList();
-
-  c = null;
+  List<Uri> uris;
 
   List<Uri> diffs = new List<Uri>();
   Set<Uri> componentUris = new Set<Uri>();
 
-  Stopwatch localStopwatch = new Stopwatch()..start();
-  for (int i = 0; i < uris.length; i++) {
-    Uri uri = uris[i];
+  Dart2jsTester(
+      this.useExperimentalInvalidation, this.fast, this.addDebugBreaks);
+
+  void test() async {
+    helper.TestIncrementalCompiler compiler = await setup();
+
+    diffs = new List<Uri>();
+    componentUris = new Set<Uri>();
+
+    Stopwatch localStopwatch = new Stopwatch()..start();
+    for (int i = 0; i < uris.length; i++) {
+      Uri uri = uris[i];
+      await step(uri, i, compiler, localStopwatch);
+    }
+
+    print("A total of ${diffs.length} diffs:");
+    for (Uri uri in diffs) {
+      print(" - $uri");
+    }
+
+    print("Done after ${uris.length} recompiles in "
+        "${stopwatch.elapsedMilliseconds} ms");
+  }
+
+  Future step(Uri uri, int i, helper.TestIncrementalCompiler compiler,
+      Stopwatch localStopwatch) async {
     print("Invalidating $uri ($i)");
     compiler.invalidate(uri);
     localStopwatch.reset();
@@ -168,24 +160,65 @@
     print("-----");
   }
 
-  print("A total of ${diffs.length} diffs:");
-  for (Uri uri in diffs) {
-    print(" - $uri");
+  Future<helper.TestIncrementalCompiler> setup() async {
+    stopwatch.reset();
+    stopwatch.start();
+    Uri input = Platform.script.resolve("../../compiler/bin/dart2js.dart");
+    CompilerOptions options = helper.getOptions(targetName: "VM");
+    helper.TestIncrementalCompiler compiler =
+        new helper.TestIncrementalCompiler(options, input);
+    compiler.useExperimentalInvalidation = useExperimentalInvalidation;
+    Component c = await compiler.computeDelta();
+    print("Compiled dart2js to Component with ${c.libraries.length} libraries "
+        "in ${stopwatch.elapsedMilliseconds} ms.");
+    stopwatch.reset();
+    if (fast) {
+      libToData = {};
+      c.libraries.sort((l1, l2) {
+        return "${l1.fileUri}".compareTo("${l2.fileUri}");
+      });
+
+      c.problemsAsJson?.sort();
+
+      c.computeCanonicalNames();
+
+      for (Library library in c.libraries) {
+        library.additionalExports.sort((Reference r1, Reference r2) {
+          return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
+        });
+        library.problemsAsJson?.sort();
+
+        List<int> libSerialized =
+            serializeComponent(c, filter: (l) => l == library);
+        libToData[library.importUri] = libSerialized;
+      }
+    } else {
+      firstCompileData = util.postProcess(c);
+    }
+    print("Serialized in ${stopwatch.elapsedMilliseconds} ms");
+    stopwatch.reset();
+
+    uris = c.uriToSource.values
+        .map((s) => s != null ? s.importUri : null)
+        .where((u) => u != null && u.scheme != "dart")
+        .toSet()
+        .toList();
+
+    c = null;
+
+    return compiler;
   }
 
-  print("Done after ${uris.length} recompiles in "
-      "${stopwatch.elapsedMilliseconds} ms");
-}
-
-bool isEqual(List<int> a, List<int> b) {
-  int length = a.length;
-  if (b.length != length) {
-    return false;
-  }
-  for (int i = 0; i < length; ++i) {
-    if (a[i] != b[i]) {
+  bool isEqual(List<int> a, List<int> b) {
+    int length = a.length;
+    if (b.length != length) {
       return false;
     }
+    for (int i = 0; i < length; ++i) {
+      if (a[i] != b[i]) {
+        return false;
+      }
+    }
+    return true;
   }
-  return true;
 }
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 79b25aa..97a33b5 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -166,7 +166,7 @@
           "forceLateLoweringForTesting",
           "incrementalSerialization"
         ]);
-        await newWorldTest(
+        await new NewWorldTest().newWorldTest(
           data,
           context,
           map["worlds"],
@@ -317,519 +317,542 @@
   return moduleResult;
 }
 
-Future<Null> newWorldTest(
-    TestData data,
-    Context context,
-    List worlds,
-    Map modules,
-    bool omitPlatform,
-    String targetName,
-    bool forceLateLoweringForTesting,
-    bool incrementalSerialization) async {
-  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
-  final Uri base = Uri.parse("org-dartlang-test:///");
-  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
-  final Uri initializeFrom = base.resolve("initializeFrom.dill");
-  Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
-  final List<int> sdkSummaryData =
-      await new File.fromUri(platformUri).readAsBytes();
-
-  List<int> newestWholeComponentData;
+class NewWorldTest {
+  // These are fields in a class to make it easier to track down memory leaks
+  // via the leak detector test.
   Component newestWholeComponent;
-  MemoryFileSystem fs;
-  Map<String, String> sourceFiles;
-  CompilerOptions options;
-  TestIncrementalCompiler compiler;
-  IncrementalSerializer incrementalSerializer;
-
-  Map<String, List<int>> moduleData;
-  Map<String, Component> moduleComponents;
   Component sdk;
-  if (modules != null) {
-    moduleData = await createModules(
-        modules, sdkSummaryData, targetName, forceLateLoweringForTesting);
-    sdk = newestWholeComponent = new Component();
-    new BinaryBuilder(sdkSummaryData, filename: null, disableLazyReading: false)
-        .readComponent(newestWholeComponent);
-  }
+  Component component;
+  Component component2;
+  Component component3;
 
-  int worldNum = 0;
-  for (YamlMap world in worlds) {
-    worldNum++;
-    print("----------------");
-    print("World #$worldNum");
-    print("----------------");
-    List<Component> modulesToUse;
-    if (world["modules"] != null) {
-      moduleComponents ??= new Map<String, Component>();
+  Future<Null> newWorldTest(
+      TestData data,
+      Context context,
+      List worlds,
+      Map modules,
+      bool omitPlatform,
+      String targetName,
+      bool forceLateLoweringForTesting,
+      bool incrementalSerialization) async {
+    final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+    final Uri base = Uri.parse("org-dartlang-test:///");
+    final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+    final Uri initializeFrom = base.resolve("initializeFrom.dill");
+    Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
+    final List<int> sdkSummaryData =
+        await new File.fromUri(platformUri).readAsBytes();
 
-      sdk.adoptChildren();
-      for (Component c in moduleComponents.values) {
-        c.adoptChildren();
-      }
+    List<int> newestWholeComponentData;
+    MemoryFileSystem fs;
+    Map<String, String> sourceFiles;
+    CompilerOptions options;
+    TestIncrementalCompiler compiler;
+    IncrementalSerializer incrementalSerializer;
 
-      modulesToUse = new List<Component>();
-      for (String moduleName in world["modules"]) {
-        Component moduleComponent = moduleComponents[moduleName];
-        if (moduleComponent != null) {
-          modulesToUse.add(moduleComponent);
+    Map<String, List<int>> moduleData;
+    Map<String, Component> moduleComponents;
+
+    if (modules != null) {
+      moduleData = await createModules(
+          modules, sdkSummaryData, targetName, forceLateLoweringForTesting);
+      sdk = newestWholeComponent = new Component();
+      new BinaryBuilder(sdkSummaryData,
+              filename: null, disableLazyReading: false)
+          .readComponent(newestWholeComponent);
+    }
+
+    int worldNum = 0;
+    for (YamlMap world in worlds) {
+      worldNum++;
+      print("----------------");
+      print("World #$worldNum");
+      print("----------------");
+      List<Component> modulesToUse;
+      if (world["modules"] != null) {
+        moduleComponents ??= new Map<String, Component>();
+
+        sdk.adoptChildren();
+        for (Component c in moduleComponents.values) {
+          c.adoptChildren();
+        }
+
+        modulesToUse = new List<Component>();
+        for (String moduleName in world["modules"]) {
+          Component moduleComponent = moduleComponents[moduleName];
+          if (moduleComponent != null) {
+            modulesToUse.add(moduleComponent);
+          }
+        }
+        for (String moduleName in world["modules"]) {
+          Component moduleComponent = moduleComponents[moduleName];
+          if (moduleComponent == null) {
+            moduleComponent = new Component(nameRoot: sdk.root);
+            new BinaryBuilder(moduleData[moduleName],
+                    filename: null,
+                    disableLazyReading: false,
+                    alwaysCreateNewNamedNodes: true)
+                .readComponent(moduleComponent);
+            moduleComponents[moduleName] = moduleComponent;
+            modulesToUse.add(moduleComponent);
+          }
         }
       }
-      for (String moduleName in world["modules"]) {
-        Component moduleComponent = moduleComponents[moduleName];
-        if (moduleComponent == null) {
-          moduleComponent = new Component(nameRoot: sdk.root);
-          new BinaryBuilder(moduleData[moduleName],
-                  filename: null,
-                  disableLazyReading: false,
-                  alwaysCreateNewNamedNodes: true)
-              .readComponent(moduleComponent);
-          moduleComponents[moduleName] = moduleComponent;
-          modulesToUse.add(moduleComponent);
-        }
-      }
-    }
 
-    bool brandNewWorld = true;
-    if (world["worldType"] == "updated") {
-      brandNewWorld = false;
-    }
-    bool noFullComponent = false;
-    if (world["noFullComponent"] == true) {
-      noFullComponent = true;
-    }
+      bool brandNewWorld = true;
+      if (world["worldType"] == "updated") {
+        brandNewWorld = false;
+      }
+      bool noFullComponent = false;
+      if (world["noFullComponent"] == true) {
+        noFullComponent = true;
+      }
 
-    if (brandNewWorld) {
-      fs = new MemoryFileSystem(base);
-    }
-    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-    bool expectInitializeFromDill = false;
-    if (newestWholeComponentData != null &&
-        newestWholeComponentData.isNotEmpty) {
-      fs
-          .entityForUri(initializeFrom)
-          .writeAsBytesSync(newestWholeComponentData);
-      expectInitializeFromDill = true;
-    }
-    if (world["expectInitializeFromDill"] != null) {
-      expectInitializeFromDill = world["expectInitializeFromDill"];
-    }
-    if (brandNewWorld) {
-      sourceFiles = new Map<String, String>.from(world["sources"]);
-    } else {
-      sourceFiles.addAll(
-          new Map<String, String>.from(world["sources"] ?? <String, String>{}));
-    }
-    Uri packagesUri;
-    for (String filename in sourceFiles.keys) {
-      String data = sourceFiles[filename] ?? "";
-      Uri uri = base.resolve(filename);
-      if (filename == ".packages") {
-        packagesUri = uri;
+      if (brandNewWorld) {
+        fs = new MemoryFileSystem(base);
       }
-      fs.entityForUri(uri).writeAsStringSync(data);
-    }
-    if (world["dotPackagesFile"] != null) {
-      packagesUri = base.resolve(world["dotPackagesFile"]);
-    }
-
-    if (brandNewWorld) {
-      options = getOptions(
-          targetName: targetName,
-          forceLateLoweringForTesting: forceLateLoweringForTesting);
-      options.fileSystem = fs;
-      options.sdkRoot = null;
-      options.sdkSummary = sdkSummary;
-      options.omitPlatform = omitPlatform != false;
-      if (world["experiments"] != null) {
-        Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
-            parseExperimentalArguments([world["experiments"]]),
-            onError: (e) => throw "Error on parsing experiments flags: $e");
-        options.experimentalFlags = experimentalFlags;
+      fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
+      bool expectInitializeFromDill = false;
+      if (newestWholeComponentData != null &&
+          newestWholeComponentData.isNotEmpty) {
+        fs
+            .entityForUri(initializeFrom)
+            .writeAsBytesSync(newestWholeComponentData);
+        expectInitializeFromDill = true;
       }
-    }
-    if (packagesUri != null) {
-      options.packagesFileUri = packagesUri;
-    }
-    bool gotError = false;
-    final Set<String> formattedErrors = Set<String>();
-    bool gotWarning = false;
-    final Set<String> formattedWarnings = Set<String>();
-
-    options.onDiagnostic = (DiagnosticMessage message) {
-      String stringId = message.ansiFormatted.join("\n");
-      if (message is FormattedMessage) {
-        stringId = message.toJsonString();
-      } else if (message is DiagnosticMessageFromJson) {
-        stringId = message.toJsonString();
+      if (world["expectInitializeFromDill"] != null) {
+        expectInitializeFromDill = world["expectInitializeFromDill"];
       }
-      if (message.severity == Severity.error) {
-        gotError = true;
-        if (!formattedErrors.add(stringId)) {
-          Expect.fail("Got the same message twice: ${stringId}");
-        }
-      } else if (message.severity == Severity.warning) {
-        gotWarning = true;
-        if (!formattedWarnings.add(stringId)) {
-          Expect.fail("Got the same message twice: ${stringId}");
-        }
-      }
-    };
-
-    List<Uri> entries;
-    if (world["entry"] is String) {
-      entries = [base.resolve(world["entry"])];
-    } else {
-      entries = new List<Uri>();
-      List<dynamic> entryList = world["entry"];
-      for (String entry in entryList) {
-        entries.add(base.resolve(entry));
-      }
-    }
-    bool outlineOnly = world["outlineOnly"] == true;
-    bool skipOutlineBodyCheck = world["skipOutlineBodyCheck"] == true;
-    if (brandNewWorld) {
-      if (incrementalSerialization == true) {
-        incrementalSerializer = new IncrementalSerializer();
-      }
-      if (world["fromComponent"] == true) {
-        compiler = new TestIncrementalCompiler.fromComponent(
-            options,
-            entries.first,
-            (modulesToUse != null) ? sdk : newestWholeComponent,
-            outlineOnly,
-            incrementalSerializer);
+      if (brandNewWorld) {
+        sourceFiles = new Map<String, String>.from(world["sources"]);
       } else {
-        compiler = new TestIncrementalCompiler(options, entries.first,
-            initializeFrom, outlineOnly, incrementalSerializer);
+        sourceFiles.addAll(new Map<String, String>.from(
+            world["sources"] ?? <String, String>{}));
+      }
+      Uri packagesUri;
+      for (String filename in sourceFiles.keys) {
+        String data = sourceFiles[filename] ?? "";
+        Uri uri = base.resolve(filename);
+        if (filename == ".packages") {
+          packagesUri = uri;
+        }
+        fs.entityForUri(uri).writeAsStringSync(data);
+      }
+      if (world["dotPackagesFile"] != null) {
+        packagesUri = base.resolve(world["dotPackagesFile"]);
+      }
 
-        if (modulesToUse != null) {
-          throw "You probably shouldn't do this! "
-              "Any modules will have another sdk loaded!";
+      if (brandNewWorld) {
+        options = getOptions(
+            targetName: targetName,
+            forceLateLoweringForTesting: forceLateLoweringForTesting);
+        options.fileSystem = fs;
+        options.sdkRoot = null;
+        options.sdkSummary = sdkSummary;
+        options.omitPlatform = omitPlatform != false;
+        if (world["experiments"] != null) {
+          Map<ExperimentalFlag, bool> experimentalFlags =
+              parseExperimentalFlags(
+                  parseExperimentalArguments([world["experiments"]]),
+                  onError: (e) =>
+                      throw "Error on parsing experiments flags: $e");
+          options.experimentalFlags = experimentalFlags;
         }
       }
-    }
-
-    compiler.useExperimentalInvalidation = false;
-    if (world["useExperimentalInvalidation"] == true) {
-      compiler.useExperimentalInvalidation = true;
-    }
-
-    List<Uri> invalidated = new List<Uri>();
-    if (world["invalidate"] != null) {
-      for (String filename in world["invalidate"]) {
-        Uri uri = base.resolve(filename);
-        invalidated.add(uri);
-        compiler.invalidate(uri);
+      if (packagesUri != null) {
+        options.packagesFileUri = packagesUri;
       }
-    }
+      bool gotError = false;
+      final Set<String> formattedErrors = Set<String>();
+      bool gotWarning = false;
+      final Set<String> formattedWarnings = Set<String>();
 
-    if (modulesToUse != null) {
-      compiler.setModulesToLoadOnNextComputeDelta(modulesToUse);
-      compiler.invalidateAllSources();
-      compiler.trackNeededDillLibraries = true;
-    }
+      options.onDiagnostic = (DiagnosticMessage message) {
+        String stringId = message.ansiFormatted.join("\n");
+        if (message is FormattedMessage) {
+          stringId = message.toJsonString();
+        } else if (message is DiagnosticMessageFromJson) {
+          stringId = message.toJsonString();
+        }
+        if (message.severity == Severity.error) {
+          gotError = true;
+          if (!formattedErrors.add(stringId)) {
+            Expect.fail("Got the same message twice: ${stringId}");
+          }
+        } else if (message.severity == Severity.warning) {
+          gotWarning = true;
+          if (!formattedWarnings.add(stringId)) {
+            Expect.fail("Got the same message twice: ${stringId}");
+          }
+        }
+      };
 
-    Stopwatch stopwatch = new Stopwatch()..start();
-    Component component = await compiler.computeDelta(
-        entryPoints: entries,
-        fullComponent: brandNewWorld ? false : (noFullComponent ? false : true),
-        simulateTransformer: world["simulateTransformer"]);
-    if (outlineOnly && !skipOutlineBodyCheck) {
-      for (Library lib in component.libraries) {
-        for (Class c in lib.classes) {
-          for (Procedure p in c.procedures) {
+      List<Uri> entries;
+      if (world["entry"] is String) {
+        entries = [base.resolve(world["entry"])];
+      } else {
+        entries = new List<Uri>();
+        List<dynamic> entryList = world["entry"];
+        for (String entry in entryList) {
+          entries.add(base.resolve(entry));
+        }
+      }
+      bool outlineOnly = world["outlineOnly"] == true;
+      bool skipOutlineBodyCheck = world["skipOutlineBodyCheck"] == true;
+      if (brandNewWorld) {
+        if (incrementalSerialization == true) {
+          incrementalSerializer = new IncrementalSerializer();
+        }
+        if (world["fromComponent"] == true) {
+          compiler = new TestIncrementalCompiler.fromComponent(
+              options,
+              entries.first,
+              (modulesToUse != null) ? sdk : newestWholeComponent,
+              outlineOnly,
+              incrementalSerializer);
+        } else {
+          compiler = new TestIncrementalCompiler(options, entries.first,
+              initializeFrom, outlineOnly, incrementalSerializer);
+
+          if (modulesToUse != null) {
+            throw "You probably shouldn't do this! "
+                "Any modules will have another sdk loaded!";
+          }
+        }
+      }
+
+      compiler.useExperimentalInvalidation = false;
+      if (world["useExperimentalInvalidation"] == true) {
+        compiler.useExperimentalInvalidation = true;
+      }
+
+      List<Uri> invalidated = new List<Uri>();
+      if (world["invalidate"] != null) {
+        for (String filename in world["invalidate"]) {
+          Uri uri = base.resolve(filename);
+          invalidated.add(uri);
+          compiler.invalidate(uri);
+        }
+      }
+
+      if (modulesToUse != null) {
+        compiler.setModulesToLoadOnNextComputeDelta(modulesToUse);
+        compiler.invalidateAllSources();
+        compiler.trackNeededDillLibraries = true;
+      }
+
+      Stopwatch stopwatch = new Stopwatch()..start();
+      component = await compiler.computeDelta(
+          entryPoints: entries,
+          fullComponent:
+              brandNewWorld ? false : (noFullComponent ? false : true),
+          simulateTransformer: world["simulateTransformer"]);
+      if (outlineOnly && !skipOutlineBodyCheck) {
+        for (Library lib in component.libraries) {
+          for (Class c in lib.classes) {
+            for (Procedure p in c.procedures) {
+              if (p.function.body != null &&
+                  p.function.body is! EmptyStatement) {
+                throw "Got body (${p.function.body.runtimeType})";
+              }
+            }
+          }
+          for (Procedure p in lib.procedures) {
             if (p.function.body != null && p.function.body is! EmptyStatement) {
               throw "Got body (${p.function.body.runtimeType})";
             }
           }
         }
-        for (Procedure p in lib.procedures) {
-          if (p.function.body != null && p.function.body is! EmptyStatement) {
-            throw "Got body (${p.function.body.runtimeType})";
+      }
+      performErrorAndWarningCheck(
+          world, gotError, formattedErrors, gotWarning, formattedWarnings);
+      util.throwOnEmptyMixinBodies(component);
+      await util.throwOnInsufficientUriToSource(component,
+          fileSystem: gotError ? null : fs);
+      print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+
+      checkExpectedContent(world, component);
+      checkNeededDillLibraries(world, compiler.neededDillLibraries, base);
+
+      if (!noFullComponent) {
+        Set<Library> allLibraries = new Set<Library>();
+        for (Library lib in component.libraries) {
+          computeAllReachableLibrariesFor(lib, allLibraries);
+        }
+        if (allLibraries.length != component.libraries.length) {
+          Expect.fail("Expected for the reachable stuff to be equal to "
+              "${component.libraries} but it was $allLibraries");
+        }
+        Set<Library> tooMany = allLibraries.toSet()
+          ..removeAll(component.libraries);
+        if (tooMany.isNotEmpty) {
+          Expect.fail("Expected for the reachable stuff to be equal to "
+              "${component.libraries} but these were there too: $tooMany "
+              "(and others were missing)");
+        }
+      }
+
+      newestWholeComponentData = util.postProcess(component);
+      newestWholeComponent = component;
+      String actualSerialized = componentToStringSdkFiltered(component);
+      print("*****\n\ncomponent:\n"
+          "${actualSerialized}\n\n\n");
+
+      if (world["uriToSourcesDoesntInclude"] != null) {
+        for (String filename in world["uriToSourcesDoesntInclude"]) {
+          Uri uri = base.resolve(filename);
+          if (component.uriToSource[uri] != null) {
+            throw "Expected no uriToSource for $uri but found "
+                "${component.uriToSource[uri]}";
           }
         }
       }
-    }
-    performErrorAndWarningCheck(
-        world, gotError, formattedErrors, gotWarning, formattedWarnings);
-    util.throwOnEmptyMixinBodies(component);
-    await util.throwOnInsufficientUriToSource(component,
-        fileSystem: gotError ? null : fs);
-    print("Compile took ${stopwatch.elapsedMilliseconds} ms");
-
-    checkExpectedContent(world, component);
-    checkNeededDillLibraries(world, compiler.neededDillLibraries, base);
-
-    if (!noFullComponent) {
-      Set<Library> allLibraries = new Set<Library>();
-      for (Library lib in component.libraries) {
-        computeAllReachableLibrariesFor(lib, allLibraries);
-      }
-      if (allLibraries.length != component.libraries.length) {
-        Expect.fail("Expected for the reachable stuff to be equal to "
-            "${component.libraries} but it was $allLibraries");
-      }
-      Set<Library> tooMany = allLibraries.toSet()
-        ..removeAll(component.libraries);
-      if (tooMany.isNotEmpty) {
-        Expect.fail("Expected for the reachable stuff to be equal to "
-            "${component.libraries} but these were there too: $tooMany "
-            "(and others were missing)");
-      }
-    }
-
-    newestWholeComponentData = util.postProcess(component);
-    newestWholeComponent = component;
-    String actualSerialized = componentToStringSdkFiltered(component);
-    print("*****\n\ncomponent:\n"
-        "${actualSerialized}\n\n\n");
-
-    if (world["uriToSourcesDoesntInclude"] != null) {
-      for (String filename in world["uriToSourcesDoesntInclude"]) {
-        Uri uri = base.resolve(filename);
-        if (component.uriToSource[uri] != null) {
-          throw "Expected no uriToSource for $uri but found "
-              "${component.uriToSource[uri]}";
+      if (world["uriToSourcesOnlyIncludes"] != null) {
+        Set<Uri> allowed = {};
+        for (String filename in world["uriToSourcesOnlyIncludes"]) {
+          Uri uri = base.resolve(filename);
+          allowed.add(uri);
+        }
+        for (Uri uri in component.uriToSource.keys) {
+          // null is always there, so allow it implicitly.
+          // Dart scheme uris too.
+          if (uri == null || uri.scheme == "org-dartlang-sdk") continue;
+          if (!allowed.contains(uri)) {
+            throw "Expected no uriToSource for $uri but found "
+                "${component.uriToSource[uri]}";
+          }
         }
       }
-    }
-    if (world["uriToSourcesOnlyIncludes"] != null) {
-      Set<Uri> allowed = {};
-      for (String filename in world["uriToSourcesOnlyIncludes"]) {
-        Uri uri = base.resolve(filename);
-        allowed.add(uri);
-      }
-      for (Uri uri in component.uriToSource.keys) {
-        // null is always there, so allow it implicitly.
-        // Dart scheme uris too.
-        if (uri == null || uri.scheme == "org-dartlang-sdk") continue;
-        if (!allowed.contains(uri)) {
-          throw "Expected no uriToSource for $uri but found "
-              "${component.uriToSource[uri]}";
-        }
-      }
-    }
 
-    checkExpectFile(data, worldNum, context, actualSerialized);
-    checkClassHierarchy(compiler, component, data, worldNum, context);
+      checkExpectFile(data, worldNum, context, actualSerialized);
+      checkClassHierarchy(compiler, component, data, worldNum, context);
 
-    int nonSyntheticLibraries = countNonSyntheticLibraries(component);
-    int nonSyntheticPlatformLibraries =
-        countNonSyntheticPlatformLibraries(component);
-    int syntheticLibraries = countSyntheticLibraries(component);
-    if (world["expectsPlatform"] == true) {
-      if (nonSyntheticPlatformLibraries < 5) {
-        throw "Expected to have at least 5 platform libraries "
-            "(actually, the entire sdk), "
-            "but got $nonSyntheticPlatformLibraries.";
-      }
-    } else {
-      if (nonSyntheticPlatformLibraries != 0) {
-        throw "Expected to have 0 platform libraries "
-            "but got $nonSyntheticPlatformLibraries.";
-      }
-    }
-    if (world["expectedLibraryCount"] != null) {
-      if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
-          world["expectedLibraryCount"]) {
-        throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
-            "libraries, got "
-            "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
-            "(not counting platform libraries)";
-      }
-    }
-    if (world["expectedSyntheticLibraryCount"] != null) {
-      if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
-        throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
-            "libraries, got ${syntheticLibraries}";
-      }
-    }
-
-    if (world["expectsRebuildBodiesOnly"] != null) {
-      bool didRebuildBodiesOnly = compiler.rebuildBodiesCount > 0;
-      Expect.equals(world["expectsRebuildBodiesOnly"], didRebuildBodiesOnly,
-          "Whether we expected to rebuild bodies only.");
-    }
-
-    if (!noFullComponent) {
-      List<Library> entryLib = component.libraries
-          .where((Library lib) =>
-              entries.contains(lib.importUri) || entries.contains(lib.fileUri))
-          .toList();
-      if (entryLib.length != entries.length) {
-        throw "Expected the entries to become libraries. "
-            "Got ${entryLib.length} libraries for the expected "
-            "${entries.length} entries.";
-      }
-    }
-    if (compiler.initializedFromDill != expectInitializeFromDill) {
-      throw "Expected that initializedFromDill would be "
-          "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
-    }
-
-    if (incrementalSerialization == true && compiler.initializedFromDill) {
-      Expect.isTrue(compiler.initializedIncrementalSerializer);
-    } else {
-      Expect.isFalse(compiler.initializedIncrementalSerializer);
-    }
-
-    if (world["checkInvalidatedFiles"] != false) {
-      Set<Uri> filteredInvalidated =
-          compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
-      if (world["invalidate"] != null) {
-        Expect.equals(
-            world["invalidate"].length, filteredInvalidated?.length ?? 0);
-        List expectedInvalidatedUri = world["expectedInvalidatedUri"];
-        if (expectedInvalidatedUri != null) {
-          Expect.setEquals(expectedInvalidatedUri.map((s) => base.resolve(s)),
-              filteredInvalidated);
+      int nonSyntheticLibraries = countNonSyntheticLibraries(component);
+      int nonSyntheticPlatformLibraries =
+          countNonSyntheticPlatformLibraries(component);
+      int syntheticLibraries = countSyntheticLibraries(component);
+      if (world["expectsPlatform"] == true) {
+        if (nonSyntheticPlatformLibraries < 5) {
+          throw "Expected to have at least 5 platform libraries "
+              "(actually, the entire sdk), "
+              "but got $nonSyntheticPlatformLibraries.";
         }
       } else {
-        Expect.isNull(filteredInvalidated);
-        Expect.isNull(world["expectedInvalidatedUri"]);
-      }
-    }
-    List<int> incrementalSerializationBytes = checkIncrementalSerialization(
-        incrementalSerialization, component, incrementalSerializer, world);
-
-    Set<String> prevFormattedErrors = formattedErrors.toSet();
-    Set<String> prevFormattedWarnings = formattedWarnings.toSet();
-
-    clearPrevErrorsEtc() {
-      gotError = false;
-      formattedErrors.clear();
-      gotWarning = false;
-      formattedWarnings.clear();
-    }
-
-    if (!noFullComponent) {
-      clearPrevErrorsEtc();
-      Component component2 = await compiler.computeDelta(
-          entryPoints: entries,
-          fullComponent: true,
-          simulateTransformer: world["simulateTransformer"]);
-      performErrorAndWarningCheck(
-          world, gotError, formattedErrors, gotWarning, formattedWarnings);
-      List<int> thisWholeComponent = util.postProcess(component2);
-      print("*****\n\ncomponent2:\n"
-          "${componentToStringSdkFiltered(component2)}\n\n\n");
-      checkIsEqual(newestWholeComponentData, thisWholeComponent);
-      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
-          prevFormattedWarnings, formattedWarnings);
-
-      List<int> incrementalSerializationBytes2 = checkIncrementalSerialization(
-          incrementalSerialization, component2, incrementalSerializer, world);
-
-      if ((incrementalSerializationBytes == null &&
-              incrementalSerializationBytes2 != null) ||
-          (incrementalSerializationBytes != null &&
-              incrementalSerializationBytes2 == null)) {
-        throw "Incremental serialization gave results in one instance, "
-            "but not another.";
-      }
-
-      if (incrementalSerializationBytes != null) {
-        checkIsEqual(
-            incrementalSerializationBytes, incrementalSerializationBytes2);
-      }
-    }
-
-    if (world["expressionCompilation"] != null) {
-      List compilations;
-      if (world["expressionCompilation"] is List) {
-        compilations = world["expressionCompilation"];
-      } else {
-        compilations = [world["expressionCompilation"]];
-      }
-      for (Map compilation in compilations) {
-        clearPrevErrorsEtc();
-        bool expectErrors = compilation["errors"] ?? false;
-        bool expectWarnings = compilation["warnings"] ?? false;
-        Uri uri = base.resolve(compilation["uri"]);
-        String expression = compilation["expression"];
-        await compiler.compileExpression(expression, {}, [], "debugExpr", uri);
-        if (gotError && !expectErrors) {
-          throw "Got error(s) on expression compilation: ${formattedErrors}.";
-        } else if (!gotError && expectErrors) {
-          throw "Didn't get any errors.";
-        }
-        if (gotWarning && !expectWarnings) {
-          throw "Got warning(s) on expression compilation: "
-              "${formattedWarnings}.";
-        } else if (!gotWarning && expectWarnings) {
-          throw "Didn't get any warnings.";
+        if (nonSyntheticPlatformLibraries != 0) {
+          throw "Expected to have 0 platform libraries "
+              "but got $nonSyntheticPlatformLibraries.";
         }
       }
-    }
-
-    if (!noFullComponent && incrementalSerialization == true) {
-      // Do compile from scratch and compare.
-      clearPrevErrorsEtc();
-      TestIncrementalCompiler compilerFromScratch;
-
-      IncrementalSerializer incrementalSerializer2;
-      if (incrementalSerialization == true) {
-        incrementalSerializer2 = new IncrementalSerializer();
+      if (world["expectedLibraryCount"] != null) {
+        if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
+            world["expectedLibraryCount"]) {
+          throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
+              "libraries, got "
+              "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
+              "(not counting platform libraries)";
+        }
+      }
+      if (world["expectedSyntheticLibraryCount"] != null) {
+        if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
+          throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
+              "libraries, got ${syntheticLibraries}";
+        }
       }
 
-      if (world["fromComponent"] == true || modulesToUse != null) {
-        compilerFromScratch = new TestIncrementalCompiler.fromComponent(
-            options, entries.first, sdk, outlineOnly, incrementalSerializer2);
+      if (world["expectsRebuildBodiesOnly"] != null) {
+        bool didRebuildBodiesOnly = compiler.rebuildBodiesCount > 0;
+        Expect.equals(world["expectsRebuildBodiesOnly"], didRebuildBodiesOnly,
+            "Whether we expected to rebuild bodies only.");
+      }
+
+      if (!noFullComponent) {
+        List<Library> entryLib = component.libraries
+            .where((Library lib) =>
+                entries.contains(lib.importUri) ||
+                entries.contains(lib.fileUri))
+            .toList();
+        if (entryLib.length != entries.length) {
+          throw "Expected the entries to become libraries. "
+              "Got ${entryLib.length} libraries for the expected "
+              "${entries.length} entries.";
+        }
+      }
+      if (compiler.initializedFromDill != expectInitializeFromDill) {
+        throw "Expected that initializedFromDill would be "
+            "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
+      }
+
+      if (incrementalSerialization == true && compiler.initializedFromDill) {
+        Expect.isTrue(compiler.initializedIncrementalSerializer);
       } else {
-        compilerFromScratch = new TestIncrementalCompiler(
-            options, entries.first, null, outlineOnly, incrementalSerializer2);
+        Expect.isFalse(compiler.initializedIncrementalSerializer);
       }
 
-      if (modulesToUse != null) {
-        compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
-        compilerFromScratch.invalidateAllSources();
-        compilerFromScratch.trackNeededDillLibraries = true;
-      }
-
-      Stopwatch stopwatch = new Stopwatch()..start();
-      Component component3 = await compilerFromScratch.computeDelta(
-          entryPoints: entries,
-          simulateTransformer: world["simulateTransformer"]);
-      compilerFromScratch = null;
-      performErrorAndWarningCheck(
-          world, gotError, formattedErrors, gotWarning, formattedWarnings);
-      util.throwOnEmptyMixinBodies(component3);
-      await util.throwOnInsufficientUriToSource(component3);
-      print("Compile took ${stopwatch.elapsedMilliseconds} ms");
-
-      util.postProcess(component3);
-      print("*****\n\ncomponent3:\n"
-          "${componentToStringSdkFiltered(component3)}\n\n\n");
-      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
-          prevFormattedWarnings, formattedWarnings);
-
-      List<int> incrementalSerializationBytes3 = checkIncrementalSerialization(
-          incrementalSerialization, component3, incrementalSerializer2, world);
-
-      if ((incrementalSerializationBytes == null &&
-              incrementalSerializationBytes3 != null) ||
-          (incrementalSerializationBytes != null &&
-              incrementalSerializationBytes3 == null)) {
-        throw "Incremental serialization gave results in one instance, "
-            "but not another.";
-      }
-
-      if (incrementalSerializationBytes != null) {
-        if (world["brandNewIncrementalSerializationAllowDifferent"] == true) {
-          // Don't check for equality when we allow it to be different
-          // (e.g. when the old one contains more, and the new one doesn't).
+      if (world["checkInvalidatedFiles"] != false) {
+        Set<Uri> filteredInvalidated =
+            compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
+        if (world["invalidate"] != null) {
+          Expect.equals(
+              world["invalidate"].length, filteredInvalidated?.length ?? 0);
+          List expectedInvalidatedUri = world["expectedInvalidatedUri"];
+          if (expectedInvalidatedUri != null) {
+            Expect.setEquals(expectedInvalidatedUri.map((s) => base.resolve(s)),
+                filteredInvalidated);
+          }
         } else {
-          checkIsEqual(
-              incrementalSerializationBytes, incrementalSerializationBytes3);
+          Expect.isNull(filteredInvalidated);
+          Expect.isNull(world["expectedInvalidatedUri"]);
         }
-        newestWholeComponentData = incrementalSerializationBytes;
       }
-    }
+      List<int> incrementalSerializationBytes = checkIncrementalSerialization(
+          incrementalSerialization, component, incrementalSerializer, world);
 
-    if (context.breakBetween) {
-      debugger();
-      print("Continuing after debug break");
+      Set<String> prevFormattedErrors = formattedErrors.toSet();
+      Set<String> prevFormattedWarnings = formattedWarnings.toSet();
+
+      clearPrevErrorsEtc() {
+        gotError = false;
+        formattedErrors.clear();
+        gotWarning = false;
+        formattedWarnings.clear();
+      }
+
+      if (!noFullComponent) {
+        clearPrevErrorsEtc();
+        component2 = await compiler.computeDelta(
+            entryPoints: entries,
+            fullComponent: true,
+            simulateTransformer: world["simulateTransformer"]);
+        performErrorAndWarningCheck(
+            world, gotError, formattedErrors, gotWarning, formattedWarnings);
+        List<int> thisWholeComponent = util.postProcess(component2);
+        print("*****\n\ncomponent2:\n"
+            "${componentToStringSdkFiltered(component2)}\n\n\n");
+        checkIsEqual(newestWholeComponentData, thisWholeComponent);
+        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
+            prevFormattedWarnings, formattedWarnings);
+        newestWholeComponent = component2;
+
+        List<int> incrementalSerializationBytes2 =
+            checkIncrementalSerialization(incrementalSerialization, component2,
+                incrementalSerializer, world);
+
+        if ((incrementalSerializationBytes == null &&
+                incrementalSerializationBytes2 != null) ||
+            (incrementalSerializationBytes != null &&
+                incrementalSerializationBytes2 == null)) {
+          throw "Incremental serialization gave results in one instance, "
+              "but not another.";
+        }
+
+        if (incrementalSerializationBytes != null) {
+          checkIsEqual(
+              incrementalSerializationBytes, incrementalSerializationBytes2);
+        }
+      }
+
+      if (world["expressionCompilation"] != null) {
+        List compilations;
+        if (world["expressionCompilation"] is List) {
+          compilations = world["expressionCompilation"];
+        } else {
+          compilations = [world["expressionCompilation"]];
+        }
+        for (Map compilation in compilations) {
+          clearPrevErrorsEtc();
+          bool expectErrors = compilation["errors"] ?? false;
+          bool expectWarnings = compilation["warnings"] ?? false;
+          Uri uri = base.resolve(compilation["uri"]);
+          String expression = compilation["expression"];
+          await compiler.compileExpression(
+              expression, {}, [], "debugExpr", uri);
+          if (gotError && !expectErrors) {
+            throw "Got error(s) on expression compilation: ${formattedErrors}.";
+          } else if (!gotError && expectErrors) {
+            throw "Didn't get any errors.";
+          }
+          if (gotWarning && !expectWarnings) {
+            throw "Got warning(s) on expression compilation: "
+                "${formattedWarnings}.";
+          } else if (!gotWarning && expectWarnings) {
+            throw "Didn't get any warnings.";
+          }
+        }
+      }
+
+      if (!noFullComponent && incrementalSerialization == true) {
+        // Do compile from scratch and compare.
+        clearPrevErrorsEtc();
+        TestIncrementalCompiler compilerFromScratch;
+
+        IncrementalSerializer incrementalSerializer2;
+        if (incrementalSerialization == true) {
+          incrementalSerializer2 = new IncrementalSerializer();
+        }
+
+        if (world["fromComponent"] == true || modulesToUse != null) {
+          compilerFromScratch = new TestIncrementalCompiler.fromComponent(
+              options, entries.first, sdk, outlineOnly, incrementalSerializer2);
+        } else {
+          compilerFromScratch = new TestIncrementalCompiler(options,
+              entries.first, null, outlineOnly, incrementalSerializer2);
+        }
+
+        if (modulesToUse != null) {
+          compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
+          compilerFromScratch.invalidateAllSources();
+          compilerFromScratch.trackNeededDillLibraries = true;
+        }
+
+        Stopwatch stopwatch = new Stopwatch()..start();
+        component3 = await compilerFromScratch.computeDelta(
+            entryPoints: entries,
+            simulateTransformer: world["simulateTransformer"]);
+        compilerFromScratch = null;
+        performErrorAndWarningCheck(
+            world, gotError, formattedErrors, gotWarning, formattedWarnings);
+        util.throwOnEmptyMixinBodies(component3);
+        await util.throwOnInsufficientUriToSource(component3);
+        print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+
+        util.postProcess(component3);
+        print("*****\n\ncomponent3:\n"
+            "${componentToStringSdkFiltered(component3)}\n\n\n");
+        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
+            prevFormattedWarnings, formattedWarnings);
+
+        List<int> incrementalSerializationBytes3 =
+            checkIncrementalSerialization(incrementalSerialization, component3,
+                incrementalSerializer2, world);
+
+        if ((incrementalSerializationBytes == null &&
+                incrementalSerializationBytes3 != null) ||
+            (incrementalSerializationBytes != null &&
+                incrementalSerializationBytes3 == null)) {
+          throw "Incremental serialization gave results in one instance, "
+              "but not another.";
+        }
+
+        if (incrementalSerializationBytes != null) {
+          if (world["brandNewIncrementalSerializationAllowDifferent"] == true) {
+            // Don't check for equality when we allow it to be different
+            // (e.g. when the old one contains more, and the new one doesn't).
+          } else {
+            checkIsEqual(
+                incrementalSerializationBytes, incrementalSerializationBytes3);
+          }
+          newestWholeComponentData = incrementalSerializationBytes;
+        }
+      }
+
+      component = null;
+      component2 = null;
+      component3 = null;
+
+      if (context.breakBetween) {
+        debugger();
+        print("Continuing after debug break");
+      }
     }
   }
 }
@@ -1171,10 +1194,10 @@
       libContent.add("Class ${c.name}");
     }
     for (Procedure p in lib.procedures) {
-      libContent.add("Procedure ${p.name}");
+      libContent.add("Procedure ${p.name.name}");
     }
     for (Field f in lib.fields) {
-      libContent.add("Field ${f.name}");
+      libContent.add("Field ${f.name.name}");
     }
   }
   return actualContent;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 6dce68e..325d45ea 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -638,6 +638,7 @@
 nnbd
 node's
 nonimplementation
+norm
 normalization
 notifier
 notifying
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index f577286..2a58a94 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1028,6 +1028,7 @@
 exclamation
 exclude
 excluded
+excludes
 excluding
 exclusive
 executable
@@ -3150,6 +3151,7 @@
 visited
 visiting
 visitor
+visitor's
 visual
 vm
 void
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 8422fa5..59795b4 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -33,6 +33,7 @@
 authority
 auto
 autobianchi
+automatic
 b0x
 b1x
 b2x
@@ -121,6 +122,7 @@
 depended
 depfile
 desc
+detector
 deviation
 dfast
 dictionaries
@@ -137,6 +139,7 @@
 disconnect
 discovering
 dispatcher
+dispose
 dist
 doctype
 doesnt
@@ -184,9 +187,11 @@
 fisk
 five
 floor
+foos
 forbidden
 forces
 foreign
+forrest
 fox
 fulfill
 func
@@ -251,6 +256,7 @@
 lengths
 lightly
 likewise
+lily
 linebreaks
 lints
 linux
@@ -380,6 +386,7 @@
 splitting
 sqrt
 sssp
+stats
 std
 stdio
 strip
diff --git a/pkg/front_end/test/vm_service_for_leak_detection.dart b/pkg/front_end/test/vm_service_for_leak_detection.dart
index 7d3c6ba..040e1d5 100644
--- a/pkg/front_end/test/vm_service_for_leak_detection.dart
+++ b/pkg/front_end/test/vm_service_for_leak_detection.dart
@@ -26,11 +26,23 @@
             ["_extension"]),
         new helper.Interest(Uri.parse("package:kernel/ast.dart"), "Extension",
             ["name", "fileUri"]),
+        new helper.Interest(Uri.parse("package:kernel/ast.dart"), "Library",
+            ["fileUri", "_libraryIdString"]),
       ],
       true);
+
+  // heapHelper.start([
+  //   "--enable-asserts",
+  //   Platform.script.resolve("incremental_dart2js_tester.dart").toString(),
+  //   "--addDebugBreaks",
+  //   "--fast",
+  //   "--experimental",
+  // ]);
   heapHelper.start([
-    Platform.script.resolve("incremental_dart2js_tester.dart").toString(),
-    "--fast",
-    "--addDebugBreaks",
+    "--enable-asserts",
+    Platform.script.resolve("incremental_load_from_dill_suite.dart").toString(),
+    "-DaddDebugBreaks=true",
+    // "--",
+    // "incremental_load_from_dill/no_outline_change_...",
   ]);
 }
diff --git a/pkg/front_end/test/vm_service_heap_finder.dart b/pkg/front_end/test/vm_service_heap_finder.dart
new file mode 100644
index 0000000..f199b1e
--- /dev/null
+++ b/pkg/front_end/test/vm_service_heap_finder.dart
@@ -0,0 +1,40 @@
+import "dart:io";
+import "vm_service_heap_helper.dart";
+
+class Foo {
+  final String x;
+  final int y;
+
+  Foo(this.x, this.y);
+}
+
+main() async {
+  List<Foo> foos = [];
+  foos.add(new Foo("hello", 42));
+  foos.add(new Foo("world", 43));
+  foos.add(new Foo("!", 44));
+  String connectTo = ask("Connect to");
+  VMServiceHeapHelperBase vm = VMServiceHeapHelperBase();
+  await vm.connect(Uri.parse(connectTo));
+  String isolateId = await vm.getIsolateId();
+  String classToFind = ask("Find what class");
+  await vm.printAllocationProfile(isolateId, filter: classToFind);
+  String fieldToFilter = ask("Filter on what field");
+  Set<String> fieldValues = {};
+  while (true) {
+    String fieldValue = ask("Look for value in field (empty to stop)");
+    if (fieldValue == "") break;
+    fieldValues.add(fieldValue);
+  }
+
+  await vm.filterAndPrintInstances(
+      isolateId, classToFind, fieldToFilter, fieldValues);
+
+  await vm.disconnect();
+  print("Disconnect done!");
+}
+
+String ask(String question) {
+  stdout.write("$question: ");
+  return stdin.readLineSync();
+}
diff --git a/pkg/front_end/test/vm_service_heap_helper.dart b/pkg/front_end/test/vm_service_heap_helper.dart
index b4a80f1..e23bdbd 100644
--- a/pkg/front_end/test/vm_service_heap_helper.dart
+++ b/pkg/front_end/test/vm_service_heap_helper.dart
@@ -1,4 +1,5 @@
 import "dart:convert";
+import "dart:developer";
 import "dart:io";
 
 import "package:vm_service/vm_service.dart" as vmService;
@@ -6,230 +7,20 @@
 
 import "dijkstras_sssp_algorithm.dart";
 
-class VMServiceHeapHelper {
-  Process _process;
+class VMServiceHeapHelperBase {
   vmService.VmService _serviceClient;
-  bool _started = false;
-  final Map<Uri, Map<String, List<String>>> _interests =
-      new Map<Uri, Map<String, List<String>>>();
-  final Map<Uri, Map<String, List<String>>> _prettyPrints =
-      new Map<Uri, Map<String, List<String>>>();
-  final bool throwOnPossibleLeak;
 
-  VMServiceHeapHelper(List<Interest> interests, List<Interest> prettyPrints,
-      this.throwOnPossibleLeak) {
-    if (interests.isEmpty) throw "Empty list of interests given";
-    for (Interest interest in interests) {
-      Map<String, List<String>> classToFields = _interests[interest.uri];
-      if (classToFields == null) {
-        classToFields = Map<String, List<String>>();
-        _interests[interest.uri] = classToFields;
-      }
-      List<String> fields = classToFields[interest.className];
-      if (fields == null) {
-        fields = new List<String>();
-        classToFields[interest.className] = fields;
-      }
-      fields.addAll(interest.fieldNames);
-    }
-    for (Interest interest in prettyPrints) {
-      Map<String, List<String>> classToFields = _prettyPrints[interest.uri];
-      if (classToFields == null) {
-        classToFields = Map<String, List<String>>();
-        _prettyPrints[interest.uri] = classToFields;
-      }
-      List<String> fields = classToFields[interest.className];
-      if (fields == null) {
-        fields = new List<String>();
-        classToFields[interest.className] = fields;
-      }
-      fields.addAll(interest.fieldNames);
-    }
-  }
+  VMServiceHeapHelperBase();
 
-  void start(List<String> scriptAndArgs) async {
-    if (_started) throw "Already started";
-    _started = true;
-    _process = await Process.start(
-        Platform.resolvedExecutable,
-        ["--pause_isolates_on_start", "--enable-vm-service=0"]
-          ..addAll(scriptAndArgs));
-    _process.stdout
-        .transform(utf8.decoder)
-        .transform(new LineSplitter())
-        .listen((line) {
-      const kObservatoryListening = 'Observatory listening on ';
-      if (line.startsWith(kObservatoryListening)) {
-        Uri observatoryUri =
-            Uri.parse(line.substring(kObservatoryListening.length));
-        _gotObservatoryUri(observatoryUri);
-      }
-      stdout.writeln("> $line");
-    });
-    _process.stderr
-        .transform(utf8.decoder)
-        .transform(new LineSplitter())
-        .listen((line) {
-      stderr.writeln("> $line");
-    });
-  }
-
-  void _gotObservatoryUri(Uri observatoryUri) async {
+  Future connect(Uri observatoryUri) async {
     String wsUriString =
         'ws://${observatoryUri.authority}${observatoryUri.path}ws';
     _serviceClient = await vmService.vmServiceConnectUri(wsUriString,
         log: const StdOutLog());
-    await _run();
   }
 
-  void _run() async {
-    vmService.VM vm = await _serviceClient.getVM();
-    if (vm.isolates.length != 1) {
-      throw "Expected 1 isolate, got ${vm.isolates.length}";
-    }
-    vmService.IsolateRef isolateRef = vm.isolates.single;
-    await _forceGC(isolateRef.id);
-
-    assert(await _isPausedAtStart(isolateRef.id));
-    await _serviceClient.resume(isolateRef.id);
-
-    int iterationNumber = 1;
-    while (true) {
-      await _waitUntilPaused(isolateRef.id);
-      print("Iteration: #$iterationNumber");
-      iterationNumber++;
-      await _forceGC(isolateRef.id);
-
-      vmService.HeapSnapshotGraph heapSnapshotGraph =
-          await vmService.HeapSnapshotGraph.getSnapshot(
-              _serviceClient, isolateRef);
-      HeapGraph graph = convertHeapGraph(heapSnapshotGraph);
-
-      Set<String> seenPrints = {};
-      Set<String> duplicatePrints = {};
-      Map<String, List<HeapGraphElement>> groupedByToString = {};
-      for (HeapGraphClassActual c in graph.classes) {
-        Map<String, List<String>> interests = _interests[c.libraryUri];
-        if (interests != null && interests.isNotEmpty) {
-          List<String> fieldsToUse = interests[c.name];
-          if (fieldsToUse != null && fieldsToUse.isNotEmpty) {
-            for (HeapGraphElement instance in c.instances) {
-              StringBuffer sb = new StringBuffer();
-              sb.writeln("Instance: ${instance}");
-              if (instance is HeapGraphElementActual) {
-                for (String fieldName in fieldsToUse) {
-                  String prettyPrinted = instance
-                      .getField(fieldName)
-                      .getPrettyPrint(_prettyPrints);
-                  sb.writeln("  $fieldName: "
-                      "${prettyPrinted}");
-                }
-              }
-              String sbToString = sb.toString();
-              if (!seenPrints.add(sbToString)) {
-                duplicatePrints.add(sbToString);
-              }
-              groupedByToString[sbToString] ??= [];
-              groupedByToString[sbToString].add(instance);
-            }
-          }
-        }
-      }
-      if (duplicatePrints.isNotEmpty) {
-        print("======================================");
-        print("WARNING: Duplicated pretty prints of objects.");
-        print("This might be a memory leak!");
-        print("");
-        for (String s in duplicatePrints) {
-          int count = groupedByToString[s].length;
-          print("$s ($count)");
-          print("");
-        }
-        print("======================================");
-        for (String duplicateString in duplicatePrints) {
-          print("$duplicateString:");
-          List<HeapGraphElement> Function(HeapGraphElement target)
-              dijkstraTarget = dijkstra(graph.elements.first, graph);
-          for (HeapGraphElement duplicate
-              in groupedByToString[duplicateString]) {
-            print("${duplicate} pointed to from:");
-            List<HeapGraphElement> shortestPath = dijkstraTarget(duplicate);
-            for (int i = 0; i < shortestPath.length - 1; i++) {
-              HeapGraphElement thisOne = shortestPath[i];
-              HeapGraphElement nextOne = shortestPath[i + 1];
-              String indexFieldName;
-              if (thisOne is HeapGraphElementActual) {
-                HeapGraphClass c = thisOne.class_;
-                if (c is HeapGraphClassActual) {
-                  for (vmService.HeapSnapshotField field in c.origin.fields) {
-                    if (thisOne.references[field.index] == nextOne) {
-                      indexFieldName = field.name;
-                    }
-                  }
-                }
-              }
-              if (indexFieldName == null) {
-                indexFieldName = "no field found; index "
-                    "${thisOne.references.indexOf(nextOne)}";
-              }
-              print("  $thisOne -> $nextOne ($indexFieldName)");
-            }
-            print("---------------------------");
-          }
-        }
-
-        if (throwOnPossibleLeak) throw "Possible leak detected.";
-      }
-      await _serviceClient.resume(isolateRef.id);
-    }
-  }
-
-  List<HeapGraphElement> Function(HeapGraphElement target) dijkstra(
-      HeapGraphElement source, HeapGraph heapGraph) {
-    Map<HeapGraphElement, int> elementNum = {};
-    Map<HeapGraphElement, GraphNode<HeapGraphElement>> elements = {};
-    elements[heapGraph.elementSentinel] =
-        new GraphNode<HeapGraphElement>(heapGraph.elementSentinel);
-    elementNum[heapGraph.elementSentinel] = elements.length;
-    for (HeapGraphElementActual element in heapGraph.elements) {
-      elements[element] = new GraphNode<HeapGraphElement>(element);
-      elementNum[element] = elements.length;
-    }
-
-    for (HeapGraphElementActual element in heapGraph.elements) {
-      GraphNode<HeapGraphElement> node = elements[element];
-      for (HeapGraphElement out in element.references) {
-        node.addOutgoing(elements[out]);
-      }
-    }
-
-    DijkstrasAlgorithm<HeapGraphElement> result =
-        new DijkstrasAlgorithm<HeapGraphElement>(
-      elements.values,
-      elements[source],
-      (HeapGraphElement a, HeapGraphElement b) {
-        if (identical(a, b)) {
-          throw "Comparing two identical ones was unexpected";
-        }
-        return elementNum[a] - elementNum[b];
-      },
-      (HeapGraphElement a, HeapGraphElement b) {
-        if (identical(a, b)) return 0;
-        // Prefer not to go via sentinel and via "Context".
-        if (b is HeapGraphElementSentinel) return 100;
-        HeapGraphElementActual bb = b;
-        if (bb.class_ is HeapGraphClassSentinel) return 100;
-        HeapGraphClassActual c = bb.class_;
-        if (c.name == "Context") {
-          if (c.libraryUri.toString().isEmpty) return 100;
-        }
-        return 1;
-      },
-    );
-
-    return (HeapGraphElement target) {
-      return result.getPathFromTarget(elements[source], elements[target]);
-    };
+  Future disconnect() async {
+    await _serviceClient.dispose();
   }
 
   Future<void> _waitUntilPaused(String isolateId) async {
@@ -310,6 +101,329 @@
       }
     }
   }
+
+  Future<void> printAllocationProfile(String isolateId, {String filter}) async {
+    await _waitUntilIsolateIsRunnable(isolateId);
+    vmService.AllocationProfile allocationProfile =
+        await _serviceClient.getAllocationProfile(isolateId);
+    for (vmService.ClassHeapStats member in allocationProfile.members) {
+      if (filter != null) {
+        if (member.classRef.name != filter) continue;
+      } else {
+        if (member.classRef.name == "") continue;
+        if (member.instancesCurrent == 0) continue;
+      }
+      vmService.Class c =
+          await _serviceClient.getObject(isolateId, member.classRef.id);
+      if (c.location?.script?.uri == null) continue;
+      print("${member.classRef.name}: ${member.instancesCurrent}");
+    }
+  }
+
+  Future<void> filterAndPrintInstances(String isolateId, String filter,
+      String fieldName, Set<String> fieldValues) async {
+    await _waitUntilIsolateIsRunnable(isolateId);
+    vmService.AllocationProfile allocationProfile =
+        await _serviceClient.getAllocationProfile(isolateId);
+    for (vmService.ClassHeapStats member in allocationProfile.members) {
+      if (member.classRef.name != filter) continue;
+      vmService.Class c =
+          await _serviceClient.getObject(isolateId, member.classRef.id);
+      if (c.location?.script?.uri == null) continue;
+      print("${member.classRef.name}: ${member.instancesCurrent}");
+      print(c.location.script.uri);
+
+      vmService.InstanceSet instances = await _serviceClient.getInstances(
+          isolateId, member.classRef.id, 10000);
+      int instanceNum = 0;
+      for (vmService.ObjRef instance in instances.instances) {
+        instanceNum++;
+        var receivedObject =
+            await _serviceClient.getObject(isolateId, instance.id);
+        if (receivedObject is! vmService.Instance) continue;
+        vmService.Instance object = receivedObject;
+        for (vmService.BoundField field in object.fields) {
+          if (field.decl.name == fieldName) {
+            if (field.value is vmService.Sentinel) continue;
+            var receivedValue =
+                await _serviceClient.getObject(isolateId, field.value.id);
+            if (receivedValue is! vmService.Instance) continue;
+            String value = (receivedValue as vmService.Instance).valueAsString;
+            if (!fieldValues.contains(value)) continue;
+            print("${instanceNum}: ${field.decl.name}: "
+                "${value} --- ${instance.id}");
+          }
+        }
+      }
+    }
+    print("Done!");
+  }
+
+  Future<String> getIsolateId() async {
+    vmService.VM vm = await _serviceClient.getVM();
+    if (vm.isolates.length != 1) {
+      throw "Expected 1 isolate, got ${vm.isolates.length}";
+    }
+    vmService.IsolateRef isolateRef = vm.isolates.single;
+    return isolateRef.id;
+  }
+}
+
+class VMServiceHeapHelper extends VMServiceHeapHelperBase {
+  Process _process;
+
+  bool _started = false;
+  final Map<Uri, Map<String, List<String>>> _interests =
+      new Map<Uri, Map<String, List<String>>>();
+  final Map<Uri, Map<String, List<String>>> _prettyPrints =
+      new Map<Uri, Map<String, List<String>>>();
+  final bool throwOnPossibleLeak;
+
+  VMServiceHeapHelper(List<Interest> interests, List<Interest> prettyPrints,
+      this.throwOnPossibleLeak) {
+    if (interests.isEmpty) throw "Empty list of interests given";
+    for (Interest interest in interests) {
+      Map<String, List<String>> classToFields = _interests[interest.uri];
+      if (classToFields == null) {
+        classToFields = Map<String, List<String>>();
+        _interests[interest.uri] = classToFields;
+      }
+      List<String> fields = classToFields[interest.className];
+      if (fields == null) {
+        fields = new List<String>();
+        classToFields[interest.className] = fields;
+      }
+      fields.addAll(interest.fieldNames);
+    }
+    for (Interest interest in prettyPrints) {
+      Map<String, List<String>> classToFields = _prettyPrints[interest.uri];
+      if (classToFields == null) {
+        classToFields = Map<String, List<String>>();
+        _prettyPrints[interest.uri] = classToFields;
+      }
+      List<String> fields = classToFields[interest.className];
+      if (fields == null) {
+        fields = new List<String>();
+        classToFields[interest.className] = fields;
+      }
+      fields.addAll(interest.fieldNames);
+    }
+  }
+
+  void start(List<String> scriptAndArgs) async {
+    if (_started) throw "Already started";
+    _started = true;
+    _process = await Process.start(
+        Platform.resolvedExecutable,
+        ["--pause_isolates_on_start", "--enable-vm-service=0"]
+          ..addAll(scriptAndArgs));
+    _process.stdout
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((line) {
+      const kObservatoryListening = 'Observatory listening on ';
+      if (line.startsWith(kObservatoryListening)) {
+        Uri observatoryUri =
+            Uri.parse(line.substring(kObservatoryListening.length));
+        _setupAndRun(observatoryUri);
+      }
+      stdout.writeln("> $line");
+    });
+    _process.stderr
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((line) {
+      stderr.writeln("> $line");
+    });
+  }
+
+  void _setupAndRun(Uri observatoryUri) async {
+    await connect(observatoryUri);
+    await _run();
+  }
+
+  void _run() async {
+    vmService.VM vm = await _serviceClient.getVM();
+    if (vm.isolates.length != 1) {
+      throw "Expected 1 isolate, got ${vm.isolates.length}";
+    }
+    vmService.IsolateRef isolateRef = vm.isolates.single;
+    await _forceGC(isolateRef.id);
+
+    assert(await _isPausedAtStart(isolateRef.id));
+    await _serviceClient.resume(isolateRef.id);
+
+    int iterationNumber = 1;
+    while (true) {
+      await _waitUntilPaused(isolateRef.id);
+      print("Iteration: #$iterationNumber");
+      iterationNumber++;
+      await _forceGC(isolateRef.id);
+
+      vmService.HeapSnapshotGraph heapSnapshotGraph =
+          await vmService.HeapSnapshotGraph.getSnapshot(
+              _serviceClient, isolateRef);
+      HeapGraph graph = convertHeapGraph(heapSnapshotGraph);
+
+      Set<String> seenPrints = {};
+      Set<String> duplicatePrints = {};
+      Map<String, List<HeapGraphElement>> groupedByToString = {};
+      for (HeapGraphClassActual c in graph.classes) {
+        Map<String, List<String>> interests = _interests[c.libraryUri];
+        if (interests != null && interests.isNotEmpty) {
+          List<String> fieldsToUse = interests[c.name];
+          if (fieldsToUse != null && fieldsToUse.isNotEmpty) {
+            for (HeapGraphElement instance in c.instances) {
+              StringBuffer sb = new StringBuffer();
+              sb.writeln("Instance: ${instance}");
+              if (instance is HeapGraphElementActual) {
+                for (String fieldName in fieldsToUse) {
+                  String prettyPrinted = instance
+                      .getField(fieldName)
+                      .getPrettyPrint(_prettyPrints);
+                  sb.writeln("  $fieldName: "
+                      "${prettyPrinted}");
+                }
+              }
+              String sbToString = sb.toString();
+              if (!seenPrints.add(sbToString)) {
+                duplicatePrints.add(sbToString);
+              }
+              groupedByToString[sbToString] ??= [];
+              groupedByToString[sbToString].add(instance);
+            }
+          }
+        }
+      }
+      if (duplicatePrints.isNotEmpty) {
+        print("======================================");
+        print("WARNING: Duplicated pretty prints of objects.");
+        print("This might be a memory leak!");
+        print("");
+        for (String s in duplicatePrints) {
+          int count = groupedByToString[s].length;
+          print("$s ($count)");
+          print("");
+        }
+        print("======================================");
+        for (String duplicateString in duplicatePrints) {
+          print("$duplicateString:");
+          List<HeapGraphElement> Function(HeapGraphElement target)
+              dijkstraTarget = dijkstra(graph.elements.first, graph);
+          for (HeapGraphElement duplicate
+              in groupedByToString[duplicateString]) {
+            print("${duplicate} pointed to from:");
+            print(duplicate.getPrettyPrint(_prettyPrints));
+            List<HeapGraphElement> shortestPath = dijkstraTarget(duplicate);
+            for (int i = 0; i < shortestPath.length - 1; i++) {
+              HeapGraphElement thisOne = shortestPath[i];
+              HeapGraphElement nextOne = shortestPath[i + 1];
+              String indexFieldName;
+              if (thisOne is HeapGraphElementActual) {
+                HeapGraphClass c = thisOne.class_;
+                if (c is HeapGraphClassActual) {
+                  for (vmService.HeapSnapshotField field in c.origin.fields) {
+                    if (thisOne.references[field.index] == nextOne) {
+                      indexFieldName = field.name;
+                    }
+                  }
+                }
+              }
+              if (indexFieldName == null) {
+                indexFieldName = "no field found; index "
+                    "${thisOne.references.indexOf(nextOne)}";
+              }
+              print("  $thisOne -> $nextOne ($indexFieldName)");
+            }
+            print("---------------------------");
+          }
+        }
+
+        if (throwOnPossibleLeak) {
+          debugger();
+          throw "Possible leak detected.";
+        }
+      }
+      await _serviceClient.resume(isolateRef.id);
+    }
+  }
+
+  List<HeapGraphElement> Function(HeapGraphElement target) dijkstra(
+      HeapGraphElement source, HeapGraph heapGraph) {
+    Map<HeapGraphElement, int> elementNum = {};
+    Map<HeapGraphElement, GraphNode<HeapGraphElement>> elements = {};
+    elements[heapGraph.elementSentinel] =
+        new GraphNode<HeapGraphElement>(heapGraph.elementSentinel);
+    elementNum[heapGraph.elementSentinel] = elements.length;
+    for (HeapGraphElementActual element in heapGraph.elements) {
+      elements[element] = new GraphNode<HeapGraphElement>(element);
+      elementNum[element] = elements.length;
+    }
+
+    for (HeapGraphElementActual element in heapGraph.elements) {
+      GraphNode<HeapGraphElement> node = elements[element];
+      for (HeapGraphElement out in element.references) {
+        node.addOutgoing(elements[out]);
+      }
+    }
+
+    DijkstrasAlgorithm<HeapGraphElement> result =
+        new DijkstrasAlgorithm<HeapGraphElement>(
+      elements.values,
+      elements[source],
+      (HeapGraphElement a, HeapGraphElement b) {
+        if (identical(a, b)) {
+          throw "Comparing two identical ones was unexpected";
+        }
+        return elementNum[a] - elementNum[b];
+      },
+      (HeapGraphElement a, HeapGraphElement b) {
+        if (identical(a, b)) return 0;
+
+        // Prefer going via actual field.
+        if (a is HeapGraphElementActual) {
+          HeapGraphClass c = a.class_;
+          if (c is HeapGraphClassActual) {
+            for (vmService.HeapSnapshotField field in c.origin.fields) {
+              if (a.references[field.index] == b) {
+                // Via actual field!
+                return 1;
+              }
+            }
+          }
+        }
+
+        // Prefer not to go directly from HeapGraphClassSentinel to Procedure.
+        if (a is HeapGraphElementActual && b is HeapGraphElementActual) {
+          HeapGraphElementActual aa = a;
+          HeapGraphElementActual bb = b;
+          if (aa.class_ is HeapGraphClassSentinel &&
+              bb.class_ is HeapGraphClassActual) {
+            HeapGraphClassActual c = bb.class_;
+            if (c.name == "Procedure") {
+              return 1000;
+            }
+          }
+        }
+
+        // Prefer not to go via sentinel and via "Context".
+        if (b is HeapGraphElementSentinel) return 100;
+        HeapGraphElementActual bb = b;
+        if (bb.class_ is HeapGraphClassSentinel) return 100;
+        HeapGraphClassActual c = bb.class_;
+        if (c.name == "Context") {
+          if (c.libraryUri.toString().isEmpty) return 100;
+        }
+
+        // Not via actual field.
+        return 10;
+      },
+    );
+
+    return (HeapGraphElement target) {
+      return result.getPathFromTarget(elements[source], elements[target]);
+    };
+  }
 }
 
 class Interest {
@@ -412,7 +526,8 @@
           if (fields != null) {
             return "${c.name}[" +
                 fields.map((field) {
-                  return "$field: ${me.getField(field).getPrettyPrint(prettyPrints)}";
+                  return "$field: "
+                      "${me.getField(field).getPrettyPrint(prettyPrints)}";
                 }).join(", ") +
                 "]";
           }
diff --git a/pkg/front_end/testcases/expression/class_type_param_circular_reference.expression.yaml.expect b/pkg/front_end/testcases/expression/class_type_param_circular_reference.expression.yaml.expect
index e380b76..d107580 100644
--- a/pkg/front_end/testcases/expression/class_type_param_circular_reference.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/class_type_param_circular_reference.expression.yaml.expect
@@ -1,4 +1,4 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
-  return this.{dart.core::Object::toString}();
\ No newline at end of file
+  return this.{dart.core::Object::toString}();
diff --git a/pkg/front_end/testcases/extensions/operators.dart.outline.expect b/pkg/front_end/testcases/extensions/operators.dart.outline.expect
index ca95978..2d2d9be 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Complex extends core::Object {
+class Complex extends core::Object /*hasConstConstructor*/  {
   final field core::double* real;
   final field core::double* imaginary;
   const constructor •(core::double* real, core::double* imaginary) → self::Complex*
diff --git a/pkg/front_end/testcases/extensions/operators.dart.strong.expect b/pkg/front_end/testcases/extensions/operators.dart.strong.expect
index 4a46ae4..0371050 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.strong.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Complex extends core::Object {
+class Complex extends core::Object /*hasConstConstructor*/  {
   final field core::double* real;
   final field core::double* imaginary;
   const constructor •(core::double* real, core::double* imaginary) → self::Complex*
diff --git a/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
index 4a46ae4..0371050 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Complex extends core::Object {
+class Complex extends core::Object /*hasConstConstructor*/  {
   final field core::double* real;
   final field core::double* imaginary;
   const constructor •(core::double* real, core::double* imaginary) → self::Complex*
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
index 0d1797b..5d802a5 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
@@ -8,7 +8,7 @@
   method run() → void
     ;
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -25,7 +25,7 @@
   static method strongest(self::Strength* s1, self::Strength* s2) → self::Strength*
     ;
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
index 4c54d2f..3a9691a 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = const <self::Foo*>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.outline.expect b/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
index 5fc0262..62a6a88 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
@@ -6,7 +6,7 @@
 
 typedef F1 = () →* void;
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.strong.expect b/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.outline.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.outline.expect
index 368f1dd..86cd7ac 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({named: dynamic}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
index 50f5128..abc752f 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::F<self::F::T*>*
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Fc<self::Fc::T*>*
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Fi<self::Fi::T*>*
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     ;
 }
@@ -209,7 +209,7 @@
   synthetic constructor •() → self::G<self::G::T*>*
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     ;
 }
@@ -217,7 +217,7 @@
   synthetic constructor •() → self::Gc<self::Gc::T*>*
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     ;
 }
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
index 74cbe0c..c4ffb93 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index 84a6515..3dae0c6 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -170,22 +170,22 @@
     : super core::Object::•()
     ;
 }
-class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::E<self::E::T*>*
     : super core::Object::•()
     ;
 }
-class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ec<self::Ec::T*>*
     : super core::Object::•()
     ;
 }
-class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.outline.expect b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
index 511a3f4..8274b91 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   method foo() → void
     ;
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
index 98cc4a6..7bed644 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
index f56cb2a..6cd473f 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.outline.expect b/pkg/front_end/testcases/general/bug34511.dart.outline.expect
index cf7dcd3..494ce66 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.outline.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → self::A<self::A::X*>*
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.strong.expect b/pkg/front_end/testcases/general/bug34511.dart.strong.expect
index f743320..4de7d7e 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
index 534c2d3..ffac059 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
index 24bf6bc..7ee9fd9 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
@@ -111,7 +111,7 @@
   synthetic constructor •() → self::Am1<self::Am1::X*, self::Am1::Y*>*
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -120,7 +120,7 @@
   synthetic constructor •() → self::Bm1<self::Bm1::Z*>*
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -129,7 +129,7 @@
   synthetic constructor •() → self::Cm1<self::Cm1::Z*>*
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -138,7 +138,7 @@
   synthetic constructor •() → self::Dm1<self::Dm1::Z*>*
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -147,7 +147,7 @@
   synthetic constructor •() → self::Em1<self::Em1::Z*>*
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -156,7 +156,7 @@
   synthetic constructor •() → self::Fm1<self::Fm1::Z*>*
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -165,7 +165,7 @@
   synthetic constructor •() → self::Gm1<self::Gm1::Z*>*
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Hm1<self::Hm1::Z*>*
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::Im1<self::Im1::Z*>*
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Jm1<self::Jm1::Z*>*
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Km1<self::Km1::Z*>*
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -269,7 +269,7 @@
   synthetic constructor •() → self::Am2<self::Am2::X*, self::Am2::Y*>*
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -278,7 +278,7 @@
   synthetic constructor •() → self::Bm2<self::Bm2::Z*>*
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -287,7 +287,7 @@
   synthetic constructor •() → self::Cm2<self::Cm2::Z*>*
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -296,7 +296,7 @@
   synthetic constructor •() → self::Dm2<self::Dm2::Z*>*
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -305,7 +305,7 @@
   synthetic constructor •() → self::Em2<self::Em2::Z*>*
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -314,7 +314,7 @@
   synthetic constructor •() → self::Fm2<self::Fm2::Z*>*
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -323,7 +323,7 @@
   synthetic constructor •() → self::Gm2<self::Gm2::Z*>*
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
   synthetic constructor •() → self::Hm2<self::Hm2::Z*>*
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -341,7 +341,7 @@
   synthetic constructor •() → self::Im2<self::Im2::Z*>*
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -350,7 +350,7 @@
   synthetic constructor •() → self::Jm2<self::Jm2::Z*>*
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -359,7 +359,7 @@
   synthetic constructor •() → self::Km2<self::Km2::Z*>*
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -427,7 +427,7 @@
   synthetic constructor •() → self::Am3<self::Am3::L*, self::Am3::Y*>*
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -436,7 +436,7 @@
   synthetic constructor •() → self::Bm3<self::Bm3::Z*>*
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -445,7 +445,7 @@
   synthetic constructor •() → self::Cm3<self::Cm3::Z*>*
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -454,7 +454,7 @@
   synthetic constructor •() → self::Dm3<self::Dm3::Z*>*
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -463,7 +463,7 @@
   synthetic constructor •() → self::Em3<self::Em3::Z*>*
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
   synthetic constructor •() → self::Fm3<self::Fm3::Z*>*
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -481,7 +481,7 @@
   synthetic constructor •() → self::Gm3<self::Gm3::Z*>*
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -490,7 +490,7 @@
   synthetic constructor •() → self::Hm3<self::Hm3::Z*>*
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -499,7 +499,7 @@
   synthetic constructor •() → self::Im3<self::Im3::Z*>*
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -508,7 +508,7 @@
   synthetic constructor •() → self::Jm3<self::Jm3::Z*>*
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
index e2c3c3c..c287cae 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
index 4c9590f..071ec09 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.outline.expect b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.outline.expect
index fbca3b4..a68c8ab 100644
--- a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.outline.expect
+++ b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.outline.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.expect b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.expect
index 29828db..1b41001 100644
--- a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.expect
+++ b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.transformed.expect b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
index 29828db..1b41001 100644
--- a/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.outline.expect b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.outline.expect
index fdcd4b7..d28ec62 100644
--- a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.outline.expect
+++ b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.outline.expect
@@ -9,14 +9,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
index 3022157..12ac432 100644
--- a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
+++ b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
index 3022157..12ac432 100644
--- a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.outline.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.outline.expect
index 6cda74d..934d099 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
index d8dce84..f2001a3 100644
--- a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
@@ -20,7 +20,7 @@
   method foo(core::num* x) → void
     ;
 }
-abstract class _D&A&B = self::A with self::B {
+abstract class _D&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
index 08d745d..03d861d 100644
--- a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
+++ b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B = self::A with self::B {
+abstract class _D&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
index 24f8755..b35ef09 100644
--- a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B extends self::A implements self::B {
+abstract class _D&A&B extends self::A implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
index b190f3a..70afe00 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
@@ -359,7 +359,7 @@
   method m() → dynamic
     ;
 }
-class Enum#4 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#4*>* values = const <self::Enum#4*>[self::Enum#4::a];
@@ -370,7 +370,7 @@
   method toString() → core::String*
     return this.{=self::Enum#4::_name};
 }
-class Enum#3 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#3*>* values = const <self::Enum#3*>[self::Enum#3::a, self::Enum#3::b, self::Enum#3::c];
@@ -383,7 +383,7 @@
   method toString() → core::String*
     return this.{=self::Enum#3::_name};
 }
-class Enum#2 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#2*>* values = const <self::Enum#2*>[self::Enum#2::Enum, self::Enum#2::a, self::Enum#2::b];
@@ -396,7 +396,7 @@
   method toString() → core::String*
     return this.{=self::Enum#2::_name};
 }
-class Enum#1 extends core::Object {
+class Enum#1 extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#1*>* values = const <self::Enum#1*>[self::Enum#1::a, self::Enum#1::b, self::Enum#1::c];
@@ -409,7 +409,7 @@
   method toString() → core::String*
     return this.{=self::Enum#1::_name};
 }
-class Enum extends core::Object {
+class Enum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum*>* values = const <self::Enum*>[self::Enum::Enum, self::Enum::a, self::Enum::b];
@@ -422,7 +422,7 @@
   method toString() → core::String*
     return this.{=self::Enum::_name};
 }
-class AnotherEnum extends core::Object {
+class AnotherEnum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::AnotherEnum*>* values = const <self::AnotherEnum*>[self::AnotherEnum::a, self::AnotherEnum::b, self::AnotherEnum::c];
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
index 71677b2..888b9d8 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
@@ -421,7 +421,7 @@
   method m() → dynamic
     return super.m();
 }
-class Enum#4 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#4*>* values = #C4;
@@ -432,7 +432,7 @@
   method toString() → core::String*
     return this.{=self::Enum#4::_name};
 }
-class Enum#3 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#3*>* values = #C12;
@@ -445,7 +445,7 @@
   method toString() → core::String*
     return this.{=self::Enum#3::_name};
 }
-class Enum#2 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#2*>* values = #C17;
@@ -458,7 +458,7 @@
   method toString() → core::String*
     return this.{=self::Enum#2::_name};
 }
-class Enum#1 extends core::Object {
+class Enum#1 extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#1*>* values = #C21;
@@ -471,7 +471,7 @@
   method toString() → core::String*
     return this.{=self::Enum#1::_name};
 }
-class Enum extends core::Object {
+class Enum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum*>* values = #C25;
@@ -484,7 +484,7 @@
   method toString() → core::String*
     return this.{=self::Enum::_name};
 }
-class AnotherEnum extends core::Object {
+class AnotherEnum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::AnotherEnum*>* values = #C32;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.outline.expect
index 14fe62f..1e369ae 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.outline.expect
@@ -11,7 +11,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
index 3df9b64..082c2d4 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
index 3df9b64..082c2d4 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.outline.expect
index 25620a0..15ae178 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.outline.expect
@@ -12,7 +12,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
index efddc10..f617628 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
index efddc10..f617628 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.outline.expect
index e2689c9..8e00ee1 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.outline.expect
@@ -12,7 +12,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
index 4028b04..a926453 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
index 4028b04..a926453 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.outline.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.outline.expect
index 4034b8b..8406a72 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.outline.expect
@@ -11,7 +11,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -26,7 +26,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field self2::Foo* x;
   const constructor •() → self3::Bar*
     : self3::Bar::x = const self2::Foo::•(0), super core::Object::•()
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
index ac754c7..0b9da71 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
index ac754c7..0b9da71 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general/extend_with_type_variable.dart.outline.expect b/pkg/front_end/testcases/general/extend_with_type_variable.dart.outline.expect
index c76d701..ac516b1 100644
--- a/pkg/front_end/testcases/general/extend_with_type_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/general/extend_with_type_variable.dart.outline.expect
@@ -21,9 +21,9 @@
   synthetic constructor •() → self::SuperClass*
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     ;
 }
@@ -31,7 +31,7 @@
   synthetic constructor •() → self::Class1<self::Class1::T*, self::Class1::S*>*
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.expect b/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.expect
index bc9f1ea..fc89e52 100644
--- a/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.transformed.expect
index e38b62f..c3f0a09 100644
--- a/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/extend_with_type_variable.dart.strong.transformed.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general/ignore_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general/ignore_function.dart.strong.transformed.expect
new file mode 100644
index 0000000..b549c23
--- /dev/null
+++ b/pkg/front_end/testcases/general/ignore_function.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/ignore_function.dart:14:15: Error: Can't infer a type for 'other' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   operator ==(other) => false;
+//               ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:core" as core;
+
+class A extends core::Object implements core::Function {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(dynamic other) → core::bool*
+    return false;
+}
+class B extends core::Object implements self::Function {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  operator ==(invalid-type other) → core::bool*
+    return false;
+}
+class Function extends core::Object {
+  synthetic constructor •() → self::Function*
+    : super core::Object::•()
+    ;
+  operator ==(core::Object* other) → core::bool*
+    return false;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.outline.expect b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.outline.expect
index 55f17dd..503d2ef 100644
--- a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = 87;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.expect b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.transformed.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/implicit_const_with_static_fields.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart b/pkg/front_end/testcases/general/infer_field_from_multiple.dart
new file mode 100644
index 0000000..d3ce0ae
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart
@@ -0,0 +1,127 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 field1 = 0;
+  var field2 = 0;
+  var field3 = 0;
+  var field4 = 0;
+  int field5;
+  int field6;
+  int field7;
+  int field8;
+  var field9;
+  T field10;
+  T field11;
+  T field12;
+  T field13;
+  T field14;
+  var field15 = 0;
+  int field16;
+  var field17 = 0;
+  int field18;
+}
+
+class B<T, S> {
+  var field1 = 1;
+  var field2 = '';
+  var field3 = 1;
+  var field4 = '';
+  int field5;
+  String field6;
+  int field7;
+  String field8;
+  var field9;
+  T field10;
+  S field11;
+  T field12;
+  T field13;
+  S field14;
+  int field15;
+  var field16 = 0;
+  String field17;
+  var field18 = '';
+}
+
+class C implements A<int>, B<int, String> {
+  var field1;
+  var field2; // error
+  var field3 = 0;
+  var field4 = 0; // error
+  var field5;
+  var field6; // error
+  var field7 = 0;
+  var field8 = 0; // error
+  var field9;
+  var field10;
+  var field11; // error
+  int field12;
+  var field13 = 0;
+  int field14; // error
+  var field15;
+  var field16;
+  var field17; // error
+  var field18; // error
+
+  C(
+      this.field1,
+      this.field2,
+      this.field3,
+      this.field4,
+      this.field5,
+      this.field6,
+      this.field7,
+      this.field8,
+      this.field9,
+      this.field10,
+      this.field11,
+      this.field12,
+      this.field13,
+      this.field14,
+      this.field15,
+      this.field16,
+      this.field17,
+      this.field18);
+}
+
+class D<T> implements A<T>, B<T, T> {
+  var field1;
+  var field2; // error
+  var field3 = 0;
+  var field4 = 0; // error
+  var field5;
+  var field6; // error
+  var field7 = 0;
+  var field8 = 0; // error
+  var field9;
+  var field10;
+  var field11;
+  T field12;
+  var field13 = null;
+  T field14;
+  var field15;
+  var field16;
+  var field17; // error
+  var field18; // error
+
+  D(
+      this.field1,
+      this.field2,
+      this.field3,
+      this.field4,
+      this.field5,
+      this.field6,
+      this.field7,
+      this.field8,
+      this.field9,
+      this.field10,
+      this.field11,
+      this.field12,
+      this.field13,
+      this.field14,
+      this.field15,
+      this.field16,
+      this.field17,
+      this.field18);
+}
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
new file mode 100644
index 0000000..39e2871
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
@@ -0,0 +1,175 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field11; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field6; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field8 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field6; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field8 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The return type of the method 'C.field14' is 'int', which does not match the return type, 'String', of the overridden method, 'B.field14'.
+// Change to a subtype of 'String'.
+//   int field14; // error
+//       ^
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:40:5: Context: This is the overridden method ('field14').
+//   S field14;
+//     ^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The field 'C.field14' has type 'int', which does not match the corresponding type, 'String', in the overridden setter, 'B.field14'.
+//   int field14; // error
+//       ^
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:40:5: Context: This is the overridden method ('field14').
+//   S field14;
+//     ^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  field core::int* field1;
+  field core::int* field2;
+  field core::int* field3;
+  field core::int* field4;
+  field core::int* field5;
+  field core::int* field6;
+  field core::int* field7;
+  field core::int* field8;
+  field dynamic field9;
+  generic-covariant-impl field self::A::T* field10;
+  generic-covariant-impl field self::A::T* field11;
+  generic-covariant-impl field self::A::T* field12;
+  generic-covariant-impl field self::A::T* field13;
+  generic-covariant-impl field self::A::T* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field core::int* field17;
+  field core::int* field18;
+  synthetic constructor •() → self::A<self::A::T*>*
+    ;
+}
+class B<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
+  field core::int* field1;
+  field core::String* field2;
+  field core::int* field3;
+  field core::String* field4;
+  field core::int* field5;
+  field core::String* field6;
+  field core::int* field7;
+  field core::String* field8;
+  field dynamic field9;
+  generic-covariant-impl field self::B::T* field10;
+  generic-covariant-impl field self::B::S* field11;
+  generic-covariant-impl field self::B::T* field12;
+  generic-covariant-impl field self::B::T* field13;
+  generic-covariant-impl field self::B::S* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field core::String* field17;
+  field core::String* field18;
+  synthetic constructor •() → self::B<self::B::T*, self::B::S*>*
+    ;
+}
+class C extends core::Object implements self::A<core::int*>, self::B<core::int*, core::String*> {
+  field core::int* field1;
+  field invalid-type field2;
+  field core::int* field3;
+  field invalid-type field4;
+  field core::int* field5;
+  field invalid-type field6;
+  field core::int* field7;
+  field invalid-type field8;
+  field dynamic field9;
+  generic-covariant-impl field core::int* field10;
+  generic-covariant-impl field invalid-type field11;
+  generic-covariant-impl field core::int* field12;
+  generic-covariant-impl field core::int* field13;
+  generic-covariant-impl field core::int* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field invalid-type field17;
+  field invalid-type field18;
+  constructor •(core::int* field1, invalid-type field2, core::int* field3, invalid-type field4, core::int* field5, invalid-type field6, core::int* field7, invalid-type field8, dynamic field9, core::int* field10, invalid-type field11, core::int* field12, core::int* field13, core::int* field14, core::int* field15, core::int* field16, invalid-type field17, invalid-type field18) → self::C*
+    ;
+}
+class D<T extends core::Object* = dynamic> extends core::Object implements self::A<self::D::T*>, self::B<self::D::T*, self::D::T*> {
+  field core::int* field1;
+  field invalid-type field2;
+  field core::int* field3;
+  field invalid-type field4;
+  field core::int* field5;
+  field invalid-type field6;
+  field core::int* field7;
+  field invalid-type field8;
+  field dynamic field9;
+  generic-covariant-impl field self::D::T* field10;
+  generic-covariant-impl field self::D::T* field11;
+  generic-covariant-impl field self::D::T* field12;
+  generic-covariant-impl field self::D::T* field13;
+  generic-covariant-impl field self::D::T* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field invalid-type field17;
+  field invalid-type field18;
+  constructor •(core::int* field1, invalid-type field2, core::int* field3, invalid-type field4, core::int* field5, invalid-type field6, core::int* field7, invalid-type field8, dynamic field9, self::D::T* field10, self::D::T* field11, self::D::T* field12, self::D::T* field13, self::D::T* field14, core::int* field15, core::int* field16, invalid-type field17, invalid-type field18) → self::D<self::D::T*>*
+    ;
+}
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
new file mode 100644
index 0000000..bf8a5eb
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
@@ -0,0 +1,179 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field11; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field6; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field8 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field6; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field8 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The return type of the method 'C.field14' is 'int', which does not match the return type, 'String', of the overridden method, 'B.field14'.
+// Change to a subtype of 'String'.
+//   int field14; // error
+//       ^
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:40:5: Context: This is the overridden method ('field14').
+//   S field14;
+//     ^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The field 'C.field14' has type 'int', which does not match the corresponding type, 'String', in the overridden setter, 'B.field14'.
+//   int field14; // error
+//       ^
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:40:5: Context: This is the overridden method ('field14').
+//   S field14;
+//     ^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  field core::int* field1 = 0;
+  field core::int* field2 = 0;
+  field core::int* field3 = 0;
+  field core::int* field4 = 0;
+  field core::int* field5 = null;
+  field core::int* field6 = null;
+  field core::int* field7 = null;
+  field core::int* field8 = null;
+  field dynamic field9 = null;
+  generic-covariant-impl field self::A::T* field10 = null;
+  generic-covariant-impl field self::A::T* field11 = null;
+  generic-covariant-impl field self::A::T* field12 = null;
+  generic-covariant-impl field self::A::T* field13 = null;
+  generic-covariant-impl field self::A::T* field14 = null;
+  field core::int* field15 = 0;
+  field core::int* field16 = null;
+  field core::int* field17 = 0;
+  field core::int* field18 = null;
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class B<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
+  field core::int* field1 = 1;
+  field core::String* field2 = "";
+  field core::int* field3 = 1;
+  field core::String* field4 = "";
+  field core::int* field5 = null;
+  field core::String* field6 = null;
+  field core::int* field7 = null;
+  field core::String* field8 = null;
+  field dynamic field9 = null;
+  generic-covariant-impl field self::B::T* field10 = null;
+  generic-covariant-impl field self::B::S* field11 = null;
+  generic-covariant-impl field self::B::T* field12 = null;
+  generic-covariant-impl field self::B::T* field13 = null;
+  generic-covariant-impl field self::B::S* field14 = null;
+  field core::int* field15 = null;
+  field core::int* field16 = 0;
+  field core::String* field17 = null;
+  field core::String* field18 = "";
+  synthetic constructor •() → self::B<self::B::T*, self::B::S*>*
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::A<core::int*>, self::B<core::int*, core::String*> {
+  field core::int* field1;
+  field invalid-type field2;
+  field core::int* field3 = 0;
+  field invalid-type field4 = 0 as{TypeError} invalid-type;
+  field core::int* field5;
+  field invalid-type field6;
+  field core::int* field7 = 0;
+  field invalid-type field8 = 0 as{TypeError} invalid-type;
+  field dynamic field9;
+  generic-covariant-impl field core::int* field10;
+  generic-covariant-impl field invalid-type field11;
+  generic-covariant-impl field core::int* field12;
+  generic-covariant-impl field core::int* field13 = 0;
+  generic-covariant-impl field core::int* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field invalid-type field17;
+  field invalid-type field18;
+  constructor •(core::int* field1, invalid-type field2, core::int* field3, invalid-type field4, core::int* field5, invalid-type field6, core::int* field7, invalid-type field8, dynamic field9, core::int* field10, invalid-type field11, core::int* field12, core::int* field13, core::int* field14, core::int* field15, core::int* field16, invalid-type field17, invalid-type field18) → self::C*
+    : self::C::field1 = field1, self::C::field2 = field2, self::C::field3 = field3, self::C::field4 = field4, self::C::field5 = field5, self::C::field6 = field6, self::C::field7 = field7, self::C::field8 = field8, self::C::field9 = field9, self::C::field10 = field10, self::C::field11 = field11, self::C::field12 = field12, self::C::field13 = field13, self::C::field14 = field14, self::C::field15 = field15, self::C::field16 = field16, self::C::field17 = field17, self::C::field18 = field18, super core::Object::•()
+    ;
+}
+class D<T extends core::Object* = dynamic> extends core::Object implements self::A<self::D::T*>, self::B<self::D::T*, self::D::T*> {
+  field core::int* field1;
+  field invalid-type field2;
+  field core::int* field3 = 0;
+  field invalid-type field4 = 0 as{TypeError} invalid-type;
+  field core::int* field5;
+  field invalid-type field6;
+  field core::int* field7 = 0;
+  field invalid-type field8 = 0 as{TypeError} invalid-type;
+  field dynamic field9;
+  generic-covariant-impl field self::D::T* field10;
+  generic-covariant-impl field self::D::T* field11;
+  generic-covariant-impl field self::D::T* field12;
+  generic-covariant-impl field self::D::T* field13 = null;
+  generic-covariant-impl field self::D::T* field14;
+  field core::int* field15;
+  field core::int* field16;
+  field invalid-type field17;
+  field invalid-type field18;
+  constructor •(core::int* field1, invalid-type field2, core::int* field3, invalid-type field4, core::int* field5, invalid-type field6, core::int* field7, invalid-type field8, dynamic field9, self::D::T* field10, self::D::T* field11, self::D::T* field12, self::D::T* field13, self::D::T* field14, core::int* field15, core::int* field16, invalid-type field17, invalid-type field18) → self::D<self::D::T*>*
+    : self::D::field1 = field1, self::D::field2 = field2, self::D::field3 = field3, self::D::field4 = field4, self::D::field5 = field5, self::D::field6 = field6, self::D::field7 = field7, self::D::field8 = field8, self::D::field9 = field9, self::D::field10 = field10, self::D::field11 = field11, self::D::field12 = field12, self::D::field13 = field13, self::D::field14 = field14, self::D::field15 = field15, self::D::field16 = field16, self::D::field17 = field17, self::D::field18 = field18, super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue37776.dart.outline.expect b/pkg/front_end/testcases/general/issue37776.dart.outline.expect
index bb2fbfa..a055aeb 100644
--- a/pkg/front_end/testcases/general/issue37776.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue37776.dart.outline.expect
@@ -12,12 +12,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue37776.dart.strong.expect b/pkg/front_end/testcases/general/issue37776.dart.strong.expect
index 481a71d..f0888c6 100644
--- a/pkg/front_end/testcases/general/issue37776.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue37776.dart.strong.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue37776.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue37776.dart.strong.transformed.expect
index 481a71d..f0888c6 100644
--- a/pkg/front_end/testcases/general/issue37776.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue37776.dart.strong.transformed.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue38944.dart.outline.expect b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
index a4f2168..4c9456c 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
@@ -13,7 +13,7 @@
   synthetic constructor •() → self::A<self::A::Q*>*
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
index 06fa503..d6a3d0a 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
index 06fa503..d6a3d0a 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue40428.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue40428.dart.strong.transformed.expect
index 11cf476..bbfe989 100644
--- a/pkg/front_end/testcases/general/issue40428.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40428.dart.strong.transformed.expect
@@ -30,12 +30,12 @@
     : super core::Object::•()
     ;
 }
-class NamedMixin1 extends self::SuperClass1 implements self::Mixin {
+class NamedMixin1 extends self::SuperClass1 implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •(core::String* value) → self::NamedMixin1*
     : super self::SuperClass1::•(value)
     ;
 }
-class NamedMixin2 extends self::SuperClass2 implements self::Mixin {
+class NamedMixin2 extends self::SuperClass2 implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •(core::String* i) → self::NamedMixin2*
     : super self::SuperClass2::•(i)
     ;
diff --git a/pkg/front_end/testcases/general/magic_const.dart.outline.expect b/pkg/front_end/testcases/general/magic_const.dart.outline.expect
index 02428e5..9eab40c 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.outline.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
index 7f979c6..d37f679 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
index 7f979c6..d37f679 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/many_errors.dart.outline.expect b/pkg/front_end/testcases/general/many_errors.dart.outline.expect
index 8485710..09f5a30 100644
--- a/pkg/front_end/testcases/general/many_errors.dart.outline.expect
+++ b/pkg/front_end/testcases/general/many_errors.dart.outline.expect
@@ -30,7 +30,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     ;
@@ -50,7 +50,7 @@
   synthetic constructor •() → self::C*
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/many_errors.dart.strong.expect b/pkg/front_end/testcases/general/many_errors.dart.strong.expect
index 0f7aef3..7dd3401 100644
--- a/pkg/front_end/testcases/general/many_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/general/many_errors.dart.strong.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/many_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/general/many_errors.dart.strong.transformed.expect
index 0f7aef3..7dd3401 100644
--- a/pkg/front_end/testcases/general/many_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/many_errors.dart.strong.transformed.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/many_errors.dart:8:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
index 7c3363e..8944460 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @self::a
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = const <self::E*>[self::E::E1, self::E::E2, self::E::E3];
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.strong.transformed.expect b/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.strong.transformed.expect
index 5cd5635..1b24fb6 100644
--- a/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class C extends self::D implements self::E {
+class C extends self::D implements self::E /*isEliminatedMixin*/  {
   synthetic constructor •() → self::C*
     : super self::D::•()
     ;
diff --git a/pkg/front_end/testcases/general/missing_constructor.dart.outline.expect b/pkg/front_end/testcases/general/missing_constructor.dart.outline.expect
index 4436b0d..a50e142 100644
--- a/pkg/front_end/testcases/general/missing_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/general/missing_constructor.dart.outline.expect
@@ -22,7 +22,7 @@
   synthetic constructor •() → self::M*
     ;
 }
-abstract class _MixinApplication&Super&M = self::Super with self::M {
+abstract class _MixinApplication&Super&M = self::Super with self::M /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general/missing_constructor.dart.strong.expect b/pkg/front_end/testcases/general/missing_constructor.dart.strong.expect
index 7d2527a..1cadfea 100644
--- a/pkg/front_end/testcases/general/missing_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/general/missing_constructor.dart.strong.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M = self::Super with self::M {
+abstract class _MixinApplication&Super&M = self::Super with self::M /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general/missing_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/general/missing_constructor.dart.strong.transformed.expect
index 756b1cf..b77e9a0 100644
--- a/pkg/front_end/testcases/general/missing_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/missing_constructor.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M extends self::Super implements self::M {
+abstract class _MixinApplication&Super&M extends self::Super implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general/mixin.dart.outline.expect b/pkg/front_end/testcases/general/mixin.dart.outline.expect
index a53c688..9a57e29 100644
--- a/pkg/front_end/testcases/general/mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.outline.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -28,12 +28,12 @@
   method m() → dynamic
     ;
 }
-abstract class _C&Object&M1 = core::Object with self::M1 {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -48,7 +48,7 @@
   method m() → dynamic
     ;
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.expect b/pkg/front_end/testcases/general/mixin.dart.strong.expect
index 4873d85..2cca9cf 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
index b36e425..b51ef02 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
index 44d03d0..baf01a7 100644
--- a/pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     : self::Super::field = field, super core::Object::•()
     ;
 }
-class Class extends self::Super implements self::Mixin {
+class Class extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •(core::int* field) → self::Class*
     : super self::Super::•(field)
     ;
diff --git a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
index 5454a33..00b6b5b 100644
--- a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
@@ -155,7 +155,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A1&S&M1 = self::S with self::M1 {
+abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
     : super self::S::•()
     ;
@@ -166,12 +166,12 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A2&S&M1 = self::S with self::M1 {
+abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 {
+abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1&M2*
     : super self::_A2&S&M1::•()
     ;
@@ -182,7 +182,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A0X&S&M = self::S with self::M {
+abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
@@ -193,12 +193,12 @@
     : super self::_A0X&S&M::•()
     ;
 }
-abstract class _A1X&S&M1 = self::S with self::M1 {
+abstract class _A1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M {
+abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
@@ -209,17 +209,17 @@
     : super self::_A1X&S&M1&M::•()
     ;
 }
-abstract class _A2X&S&M1 = self::S with self::M1 {
+abstract class _A2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 {
+abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2*
     : super self::_A2X&S&M1::•()
     ;
 }
-abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M {
+abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
@@ -230,7 +230,7 @@
     : super self::_A2X&S&M1&M2&M::•()
     ;
 }
-abstract class _B0&S&M = self::S with self::M {
+abstract class _B0&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
@@ -240,12 +240,12 @@
   synthetic constructor •() → self::B0*
     ;
 }
-abstract class _B1&S&M1 = self::S with self::M1 {
+abstract class _B1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M {
+abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
@@ -255,17 +255,17 @@
   synthetic constructor •() → self::B1*
     ;
 }
-abstract class _B2&S&M1 = self::S with self::M1 {
+abstract class _B2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 {
+abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2*
     : super self::_B2&S&M1::•()
     ;
 }
-abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M {
+abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
@@ -275,13 +275,13 @@
   synthetic constructor •() → self::B2*
     ;
 }
-abstract class _B0X&S&M = self::S with self::M {
+abstract class _B0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
+abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
     : super self::_B0X&S&M::•()
     ;
@@ -290,18 +290,18 @@
   synthetic constructor •() → self::B0X*
     ;
 }
-abstract class _B1X&S&M1 = self::S with self::M1 {
+abstract class _B1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M {
+abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
+abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
     : super self::_B1X&S&M1&M::•()
     ;
@@ -310,23 +310,23 @@
   synthetic constructor •() → self::B1X*
     ;
 }
-abstract class _B2X&S&M1 = self::S with self::M1 {
+abstract class _B2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 {
+abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2*
     : super self::_B2X&S&M1::•()
     ;
 }
-abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M {
+abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
+abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
     : super self::_B2X&S&M1&M2&M::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect b/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
index d304cbd..fca000ef 100644
--- a/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
@@ -158,7 +158,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A1&S&M1 = self::S with self::M1 {
+abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
     : super self::S::•()
     ;
@@ -169,12 +169,12 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A2&S&M1 = self::S with self::M1 {
+abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 {
+abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1&M2*
     : super self::_A2&S&M1::•()
     ;
@@ -185,7 +185,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A0X&S&M = self::S with self::M {
+abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
@@ -196,12 +196,12 @@
     : super self::_A0X&S&M::•()
     ;
 }
-abstract class _A1X&S&M1 = self::S with self::M1 {
+abstract class _A1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M {
+abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
@@ -212,17 +212,17 @@
     : super self::_A1X&S&M1&M::•()
     ;
 }
-abstract class _A2X&S&M1 = self::S with self::M1 {
+abstract class _A2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 {
+abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2*
     : super self::_A2X&S&M1::•()
     ;
 }
-abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M {
+abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
@@ -233,7 +233,7 @@
     : super self::_A2X&S&M1&M2&M::•()
     ;
 }
-abstract class _B0&S&M = self::S with self::M {
+abstract class _B0&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
@@ -244,12 +244,12 @@
     : super self::_B0&S&M::•()
     ;
 }
-abstract class _B1&S&M1 = self::S with self::M1 {
+abstract class _B1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M {
+abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
@@ -260,17 +260,17 @@
     : super self::_B1&S&M1&M::•()
     ;
 }
-abstract class _B2&S&M1 = self::S with self::M1 {
+abstract class _B2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 {
+abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2*
     : super self::_B2&S&M1::•()
     ;
 }
-abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M {
+abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
@@ -281,13 +281,13 @@
     : super self::_B2&S&M1&M2&M::•()
     ;
 }
-abstract class _B0X&S&M = self::S with self::M {
+abstract class _B0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
+abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
     : super self::_B0X&S&M::•()
     ;
@@ -297,18 +297,18 @@
     : super self::_B0X&S&M&MX::•()
     ;
 }
-abstract class _B1X&S&M1 = self::S with self::M1 {
+abstract class _B1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M {
+abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
+abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
     : super self::_B1X&S&M1&M::•()
     ;
@@ -318,23 +318,23 @@
     : super self::_B1X&S&M1&M&MX::•()
     ;
 }
-abstract class _B2X&S&M1 = self::S with self::M1 {
+abstract class _B2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 {
+abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2*
     : super self::_B2X&S&M1::•()
     ;
 }
-abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M {
+abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
+abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
     : super self::_B2X&S&M1&M2&M::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
index f5bee66..87dfa06 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
@@ -44,7 +44,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -69,7 +69,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -78,7 +78,7 @@
   synthetic constructor •() → self::C2*
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
index b4e3d5a..73140d2 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
@@ -44,7 +44,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -70,7 +70,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
index dcb89f0..52ec3ad 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M {
+class N extends core::Object implements self::M /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.outline.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.outline.expect
index 7c8f4ee..9c0a4ed 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.outline.expect
@@ -22,7 +22,7 @@
   synthetic constructor •() → self::E*
     ;
 }
-abstract class _F&C&M = self::C<core::int*> with self::M {
+abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •({dynamic a, dynamic b}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
index 7998fd7..153bb13 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M = self::C<core::int*> with self::M {
+abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
index 05cc2ce..b2dbf88 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     : super core::Object::•()
     ;
 }
-class D extends self::C<core::String*> implements self::M {
+class D extends self::C<core::String*> implements self::M /*isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C2}) → self::D*
     : super self::C::•(a: a, b: b)
     ;
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M extends self::C<core::int*> implements self::M {
+abstract class _F&C&M extends self::C<core::int*> implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
index 5d68397..3b41508 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
@@ -17,7 +17,7 @@
   synthetic constructor •() → self::D*
     ;
 }
-abstract class _Foo&Object&C = core::Object with self::C<self::B*> {
+abstract class _Foo&Object&C = core::Object with self::C<self::B*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
index 9081947..467b3b5 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C = core::Object with self::C<self::B*> {
+abstract class _Foo&Object&C = core::Object with self::C<self::B*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
index 8d92589..6b9150f 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> {
+abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> /*isAnonymousMixin,isEliminatedMixin*/  {
   generic-covariant-impl field self::B* _field = null;
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
index 7e6110b..13e9d25 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
@@ -19,12 +19,12 @@
   synthetic constructor •() → self::S*
     ;
 }
-abstract class _Named&S&M = self::S with self::M {
+abstract class _Named&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N = self::_Named&S&M with self::N {
+abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
index 1dc8051..085e258 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
@@ -23,12 +23,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M = self::S with self::M {
+abstract class _Named&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N = self::_Named&S&M with self::N {
+abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
index 14cb42d..ad78013 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
@@ -23,13 +23,13 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M extends self::S implements self::M {
+abstract class _Named&S&M extends self::S implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N extends self::_Named&S&M implements self::N {
+abstract class _Named&S&M&N extends self::_Named&S&M implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
@@ -39,7 +39,7 @@
   get superM() → dynamic
     return super.{self::M::m};
 }
-class Named extends self::_Named&S&M&N implements self::M {
+class Named extends self::_Named&S&M&N implements self::M /*isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
diff --git a/pkg/front_end/testcases/general/mixin_with_static_member.dart.outline.expect b/pkg/front_end/testcases/general/mixin_with_static_member.dart.outline.expect
index c82f01d..f982247 100644
--- a/pkg/front_end/testcases/general/mixin_with_static_member.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_with_static_member.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M = self::B with self::M {
+abstract class _A&B&M = self::B with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.expect b/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.expect
index a6968d3..85e498d 100644
--- a/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M = self::B with self::M {
+abstract class _A&B&M = self::B with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.transformed.expect
index a732858..b9faaa3 100644
--- a/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_with_static_member.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M extends self::B implements self::M {
+abstract class _A&B&M extends self::B implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
index 536cae1..f42f11f 100644
--- a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
+++ b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.expect b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.expect
+++ b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.transformed.expect b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.transformed.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/qualified.dart.outline.expect b/pkg/front_end/testcases/general/qualified.dart.outline.expect
index c8750b5..8e9513f 100644
--- a/pkg/front_end/testcases/general/qualified.dart.outline.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.outline.expect
@@ -34,7 +34,7 @@
   static factory WrongName() → self::Bad*
     ;
 }
-abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general/qualified.dart.strong.expect b/pkg/front_end/testcases/general/qualified.dart.strong.expect
index 5b18e11..d55988f 100644
--- a/pkg/front_end/testcases/general/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.strong.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
index f45751f..21eaf08 100644
--- a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
index c9e154b..f5c4fb6 100644
--- a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
@@ -62,7 +62,7 @@
     : super core::Object::•()
     ;
 }
-class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> {
+class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Mix<self::Mix::M*>*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
index 2d13710..3ed80bf 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
index 87fc76e..397a76d 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
index 0394311..2b04ded 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let<BottomType> #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
index 4118194..b15ac8d 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
@@ -4,7 +4,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -12,7 +12,7 @@
   static factory •() → self::A*
     let dynamic #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
index a87fba5..81c22f9 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let dynamic #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
index d6f34c9..8c2291d 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let<BottomType> #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
index 2b697f3..9c617a6 100644
--- a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect
index 422552b..545b639 100644
--- a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect
index 422552b..545b639 100644
--- a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.outline.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.outline.expect
index 6de5e4c..4f01970 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.outline.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
index 71db16b..8b71195 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
index 71db16b..8b71195 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.outline.expect
index 0d1797b..5d802a5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.outline.expect
@@ -8,7 +8,7 @@
   method run() → void
     ;
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -25,7 +25,7 @@
   static method strongest(self::Strength* s1, self::Strength* s2) → self::Strength*
     ;
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.transformed.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
index 2a91755..2b67a8a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
     self::projectionTest(100);
   }
 }
-class Strength extends core::Object {
+class Strength extends core::Object /*hasConstConstructor*/  {
   final field core::int* value;
   final field core::String* name;
   const constructor •(core::int* value, core::String* name) → self::Strength*
@@ -32,7 +32,7 @@
     return self::Strength::stronger(s1, s2) ?{self::Strength*} s1 : s2;
   }
 }
-abstract class Constraint extends core::Object {
+abstract class Constraint extends core::Object /*hasConstConstructor*/  {
   final field self::Strength* strength;
   const constructor •(self::Strength* strength) → self::Constraint*
     : self::Constraint::strength = strength, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.outline.expect
index 4c54d2f..3a9691a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.outline.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = const <self::Foo*>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.transformed.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
index b030b8a..ad232a9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Fisk<T extends core::Object* = dynamic> extends core::Object {
+class Fisk<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::Fisk::T* x;
   const constructor fisk(self::Fisk::T* x) → self::Fisk<self::Fisk::T*>*
     : self::Fisk::x = x, super core::Object::•()
     ;
 }
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C10;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.outline.expect
index 5fc0262..62a6a88 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.outline.expect
@@ -6,7 +6,7 @@
 
 typedef F1 = () →* void;
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.transformed.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
index 6f2d3774..29c9cb7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
 @#C1
 @#C2
 typedef F2 = () →* void;
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* value) → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.outline.expect
index 368f1dd..86cd7ac 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({named: dynamic}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.transformed.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
index 023576c..7a689b8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef hest_t = ({@#C1 dynamic named}) →* dynamic;
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
index 6dcbef2..193fcfd 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::F<self::F::T*>*
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Fc<self::Fc::T*>*
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Fi<self::Fi::T*>*
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     ;
 }
@@ -209,7 +209,7 @@
   synthetic constructor •() → self::G<self::G::T*>*
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     ;
 }
@@ -217,7 +217,7 @@
   synthetic constructor •() → self::Gc<self::Gc::T*>*
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     ;
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
index d928707..f823e7b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index cf7a1fe..7ca9c2a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -170,22 +170,22 @@
     : super core::Object::•()
     ;
 }
-class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::E<self::E::T*>*
     : super core::Object::•()
     ;
 }
-class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ec<self::Ec::T*>*
     : super core::Object::•()
     ;
 }
-class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
index d928707..f823e7b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> = core::Object with self::Empty /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
index cf7a1fe..7ca9c2a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
@@ -170,22 +170,22 @@
     : super core::Object::•()
     ;
 }
-class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class E<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::E<self::E::T*>*
     : super core::Object::•()
     ;
 }
-class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ec<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ec<self::Ec::T*>*
     : super core::Object::•()
     ;
 }
-class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+class Ei<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -215,7 +215,7 @@
     : super self::_Fi&Object&A::•()
     ;
 }
-abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _G&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -225,7 +225,7 @@
     : super self::_G&A&Empty::•()
     ;
 }
-abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gc&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T*>*
     : super core::Object::•()
     ;
@@ -235,7 +235,7 @@
     : super self::_Gc&A&Empty::•()
     ;
 }
-abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty {
+abstract class _Gi&A&Empty<T extends core::Object* = dynamic> extends core::Object implements self::Empty /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
index 511a3f4..8274b91 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   method foo() → void
     ;
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
index 98cc4a6..7bed644 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
index f56cb2a..6cd473f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
index 98cc4a6..7bed644 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
index f56cb2a..6cd473f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 import "dart:mirrors";
 
-class _FailingTest extends core::Object {
+class _FailingTest extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_FailingTest*
     : super core::Object::•()
     ;
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
index cf7dcd3..494ce66 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → self::A<self::A::X*>*
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
index f743320..4de7d7e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
index 534c2d3..ffac059 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
index f743320..4de7d7e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
index 534c2d3..ffac059 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
index 4c7789d..e4929d5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
@@ -111,7 +111,7 @@
   synthetic constructor •() → self::Am1<self::Am1::X*, self::Am1::Y*>*
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -120,7 +120,7 @@
   synthetic constructor •() → self::Bm1<self::Bm1::Z*>*
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -129,7 +129,7 @@
   synthetic constructor •() → self::Cm1<self::Cm1::Z*>*
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -138,7 +138,7 @@
   synthetic constructor •() → self::Dm1<self::Dm1::Z*>*
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -147,7 +147,7 @@
   synthetic constructor •() → self::Em1<self::Em1::Z*>*
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -156,7 +156,7 @@
   synthetic constructor •() → self::Fm1<self::Fm1::Z*>*
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -165,7 +165,7 @@
   synthetic constructor •() → self::Gm1<self::Gm1::Z*>*
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Hm1<self::Hm1::Z*>*
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::Im1<self::Im1::Z*>*
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Jm1<self::Jm1::Z*>*
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Km1<self::Km1::Z*>*
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -269,7 +269,7 @@
   synthetic constructor •() → self::Am2<self::Am2::X*, self::Am2::Y*>*
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -278,7 +278,7 @@
   synthetic constructor •() → self::Bm2<self::Bm2::Z*>*
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -287,7 +287,7 @@
   synthetic constructor •() → self::Cm2<self::Cm2::Z*>*
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -296,7 +296,7 @@
   synthetic constructor •() → self::Dm2<self::Dm2::Z*>*
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -305,7 +305,7 @@
   synthetic constructor •() → self::Em2<self::Em2::Z*>*
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -314,7 +314,7 @@
   synthetic constructor •() → self::Fm2<self::Fm2::Z*>*
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -323,7 +323,7 @@
   synthetic constructor •() → self::Gm2<self::Gm2::Z*>*
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
   synthetic constructor •() → self::Hm2<self::Hm2::Z*>*
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -341,7 +341,7 @@
   synthetic constructor •() → self::Im2<self::Im2::Z*>*
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -350,7 +350,7 @@
   synthetic constructor •() → self::Jm2<self::Jm2::Z*>*
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -359,7 +359,7 @@
   synthetic constructor •() → self::Km2<self::Km2::Z*>*
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -427,7 +427,7 @@
   synthetic constructor •() → self::Am3<self::Am3::L*, self::Am3::Y*>*
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -436,7 +436,7 @@
   synthetic constructor •() → self::Bm3<self::Bm3::Z*>*
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -445,7 +445,7 @@
   synthetic constructor •() → self::Cm3<self::Cm3::Z*>*
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -454,7 +454,7 @@
   synthetic constructor •() → self::Dm3<self::Dm3::Z*>*
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -463,7 +463,7 @@
   synthetic constructor •() → self::Em3<self::Em3::Z*>*
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
   synthetic constructor •() → self::Fm3<self::Fm3::Z*>*
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -481,7 +481,7 @@
   synthetic constructor •() → self::Gm3<self::Gm3::Z*>*
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -490,7 +490,7 @@
   synthetic constructor •() → self::Hm3<self::Hm3::Z*>*
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -499,7 +499,7 @@
   synthetic constructor •() → self::Im3<self::Im3::Z*>*
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -508,7 +508,7 @@
   synthetic constructor •() → self::Jm3<self::Jm3::Z*>*
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
index 08e48db..1d8753e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
index e8aa8a5..cae8d00 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
index 08e48db..1d8753e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
index e8aa8a5..cae8d00 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.outline.expect
index b358ba8..464c765 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.outline.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.expect
index 3ce1d82..04ddb74 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
index 3ce1d82..04ddb74 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.expect
index 3ce1d82..04ddb74 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.transformed.expect
index 3ce1d82..04ddb74 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/co19_language_metadata_syntax_t04.dart.weak.transformed.expect
@@ -16,7 +16,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.outline.expect
index 77754c2..aef74b2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.outline.expect
@@ -9,14 +9,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.expect
index b4fdfe8..13e8324 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.transformed.expect
index b4fdfe8..13e8324 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.strong.transformed.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
index b4fdfe8..13e8324 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
index b4fdfe8..13e8324 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
@@ -13,14 +13,14 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : this self::A::bad()
     ;
   constructor bad() → self::A*
     : super core::Object::•() {}
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : super self::A::bad()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.outline.expect
index 6cda74d..934d099 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.transformed.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
index c95b9b2..1179768 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class _Y<T extends core::Object* = dynamic> extends core::Object {
+class _Y<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.outline.expect
index d71903c..a5ac2794 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.outline.expect
@@ -13,5 +13,5 @@
 static method main() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.expect
index 0de8c13..554df33 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.expect
@@ -33,5 +33,5 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.transformed.expect
index 0de8c13..554df33 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.strong.transformed.expect
@@ -33,5 +33,5 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.expect
index 0de8c13..554df33 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.expect
@@ -33,5 +33,5 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.transformed.expect
index 0de8c13..554df33 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/continue_inference_after_error.dart.weak.transformed.expect
@@ -33,5 +33,5 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
index d8dce84..f2001a3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
@@ -20,7 +20,7 @@
   method foo(core::num* x) → void
     ;
 }
-abstract class _D&A&B = self::A with self::B {
+abstract class _D&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
index 08d745d..03d861d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B = self::A with self::B {
+abstract class _D&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
index 24f8755..b35ef09 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B extends self::A implements self::B {
+abstract class _D&A&B extends self::A implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
index 08d745d..03d861d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B = self::A with self::B {
+abstract class _D&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.transformed.expect
index 24f8755..b35ef09 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.transformed.expect
@@ -20,7 +20,7 @@
     ;
   method foo(core::num* x) → void {}
 }
-abstract class _D&A&B extends self::A implements self::B {
+abstract class _D&A&B extends self::A implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_D&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.outline.expect
index 274daea..7865d47 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.outline.expect
@@ -359,7 +359,7 @@
   method m() → dynamic
     ;
 }
-class Enum#4 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#4*>* values = const <self::Enum#4*>[self::Enum#4::a];
@@ -370,7 +370,7 @@
   method toString() → core::String*
     return this.{=self::Enum#4::_name};
 }
-class Enum#3 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#3*>* values = const <self::Enum#3*>[self::Enum#3::a, self::Enum#3::b, self::Enum#3::c];
@@ -383,7 +383,7 @@
   method toString() → core::String*
     return this.{=self::Enum#3::_name};
 }
-class Enum#2 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#2*>* values = const <self::Enum#2*>[self::Enum#2::Enum, self::Enum#2::a, self::Enum#2::b];
@@ -396,7 +396,7 @@
   method toString() → core::String*
     return this.{=self::Enum#2::_name};
 }
-class Enum#1 extends core::Object {
+class Enum#1 extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#1*>* values = const <self::Enum#1*>[self::Enum#1::a, self::Enum#1::b, self::Enum#1::c];
@@ -409,7 +409,7 @@
   method toString() → core::String*
     return this.{=self::Enum#1::_name};
 }
-class Enum extends core::Object {
+class Enum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum*>* values = const <self::Enum*>[self::Enum::Enum, self::Enum::a, self::Enum::b];
@@ -422,7 +422,7 @@
   method toString() → core::String*
     return this.{=self::Enum::_name};
 }
-class AnotherEnum extends core::Object {
+class AnotherEnum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::AnotherEnum*>* values = const <self::AnotherEnum*>[self::AnotherEnum::a, self::AnotherEnum::b, self::AnotherEnum::c];
@@ -443,5 +443,5 @@
 static method useAnotherEnum() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.strong.expect
index 1995e45..9156586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.strong.expect
@@ -421,7 +421,7 @@
   method m() → dynamic
     return super.m();
 }
-class Enum#4 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#4*>* values = #C4;
@@ -432,7 +432,7 @@
   method toString() → core::String*
     return this.{=self::Enum#4::_name};
 }
-class Enum#3 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#3*>* values = #C12;
@@ -445,7 +445,7 @@
   method toString() → core::String*
     return this.{=self::Enum#3::_name};
 }
-class Enum#2 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#2*>* values = #C17;
@@ -458,7 +458,7 @@
   method toString() → core::String*
     return this.{=self::Enum#2::_name};
 }
-class Enum#1 extends core::Object {
+class Enum#1 extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#1*>* values = #C21;
@@ -471,7 +471,7 @@
   method toString() → core::String*
     return this.{=self::Enum#1::_name};
 }
-class Enum extends core::Object {
+class Enum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum*>* values = #C25;
@@ -484,7 +484,7 @@
   method toString() → core::String*
     return this.{=self::Enum::_name};
 }
-class AnotherEnum extends core::Object {
+class AnotherEnum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::AnotherEnum*>* values = #C32;
@@ -524,7 +524,7 @@
                                       ^^^^^^"};
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
 
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
index 1995e45..9156586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
@@ -421,7 +421,7 @@
   method m() → dynamic
     return super.m();
 }
-class Enum#4 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#4 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#4*>* values = #C4;
@@ -432,7 +432,7 @@
   method toString() → core::String*
     return this.{=self::Enum#4::_name};
 }
-class Enum#3 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#3 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#3*>* values = #C12;
@@ -445,7 +445,7 @@
   method toString() → core::String*
     return this.{=self::Enum#3::_name};
 }
-class Enum#2 extends core::Object { // from org-dartlang-testcase:///duplicated_declarations_part.dart
+class Enum#2 extends core::Object /*isEnum*/  { // from org-dartlang-testcase:///duplicated_declarations_part.dart
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#2*>* values = #C17;
@@ -458,7 +458,7 @@
   method toString() → core::String*
     return this.{=self::Enum#2::_name};
 }
-class Enum#1 extends core::Object {
+class Enum#1 extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum#1*>* values = #C21;
@@ -471,7 +471,7 @@
   method toString() → core::String*
     return this.{=self::Enum#1::_name};
 }
-class Enum extends core::Object {
+class Enum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Enum*>* values = #C25;
@@ -484,7 +484,7 @@
   method toString() → core::String*
     return this.{=self::Enum::_name};
 }
-class AnotherEnum extends core::Object {
+class AnotherEnum extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::AnotherEnum*>* values = #C32;
@@ -524,7 +524,7 @@
                                       ^^^^^^"};
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
 
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.outline.expect
index 14fe62f..1e369ae 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.outline.expect
@@ -11,7 +11,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.expect
index dbb3734..96b9063 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.transformed.expect
index dbb3734..96b9063 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
index dbb3734..96b9063 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
index dbb3734..96b9063 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.outline.expect
index 25620a0..15ae178 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.outline.expect
@@ -12,7 +12,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.expect
index da20cdc..20a4147 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.transformed.expect
index da20cdc..20a4147 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.strong.transformed.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
index da20cdc..20a4147 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
index da20cdc..20a4147 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
@@ -39,7 +39,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.outline.expect
index e2689c9..8e00ee1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.outline.expect
@@ -12,7 +12,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.expect
index c2cb3bc1..442f52e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.transformed.expect
index c2cb3bc1..442f52e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
index c2cb3bc1..442f52e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
index c2cb3bc1..442f52e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
@@ -40,7 +40,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.outline.expect
index 4034b8b..8406a72 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.outline.expect
@@ -11,7 +11,7 @@
 import self as self2;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → self2::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -26,7 +26,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field self2::Foo* x;
   const constructor •() → self3::Bar*
     : self3::Bar::x = const self2::Foo::•(0), super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.expect
index 6370a9c..298d70d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.transformed.expect
index 6370a9c..298d70d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
index 6370a9c..298d70d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
index 6370a9c..298d70d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
@@ -25,7 +25,7 @@
 import self as err;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::int* i) → err::Foo*
     : assert(i.{core::num::>}(0)), super core::Object::•()
     ;
@@ -41,7 +41,7 @@
 
 import "org-dartlang-testcase:///error_location_04_lib1.dart";
 
-class Bar extends core::Object {
+class Bar extends core::Object /*hasConstConstructor*/  {
   final field err::Foo* x;
   const constructor •() → err2::Bar*
     : err2::Bar::x = invalid-expression "This assertion failed.", super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.outline.expect
index 5506b33..239f404 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.outline.expect
@@ -21,9 +21,9 @@
   synthetic constructor •() → self::SuperClass*
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     ;
 }
@@ -31,7 +31,7 @@
   synthetic constructor •() → self::Class1<self::Class1::T*, self::Class1::S*>*
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.expect
index 6053acb..2f4e9b7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.transformed.expect
index 027d8c9..5e78586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.strong.transformed.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.expect
index 6053acb..2f4e9b7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> = core::Object with self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.transformed.expect
index 027d8c9..5e78586 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/extend_with_type_variable.dart.weak.transformed.expect
@@ -22,9 +22,9 @@
     : super core::Object::•()
     ;
 }
-abstract class Mixin<T extends core::Object* = dynamic> extends core::Object {
+abstract class Mixin<T extends core::Object* = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> {
+abstract class _Class1&S&Mixin<T extends core::Object* = dynamic, S extends self::SuperClass* = self::SuperClass*> extends core::Object implements self::Mixin<self::_Class1&S&Mixin::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Class1&S&Mixin<self::_Class1&S&Mixin::T*, self::_Class1&S&Mixin::S*>*
     : super core::Object::•()
     ;
@@ -34,7 +34,7 @@
     : super self::_Class1&S&Mixin::•()
     ;
 }
-abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass {
+abstract class _Class2&SuperClass&M<T extends core::Object* = dynamic, M extends self::Mixin<self::_Class2&SuperClass&M::T*>* = self::Mixin<dynamic>*> extends self::SuperClass /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class2&SuperClass&M<self::_Class2&SuperClass&M::T*, self::_Class2&SuperClass&M::M*>*
     : super self::SuperClass::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.outline.expect
index b0af5d4..700f57e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.outline.expect
@@ -1,7 +1,7 @@
 @dart._internal::ExternalName::•("dart-ext:here")
 @dart._internal::ExternalName::•("dart-ext:foo/../there")
 @dart._internal::ExternalName::•("dart-ext:/usr/local/somewhere")
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:_internal" as _in;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.expect
index 92724dc..8379e80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.expect
@@ -1,7 +1,7 @@
 @#C2
 @#C4
 @#C6
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:_internal" as _in;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.transformed.expect
index 92724dc..8379e80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.strong.transformed.expect
@@ -1,7 +1,7 @@
 @#C2
 @#C4
 @#C6
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:_internal" as _in;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
index 92724dc..8379e80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
@@ -1,7 +1,7 @@
 @#C2
 @#C4
 @#C6
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:_internal" as _in;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
index 92724dc..8379e80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
@@ -1,7 +1,7 @@
 @#C2
 @#C4
 @#C6
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:_internal" as _in;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.strong.transformed.expect
new file mode 100644
index 0000000..423ce57
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart:16:15: Error: Can't infer a type for 'other' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   operator ==(other) => false;
+//               ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:core" as core;
+
+class A extends core::Object implements core::Function {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(dynamic other) → core::bool*
+    return false;
+}
+class B extends core::Object implements self::Function {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  operator ==(invalid-type other) → core::bool*
+    return false;
+}
+class Function extends core::Object {
+  synthetic constructor •() → self::Function*
+    : super core::Object::•()
+    ;
+  operator ==(core::Object* other) → core::bool*
+    return false;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.weak.transformed.expect
new file mode 100644
index 0000000..423ce57
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/ignore_function.dart:16:15: Error: Can't infer a type for 'other' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   operator ==(other) => false;
+//               ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:core" as core;
+
+class A extends core::Object implements core::Function {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(dynamic other) → core::bool*
+    return false;
+}
+class B extends core::Object implements self::Function {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  operator ==(invalid-type other) → core::bool*
+    return false;
+}
+class Function extends core::Object {
+  synthetic constructor •() → self::Function*
+    : super core::Object::•()
+    ;
+  operator ==(core::Object* other) → core::bool*
+    return false;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.outline.expect
index 55f17dd..503d2ef 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = 87;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.transformed.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.transformed.expect
index c87d93f..0c80488 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_const_with_static_fields.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static const field core::int* constField = #C1;
   const constructor •(dynamic x) → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.outline.expect
index ace49f2..458f1a0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.outline.expect
@@ -12,12 +12,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.expect
index 654cbbe..ed380d1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.transformed.expect
index 654cbbe..ed380d1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.strong.transformed.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.expect
index 654cbbe..ed380d1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.transformed.expect
index 654cbbe..ed380d1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue37776.dart.weak.transformed.expect
@@ -16,12 +16,12 @@
 import self as self;
 import "dart:core" as core;
 
-class X#1 extends core::Object {
+class X#1 extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X#1*
     : super core::Object::•()
     ;
 }
-class X extends core::Object {
+class X extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::X*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
index b488581..23b1937 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
@@ -13,7 +13,7 @@
   synthetic constructor •() → self::A<self::A::Q*>*
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
index 3c42fc9..7473a34 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
index 3c42fc9..7473a34 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
index 3c42fc9..7473a34 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
index 3c42fc9..7473a34 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.outline.expect
index 02428e5..9eab40c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.expect
index 41215f5..5ded87e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.transformed.expect
index 41215f5..5ded87e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
index 41215f5..5ded87e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
index 41215f5..5ded87e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
@@ -25,7 +25,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Constant extends core::Object {
+class Constant extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Constant*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.outline.expect
index e16a9e1..6d4eac1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.outline.expect
@@ -30,7 +30,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     ;
@@ -50,7 +50,7 @@
   synthetic constructor •() → self::C*
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.expect
index dd6951e..39a61d2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart:10:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.transformed.expect
index dd6951e..39a61d2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.strong.transformed.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart:10:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.expect
index dd6951e..39a61d2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart:10:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.transformed.expect
index dd6951e..39a61d2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart.weak.transformed.expect
@@ -53,7 +53,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field dynamic x = null;
   constructor named1() → self::A*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/many_errors.dart:10:26: Error: Constructor bodies can't use 'async', 'async*', or 'sync*'.
@@ -77,7 +77,7 @@
     : super core::Object::•()
     ;
 }
-abstract class AbstractClass extends core::Object {
+abstract class AbstractClass extends core::Object /*hasConstConstructor*/  {
   const constructor id() → self::AbstractClass*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.outline.expect
index 7c3363e..8944460 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @self::a
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = const <self::E*>[self::E::E1, self::E::E2, self::E::E3];
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.transformed.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
index 676b355..623dc08 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C11;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.strong.transformed.expect
index 5cd5635..1b24fb6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class C extends self::D implements self::E {
+class C extends self::D implements self::E /*isEliminatedMixin*/  {
   synthetic constructor •() → self::C*
     : super self::D::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.weak.transformed.expect
index 5cd5635..1b24fb6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_named_mixin_application.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C1
-class C extends self::D implements self::E {
+class C extends self::D implements self::E /*isEliminatedMixin*/  {
   synthetic constructor •() → self::C*
     : super self::D::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.outline.expect
index 6a28c0d..e2cba6b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.expect
index 17fdfdc..d2f6483 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.transformed.expect
index 17fdfdc..d2f6483 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.expect
index 17fdfdc..d2f6483 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
index 17fdfdc..d2f6483 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.outline.expect
index 4436b0d..a50e142 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.outline.expect
@@ -22,7 +22,7 @@
   synthetic constructor •() → self::M*
     ;
 }
-abstract class _MixinApplication&Super&M = self::Super with self::M {
+abstract class _MixinApplication&Super&M = self::Super with self::M /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.expect
index 4e7c452..b8ba75b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M = self::Super with self::M {
+abstract class _MixinApplication&Super&M = self::Super with self::M /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.transformed.expect
index 4c0f475..f7f4881 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M extends self::Super implements self::M {
+abstract class _MixinApplication&Super&M extends self::Super implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.expect
index 4e7c452..b8ba75b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M = self::Super with self::M {
+abstract class _MixinApplication&Super&M = self::Super with self::M /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.transformed.expect
index 4c0f475..f7f4881 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_constructor.dart.weak.transformed.expect
@@ -63,7 +63,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _MixinApplication&Super&M extends self::Super implements self::M {
+abstract class _MixinApplication&Super&M extends self::Super implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor _() → self::_MixinApplication&Super&M*
     : super self::Super::_()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
index a53c688..9a57e29 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -28,12 +28,12 @@
   method m() → dynamic
     ;
 }
-abstract class _C&Object&M1 = core::Object with self::M1 {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -48,7 +48,7 @@
   method m() → dynamic
     ;
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
index 4873d85..2cca9cf 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
index b36e425..b51ef02 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
index 4873d85..2cca9cf 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
index b36e425..b51ef02 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
index e797e4f..b80758f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     : self::Super::field = field, super core::Object::•()
     ;
 }
-class Class extends self::Super implements self::Mixin {
+class Class extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •(core::int* field) → self::Class*
     : super self::Super::•(field)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.weak.transformed.expect
index e797e4f..b80758f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_inferred_parameter_type.dart.weak.transformed.expect
@@ -20,7 +20,7 @@
     : self::Super::field = field, super core::Object::•()
     ;
 }
-class Class extends self::Super implements self::Mixin {
+class Class extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •(core::int* field) → self::Class*
     : super self::Super::•(field)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.outline.expect
index 07db82c..50c040a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.outline.expect
@@ -155,7 +155,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A1&S&M1 = self::S with self::M1 {
+abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
     : super self::S::•()
     ;
@@ -166,12 +166,12 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A2&S&M1 = self::S with self::M1 {
+abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 {
+abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1&M2*
     : super self::_A2&S&M1::•()
     ;
@@ -182,7 +182,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _A0X&S&M = self::S with self::M {
+abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
@@ -193,12 +193,12 @@
     : super self::_A0X&S&M::•()
     ;
 }
-abstract class _A1X&S&M1 = self::S with self::M1 {
+abstract class _A1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M {
+abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
@@ -209,17 +209,17 @@
     : super self::_A1X&S&M1&M::•()
     ;
 }
-abstract class _A2X&S&M1 = self::S with self::M1 {
+abstract class _A2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 {
+abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2*
     : super self::_A2X&S&M1::•()
     ;
 }
-abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M {
+abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
@@ -230,7 +230,7 @@
     : super self::_A2X&S&M1&M2&M::•()
     ;
 }
-abstract class _B0&S&M = self::S with self::M {
+abstract class _B0&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
@@ -240,12 +240,12 @@
   synthetic constructor •() → self::B0*
     ;
 }
-abstract class _B1&S&M1 = self::S with self::M1 {
+abstract class _B1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M {
+abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
@@ -255,17 +255,17 @@
   synthetic constructor •() → self::B1*
     ;
 }
-abstract class _B2&S&M1 = self::S with self::M1 {
+abstract class _B2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 {
+abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2*
     : super self::_B2&S&M1::•()
     ;
 }
-abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M {
+abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
@@ -275,13 +275,13 @@
   synthetic constructor •() → self::B2*
     ;
 }
-abstract class _B0X&S&M = self::S with self::M {
+abstract class _B0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
+abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
     : super self::_B0X&S&M::•()
     ;
@@ -290,18 +290,18 @@
   synthetic constructor •() → self::B0X*
     ;
 }
-abstract class _B1X&S&M1 = self::S with self::M1 {
+abstract class _B1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M {
+abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
+abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
     : super self::_B1X&S&M1&M::•()
     ;
@@ -310,23 +310,23 @@
   synthetic constructor •() → self::B1X*
     ;
 }
-abstract class _B2X&S&M1 = self::S with self::M1 {
+abstract class _B2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 {
+abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2*
     : super self::_B2X&S&M1::•()
     ;
 }
-abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M {
+abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
   abstract forwarding-stub method foo([dynamic x]) → dynamic;
 }
-abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
+abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
     : super self::_B2X&S&M1&M2&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.strong.expect
index 0fbf4b0..5ccca35 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.strong.expect
@@ -158,7 +158,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A1&S&M1 = self::S with self::M1 {
+abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
     : super self::S::•()
     ;
@@ -169,12 +169,12 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A2&S&M1 = self::S with self::M1 {
+abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 {
+abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1&M2*
     : super self::_A2&S&M1::•()
     ;
@@ -185,7 +185,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A0X&S&M = self::S with self::M {
+abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
@@ -196,12 +196,12 @@
     : super self::_A0X&S&M::•()
     ;
 }
-abstract class _A1X&S&M1 = self::S with self::M1 {
+abstract class _A1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M {
+abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
@@ -212,17 +212,17 @@
     : super self::_A1X&S&M1&M::•()
     ;
 }
-abstract class _A2X&S&M1 = self::S with self::M1 {
+abstract class _A2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 {
+abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2*
     : super self::_A2X&S&M1::•()
     ;
 }
-abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M {
+abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
@@ -233,7 +233,7 @@
     : super self::_A2X&S&M1&M2&M::•()
     ;
 }
-abstract class _B0&S&M = self::S with self::M {
+abstract class _B0&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
@@ -244,12 +244,12 @@
     : super self::_B0&S&M::•()
     ;
 }
-abstract class _B1&S&M1 = self::S with self::M1 {
+abstract class _B1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M {
+abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
@@ -260,17 +260,17 @@
     : super self::_B1&S&M1&M::•()
     ;
 }
-abstract class _B2&S&M1 = self::S with self::M1 {
+abstract class _B2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 {
+abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2*
     : super self::_B2&S&M1::•()
     ;
 }
-abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M {
+abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
@@ -281,13 +281,13 @@
     : super self::_B2&S&M1&M2&M::•()
     ;
 }
-abstract class _B0X&S&M = self::S with self::M {
+abstract class _B0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
+abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
     : super self::_B0X&S&M::•()
     ;
@@ -297,18 +297,18 @@
     : super self::_B0X&S&M&MX::•()
     ;
 }
-abstract class _B1X&S&M1 = self::S with self::M1 {
+abstract class _B1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M {
+abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
+abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
     : super self::_B1X&S&M1&M::•()
     ;
@@ -318,23 +318,23 @@
     : super self::_B1X&S&M1&M&MX::•()
     ;
 }
-abstract class _B2X&S&M1 = self::S with self::M1 {
+abstract class _B2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 {
+abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2*
     : super self::_B2X&S&M1::•()
     ;
 }
-abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M {
+abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
+abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
     : super self::_B2X&S&M1&M2&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
index 0fbf4b0..5ccca35 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
@@ -158,7 +158,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A1&S&M1 = self::S with self::M1 {
+abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
     : super self::S::•()
     ;
@@ -169,12 +169,12 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A2&S&M1 = self::S with self::M1 {
+abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 {
+abstract class _A2&S&M1&M2 = self::_A2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1&M2*
     : super self::_A2&S&M1::•()
     ;
@@ -185,7 +185,7 @@
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _A0X&S&M = self::S with self::M {
+abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
@@ -196,12 +196,12 @@
     : super self::_A0X&S&M::•()
     ;
 }
-abstract class _A1X&S&M1 = self::S with self::M1 {
+abstract class _A1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M {
+abstract class _A1X&S&M1&M = self::_A1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
@@ -212,17 +212,17 @@
     : super self::_A1X&S&M1&M::•()
     ;
 }
-abstract class _A2X&S&M1 = self::S with self::M1 {
+abstract class _A2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 {
+abstract class _A2X&S&M1&M2 = self::_A2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2*
     : super self::_A2X&S&M1::•()
     ;
 }
-abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M {
+abstract class _A2X&S&M1&M2&M = self::_A2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
@@ -233,7 +233,7 @@
     : super self::_A2X&S&M1&M2&M::•()
     ;
 }
-abstract class _B0&S&M = self::S with self::M {
+abstract class _B0&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
@@ -244,12 +244,12 @@
     : super self::_B0&S&M::•()
     ;
 }
-abstract class _B1&S&M1 = self::S with self::M1 {
+abstract class _B1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M {
+abstract class _B1&S&M1&M = self::_B1&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
@@ -260,17 +260,17 @@
     : super self::_B1&S&M1&M::•()
     ;
 }
-abstract class _B2&S&M1 = self::S with self::M1 {
+abstract class _B2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 {
+abstract class _B2&S&M1&M2 = self::_B2&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2*
     : super self::_B2&S&M1::•()
     ;
 }
-abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M {
+abstract class _B2&S&M1&M2&M = self::_B2&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
@@ -281,13 +281,13 @@
     : super self::_B2&S&M1&M2&M::•()
     ;
 }
-abstract class _B0X&S&M = self::S with self::M {
+abstract class _B0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
+abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
     : super self::_B0X&S&M::•()
     ;
@@ -297,18 +297,18 @@
     : super self::_B0X&S&M&MX::•()
     ;
 }
-abstract class _B1X&S&M1 = self::S with self::M1 {
+abstract class _B1X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M {
+abstract class _B1X&S&M1&M = self::_B1X&S&M1 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
+abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
     : super self::_B1X&S&M1&M::•()
     ;
@@ -318,23 +318,23 @@
     : super self::_B1X&S&M1&M&MX::•()
     ;
 }
-abstract class _B2X&S&M1 = self::S with self::M1 {
+abstract class _B2X&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1*
     : super self::S::•()
     ;
 }
-abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 {
+abstract class _B2X&S&M1&M2 = self::_B2X&S&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2*
     : super self::_B2X&S&M1::•()
     ;
 }
-abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M {
+abstract class _B2X&S&M1&M2&M = self::_B2X&S&M1&M2 with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
   abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
-abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
+abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
     : super self::_B2X&S&M1&M2&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
index 8ecf33b..67867e3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
@@ -44,7 +44,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -69,7 +69,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -78,7 +78,7 @@
   synthetic constructor •() → self::C2*
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
index c8ffe22..7f6f63d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
@@ -44,7 +44,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -70,7 +70,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
index b81769a..964368f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M {
+class N extends core::Object implements self::M /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
index c8ffe22..7f6f63d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
@@ -44,7 +44,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -70,7 +70,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
index b81769a..964368f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M {
+class N extends core::Object implements self::M /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.outline.expect
index 7c8f4ee..9c0a4ed 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.outline.expect
@@ -22,7 +22,7 @@
   synthetic constructor •() → self::E*
     ;
 }
-abstract class _F&C&M = self::C<core::int*> with self::M {
+abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •({dynamic a, dynamic b}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.expect
index 66b6456..500a9d3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.expect
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M = self::C<core::int*> with self::M {
+abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.transformed.expect
index da12505..9c19e86 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     : super core::Object::•()
     ;
 }
-class D extends self::C<core::String*> implements self::M {
+class D extends self::C<core::String*> implements self::M /*isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C2}) → self::D*
     : super self::C::•(a: a, b: b)
     ;
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M extends self::C<core::int*> implements self::M {
+abstract class _F&C&M extends self::C<core::int*> implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
index 66b6456..500a9d3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M = self::C<core::int*> with self::M {
+abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
index da12505..9c19e86 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
@@ -29,7 +29,7 @@
     : super core::Object::•()
     ;
 }
-class D extends self::C<core::String*> implements self::M {
+class D extends self::C<core::String*> implements self::M /*isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C2}) → self::D*
     : super self::C::•(a: a, b: b)
     ;
@@ -39,7 +39,7 @@
     : super self::D::•()
     ;
 }
-abstract class _F&C&M extends self::C<core::int*> implements self::M {
+abstract class _F&C&M extends self::C<core::int*> implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •({dynamic a = #C1, dynamic b = #C3}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
index 5d68397..3b41508 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
@@ -17,7 +17,7 @@
   synthetic constructor •() → self::D*
     ;
 }
-abstract class _Foo&Object&C = core::Object with self::C<self::B*> {
+abstract class _Foo&Object&C = core::Object with self::C<self::B*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
index 9081947..467b3b5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C = core::Object with self::C<self::B*> {
+abstract class _Foo&Object&C = core::Object with self::C<self::B*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
index 8d92589..6b9150f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> {
+abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> /*isAnonymousMixin,isEliminatedMixin*/  {
   generic-covariant-impl field self::B* _field = null;
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
index 9081947..467b3b5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C = core::Object with self::C<self::B*> {
+abstract class _Foo&Object&C = core::Object with self::C<self::B*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
index 8d92589..6b9150f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
     : super self::C::•()
     ;
 }
-abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> {
+abstract class _Foo&Object&C extends core::Object implements self::C<self::B*> /*isAnonymousMixin,isEliminatedMixin*/  {
   generic-covariant-impl field self::B* _field = null;
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.outline.expect
index 7e6110b..13e9d25 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.outline.expect
@@ -19,12 +19,12 @@
   synthetic constructor •() → self::S*
     ;
 }
-abstract class _Named&S&M = self::S with self::M {
+abstract class _Named&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N = self::_Named&S&M with self::N {
+abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.expect
index 1dc8051..085e258 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.expect
@@ -23,12 +23,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M = self::S with self::M {
+abstract class _Named&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N = self::_Named&S&M with self::N {
+abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.transformed.expect
index 14cb42d..ad78013 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.strong.transformed.expect
@@ -23,13 +23,13 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M extends self::S implements self::M {
+abstract class _Named&S&M extends self::S implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N extends self::_Named&S&M implements self::N {
+abstract class _Named&S&M&N extends self::_Named&S&M implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
@@ -39,7 +39,7 @@
   get superM() → dynamic
     return super.{self::M::m};
 }
-class Named extends self::_Named&S&M&N implements self::M {
+class Named extends self::_Named&S&M&N implements self::M /*isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
index 1dc8051..085e258 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
@@ -23,12 +23,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M = self::S with self::M {
+abstract class _Named&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N = self::_Named&S&M with self::N {
+abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
index 14cb42d..ad78013 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
@@ -23,13 +23,13 @@
     : super core::Object::•()
     ;
 }
-abstract class _Named&S&M extends self::S implements self::M {
+abstract class _Named&S&M extends self::S implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
 }
-abstract class _Named&S&M&N extends self::_Named&S&M implements self::N {
+abstract class _Named&S&M&N extends self::_Named&S&M implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
@@ -39,7 +39,7 @@
   get superM() → dynamic
     return super.{self::M::m};
 }
-class Named extends self::_Named&S&M&N implements self::M {
+class Named extends self::_Named&S&M&N implements self::M /*isEliminatedMixin*/  {
   field dynamic m = null;
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.outline.expect
index c82f01d..f982247 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M = self::B with self::M {
+abstract class _A&B&M = self::B with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.expect
index a6968d3..85e498d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M = self::B with self::M {
+abstract class _A&B&M = self::B with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.transformed.expect
index a732858..b9faaa3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M extends self::B implements self::M {
+abstract class _A&B&M extends self::B implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.expect
index a6968d3..85e498d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M = self::B with self::M {
+abstract class _A&B&M = self::B with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.transformed.expect
index a732858..b9faaa3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_with_static_member.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _A&B&M extends self::B implements self::M {
+abstract class _A&B&M extends self::B implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&B&M*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.outline.expect
index 536cae1..f42f11f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.outline.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.transformed.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.transformed.expect
index 6a1ea6d..ec1126c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/nested_implicit_const_with_env_var.dart.weak.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* bar;
   const constructor •(core::int* bar) → self::A*
     : self::A::bar = bar, super core::Object::•()
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   final field self::A* baz;
   const constructor •(self::A* baz) → self::B*
     : self::B::baz = baz, super core::Object::•()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.outline.expect
index 2c007ed..5d86d97 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.outline.expect
@@ -34,7 +34,7 @@
   static factory WrongName() → self::Bad*
     ;
 }
-abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.expect
index ea0d145..466b5c2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.transformed.expect
index 0ae01e9..8266865 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.strong.transformed.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
index ea0d145..466b5c2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
index 0ae01e9..8266865 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
@@ -32,7 +32,7 @@
   method method() → invalid-type {}
   static factory WrongName() → self::Bad* {}
 }
-abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin {
+abstract class _WithMixin&Supertype&Mixin extends lib::Supertype implements lib::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.strong.transformed.expect
index 0b5a926..c2e98d0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.strong.transformed.expect
@@ -62,7 +62,7 @@
     : super core::Object::•()
     ;
 }
-class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> {
+class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Mix<self::Mix::M*>*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
index 0b5a926..c2e98d0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
     : super core::Object::•()
     ;
 }
-class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> {
+class Mix<M extends core::Object* = dynamic> extends self::Base<self::Mix::M*> implements self::Mixin<self::Mix::M*> /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Mix<self::Mix::M*>*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.outline.expect
index 2d13710..3ed80bf 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.outline.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.expect
index 87fc76e..397a76d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.transformed.expect
index 0394311..2b04ded 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let<BottomType> #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
index 87fc76e..397a76d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
index 0394311..2b04ded 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let<BottomType> #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
 }
-class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> {
+class _Y<T extends core::Object* = dynamic> extends core::Object implements self::_X<self::_Y::T*> /*hasConstConstructor*/  {
   const constructor •() → self::_Y<self::_Y::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.outline.expect
index 4118194..b15ac8d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.outline.expect
@@ -4,7 +4,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -12,7 +12,7 @@
   static factory •() → self::A*
     let dynamic #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.expect
index a87fba5..81c22f9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let dynamic #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.transformed.expect
index d6f34c9..8c2291d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let<BottomType> #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
index a87fba5..81c22f9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let dynamic #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
index d6f34c9..8c2291d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
@@ -13,7 +13,7 @@
   static factory •() → self::A*
     let<BottomType> #redirecting_factory = self::B::• in let core::String* #typeArg0 = null in invalid-expression;
 }
-class B<T extends core::Object* = dynamic> extends self::A {
+class B<T extends core::Object* = dynamic> extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::T*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.outline.expect
index 253f731..c570402 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.outline.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.expect
index 0f11087..3c479e0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.transformed.expect
index 0f11087..3c479e0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.expect
index 0f11087..3c479e0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.transformed.expect
index 0f11087..3c479e0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_literal_as_metadata.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.outline.expect
index de5a4aa..d05b2f5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.outline.expect
@@ -9,7 +9,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.expect
index 1b3c50c..3d8ba36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.transformed.expect
index 1b3c50c..3d8ba36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.strong.transformed.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
index 1b3c50c..3d8ba36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
index 1b3c50c..3d8ba36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
@@ -65,7 +65,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect
index 5dfc563..acc9d65 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.1.expect
@@ -23,7 +23,7 @@
       ;
     method hello(covariant lib::FooEntry* entry) → void {}
   }
-  abstract class MyMixin extends lib::Baz {
+  abstract class MyMixin extends lib::Baz /*isMixinDeclaration*/  {
   }
   abstract class Qux extends lib::Baz {
     synthetic constructor •() → lib::Qux*
@@ -31,7 +31,7 @@
       ;
     method hello(covariant lib::BarEntry* entry) → void {}
   }
-  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin {
+  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → lib::_Quux&Qux&MyMixin*
       : super lib::Qux::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect
index f0b2d5e..c05c801 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_mixin_failure_1.yaml.world.2.expect
@@ -23,7 +23,7 @@
       ;
     method hello(covariant lib::FooEntry* entry) → void {}
   }
-  abstract class MyMixin extends lib::Baz {
+  abstract class MyMixin extends lib::Baz /*isMixinDeclaration*/  {
   }
   abstract class Qux extends lib::Baz {
     synthetic constructor •() → lib::Qux*
@@ -31,7 +31,7 @@
       ;
     method hello(covariant lib::BarEntry* entry) → void {}
   }
-  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin {
+  abstract class _Quux&Qux&MyMixin extends lib::Qux implements lib::MyMixin /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → lib::_Quux&Qux&MyMixin*
       : super lib::Qux::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect
index b2daf41..1c53914 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml.world.1.expect
@@ -21,9 +21,9 @@
       : super dart.core::Object::•()
       ;
   }
-  abstract class M<T extends dart.core::Object* = dynamic> extends main::A<main::M::T*> {
+  abstract class M<T extends dart.core::Object* = dynamic> extends main::A<main::M::T*> /*isMixinDeclaration*/  {
   }
-  abstract class _C&Object&M extends dart.core::Object implements main::M<dynamic> {
+  abstract class _C&Object&M extends dart.core::Object implements main::M<dynamic> /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → main::_C&Object&M*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.1.expect
index 90ad929..ca91b00 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.1.expect
@@ -8,7 +8,7 @@
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     static const field lib2::Foo* BAR = #C1;
     const constructor •(dart.core::String* x) → lib2::Foo*
       : super dart.core::Object::•()
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.2.expect
index 166ac01..5a4ab88 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_13.yaml.world.2.expect
@@ -8,7 +8,7 @@
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     static const field lib2::Foo* BAR = #C1;
     const constructor •(dart.core::String* x) → lib2::Foo*
       : super dart.core::Object::•()
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_18.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_18.yaml
index 5016781..c7db57e 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_18.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_18.yaml
@@ -41,4 +41,4 @@
           print("exports!")
         }
     expectedLibraryCount: 3
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false # For now, libraries with errors cannot have bodies rebuild.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
index 761708e..321e0eb 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
@@ -21,7 +21,7 @@
       return "${this.{main::Foo::message}}";
     }
   }
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
index 7d8e26b..ad72d9d 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
@@ -21,7 +21,7 @@
       return "${this.{main::Foo::message}}!";
     }
   }
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
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 faa6a66..b9ec6ce 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
@@ -3,7 +3,7 @@
 
   import "dart:collection";
 
-  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> {
+  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → main::_WithListMixin&Object&ListMixin*
       : super dart.core::Object::•()
       ;
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 faa6a66..b9ec6ce 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
@@ -3,7 +3,7 @@
 
   import "dart:collection";
 
-  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> {
+  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → main::_WithListMixin&Object&ListMixin*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
index dc036f0..f4a1ddd 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///main.dart" as main {
 
-  abstract class _A&Object&B extends dart.core::Object implements main::B {
+  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
index dc036f0..f4a1ddd 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///main.dart" as main {
 
-  abstract class _A&Object&B extends dart.core::Object implements main::B {
+  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_25.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_25.yaml
index 6ada515..b561e9d 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_25.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_25.yaml
@@ -48,4 +48,4 @@
           }
         }
     expectedLibraryCount: 1
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false # For now, libraries with errors cannot have bodies rebuild.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_26.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_26.yaml
index 5f07ff2..9986dfb 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_26.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_26.yaml
@@ -40,4 +40,4 @@
           new A1.foo();
         }
     expectedLibraryCount: 1
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false # For now, libraries with errors cannot have bodies rebuild.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.1.expect
index 74a7dbe..7bc33641 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.1.expect
@@ -9,22 +9,22 @@
       dart.core::print("Class A method a");
     }
   }
-  abstract class B extends main::A {
+  abstract class B extends main::A /*isMixinDeclaration*/  {
     method b() → dynamic {
       dart.core::print("Class A method b");
     }
   }
-  abstract class _C&A&B extends dart.core::Object implements main::A, main::B {
+  abstract class _C&A&B extends dart.core::Object implements main::A, main::B /*isAnonymousMixin*/  {
     synthetic constructor •() → main::_C&A&B*
       : super dart.core::Object::•()
       ;
   }
-  abstract class C extends main::_C&A&B {
+  abstract class C extends main::_C&A&B /*isMixinDeclaration*/  {
     method c() → dynamic {
       dart.core::print("Class C method c");
     }
   }
-  abstract class _D&A&B extends main::A implements main::B {
+  abstract class _D&A&B extends main::A implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → main::_D&A&B*
       : super main::A::•()
       ;
@@ -32,7 +32,7 @@
       dart.core::print("Class A method b");
     }
   }
-  abstract class _D&A&B&C extends main::_D&A&B implements main::C {
+  abstract class _D&A&B&C extends main::_D&A&B implements main::C /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → main::_D&A&B&C*
       : super main::_D&A&B::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.2.expect
index 685e8c4..e243222 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_28.yaml.world.2.expect
@@ -9,22 +9,22 @@
       dart.core::print("Class A method a!");
     }
   }
-  abstract class B extends main::A {
+  abstract class B extends main::A /*isMixinDeclaration*/  {
     method b() → dynamic {
       dart.core::print("Class A method b!");
     }
   }
-  abstract class _C&A&B extends dart.core::Object implements main::A, main::B {
+  abstract class _C&A&B extends dart.core::Object implements main::A, main::B /*isAnonymousMixin*/  {
     synthetic constructor •() → main::_C&A&B*
       : super dart.core::Object::•()
       ;
   }
-  abstract class C extends main::_C&A&B {
+  abstract class C extends main::_C&A&B /*isMixinDeclaration*/  {
     method c() → dynamic {
       dart.core::print("Class C method c!");
     }
   }
-  abstract class _D&A&B extends main::A implements main::B {
+  abstract class _D&A&B extends main::A implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → main::_D&A&B*
       : super main::A::•()
       ;
@@ -32,7 +32,7 @@
       dart.core::print("Class A method b!");
     }
   }
-  abstract class _D&A&B&C extends main::_D&A&B implements main::C {
+  abstract class _D&A&B&C extends main::_D&A&B implements main::C /*isAnonymousMixin,isEliminatedMixin*/  {
     synthetic constructor •() → main::_D&A&B&C*
       : super main::_D&A&B::•()
       ;
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 91e8487..b765c13 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
@@ -36,7 +36,7 @@
 
   import "org-dartlang-test:///libA.dart";
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → main::Foo*
       : super dart.core::Object::•()
       ;
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 b5437cc..c5de17c 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
@@ -36,7 +36,7 @@
 
   import "org-dartlang-test:///libA.dart";
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → main::Foo*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml
index 1771b25..eaa4d06 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml
@@ -95,7 +95,6 @@
         }
     expectedLibraryCount: 3
     expectsRebuildBodiesOnly: true
-
   - entry: main.dart
     useExperimentalInvalidation: true
     worldType: updated
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml.world.4.expect
index 52f52b5..366f447 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml.world.4.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml.world.4.expect
@@ -1,6 +1,8 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib1.dart" as lib1 {
-additionalExports = (main::main,
+additionalExports = (main::Extension|get#method,
+  main::Extension|method,
+  main::main,
   main::Class,
   main::Extension)
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml
new file mode 100644
index 0000000..d3b6f53
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml
@@ -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.md file.
+
+# Compile an application, change a file, but don't change the outline.
+# Test FFI compilation.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    useExperimentalInvalidation: true
+    sources:
+      main.dart: |
+        import 'lib.dart';
+
+        main() {
+          Coordinate coordinate = new Coordinate.allocate(42.0, 42.0, null);
+          print(coordinate.x);
+          print(coordinate.y);
+          print(coordinate.next);
+        }
+      lib.dart: |
+        import 'dart:ffi';
+        class Coordinate extends Struct {
+          @Double()
+          double x;
+
+          @Double()
+          double y;
+
+          Pointer<Coordinate> next;
+
+          factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
+            return null;
+          }
+        }
+    expectedLibraryCount: 2
+  - entry: main.dart
+    useExperimentalInvalidation: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import 'lib.dart';
+
+        main() {
+          Coordinate coordinate = new Coordinate.allocate(42.0, 42.0, null);
+          print(coordinate.x);
+          print(coordinate.y);
+          print(coordinate.next);
+          print("Done!");
+        }
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: true
+  - entry: main.dart
+    useExperimentalInvalidation: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    sources:
+      lib.dart: |
+        import 'dart:ffi';
+        class Coordinate extends Struct {
+          @Double()
+          double x;
+
+          @Double()
+          double y;
+
+          Pointer<Coordinate> next;
+
+          factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
+            print("hello");
+            return null;
+          }
+        }
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
new file mode 100644
index 0000000..748c4c0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
@@ -0,0 +1,60 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "dart:ffi";
+
+  @#C3
+  class Coordinate extends dart.ffi::Struct {
+    @#C3
+    static final field dart.core::int* #sizeOf = (#C6).{dart.core::List::[]}(dart.ffi::_abi());
+    @#C3
+    constructor #fromPointer(dynamic #pointer) → dynamic
+      : super dart.ffi::Struct::_fromPointer(#pointer)
+      ;
+    static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
+      return null;
+    }
+    get #_ptr_x() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get x() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_x}, #C7);
+    set x(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_x}, #C7, #v);
+    get #_ptr_y() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C9).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get y() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_y}, #C7);
+    set y(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_y}, #C7, #v);
+    get #_ptr_next() → dart.ffi::Pointer<dart.ffi::Pointer<lib::Coordinate*>*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C11).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Pointer<lib::Coordinate*>*>();
+    get next() → dart.ffi::Pointer<lib::Coordinate*>*
+      return dart.ffi::_loadPointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7);
+    set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
+      return dart.ffi::_storePointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7, #v);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::Coordinate* coordinate = lib::Coordinate::allocate(42.0, 42.0, null);
+    dart.core::print(coordinate.{lib::Coordinate::x});
+    dart.core::print(coordinate.{lib::Coordinate::y});
+    dart.core::print(coordinate.{lib::Coordinate::next});
+  }
+}
+constants  {
+  #C1 = "vm:entry-point"
+  #C2 = null
+  #C3 = dart.core::pragma {name:#C1, options:#C2}
+  #C4 = 24
+  #C5 = 20
+  #C6 = <dart.core::int*>[#C4, #C5, #C4]
+  #C7 = 0
+  #C8 = 8
+  #C9 = <dart.core::int*>[#C8, #C8, #C8]
+  #C10 = 16
+  #C11 = <dart.core::int*>[#C10, #C10, #C10]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
new file mode 100644
index 0000000..b1805b0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
@@ -0,0 +1,61 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "dart:ffi";
+
+  @#C3
+  class Coordinate extends dart.ffi::Struct {
+    @#C3
+    static final field dart.core::int* #sizeOf = (#C6).{dart.core::List::[]}(dart.ffi::_abi());
+    @#C3
+    constructor #fromPointer(dynamic #pointer) → dynamic
+      : super dart.ffi::Struct::_fromPointer(#pointer)
+      ;
+    static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
+      return null;
+    }
+    get #_ptr_x() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get x() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_x}, #C7);
+    set x(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_x}, #C7, #v);
+    get #_ptr_y() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C9).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get y() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_y}, #C7);
+    set y(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_y}, #C7, #v);
+    get #_ptr_next() → dart.ffi::Pointer<dart.ffi::Pointer<lib::Coordinate*>*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C11).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Pointer<lib::Coordinate*>*>();
+    get next() → dart.ffi::Pointer<lib::Coordinate*>*
+      return dart.ffi::_loadPointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7);
+    set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
+      return dart.ffi::_storePointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7, #v);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::Coordinate* coordinate = lib::Coordinate::allocate(42.0, 42.0, null);
+    dart.core::print(coordinate.{lib::Coordinate::x});
+    dart.core::print(coordinate.{lib::Coordinate::y});
+    dart.core::print(coordinate.{lib::Coordinate::next});
+    dart.core::print("Done!");
+  }
+}
+constants  {
+  #C1 = "vm:entry-point"
+  #C2 = null
+  #C3 = dart.core::pragma {name:#C1, options:#C2}
+  #C4 = 24
+  #C5 = 20
+  #C6 = <dart.core::int*>[#C4, #C5, #C4]
+  #C7 = 0
+  #C8 = 8
+  #C9 = <dart.core::int*>[#C8, #C8, #C8]
+  #C10 = 16
+  #C11 = <dart.core::int*>[#C10, #C10, #C10]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
new file mode 100644
index 0000000..32cc854
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
@@ -0,0 +1,62 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "dart:ffi";
+
+  @#C3
+  class Coordinate extends dart.ffi::Struct {
+    @#C3
+    static final field dart.core::int* #sizeOf = (#C6).{dart.core::List::[]}(dart.ffi::_abi());
+    @#C3
+    constructor #fromPointer(dynamic #pointer) → dynamic
+      : super dart.ffi::Struct::_fromPointer(#pointer)
+      ;
+    static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
+      dart.core::print("hello");
+      return null;
+    }
+    get #_ptr_x() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get x() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_x}, #C7);
+    set x(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_x}, #C7, #v);
+    get #_ptr_y() → dart.ffi::Pointer<dart.ffi::Double*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C9).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Double*>();
+    get y() → dart.core::double*
+      return dart.ffi::_loadDouble(this.{lib::Coordinate::#_ptr_y}, #C7);
+    set y(dart.core::double* #v) → void
+      return dart.ffi::_storeDouble(this.{lib::Coordinate::#_ptr_y}, #C7, #v);
+    get #_ptr_next() → dart.ffi::Pointer<dart.ffi::Pointer<lib::Coordinate*>*>*
+      return this.{dart.ffi::Struct::_addressOf}.{dart.ffi::Pointer::_offsetBy}((#C11).{dart.core::List::[]}(dart.ffi::_abi())).{dart.ffi::Pointer::cast}<dart.ffi::Pointer<lib::Coordinate*>*>();
+    get next() → dart.ffi::Pointer<lib::Coordinate*>*
+      return dart.ffi::_loadPointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7);
+    set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
+      return dart.ffi::_storePointer<dart.ffi::Pointer<lib::Coordinate*>*>(this.{lib::Coordinate::#_ptr_next}, #C7, #v);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    lib::Coordinate* coordinate = lib::Coordinate::allocate(42.0, 42.0, null);
+    dart.core::print(coordinate.{lib::Coordinate::x});
+    dart.core::print(coordinate.{lib::Coordinate::y});
+    dart.core::print(coordinate.{lib::Coordinate::next});
+    dart.core::print("Done!");
+  }
+}
+constants  {
+  #C1 = "vm:entry-point"
+  #C2 = null
+  #C3 = dart.core::pragma {name:#C1, options:#C2}
+  #C4 = 24
+  #C5 = 20
+  #C6 = <dart.core::int*>[#C4, #C5, #C4]
+  #C7 = 0
+  #C8 = 8
+  #C9 = <dart.core::int*>[#C8, #C8, #C8]
+  #C10 = 16
+  #C11 = <dart.core::int*>[#C10, #C10, #C10]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
index a2166d9..174ad04 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
@@ -3,7 +3,7 @@
 
   import "org-dartlang-test:///main.dart";
 
-  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo {
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
index 6ec9787..089f7dc 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
@@ -3,7 +3,7 @@
 
   import "org-dartlang-test:///main.dart";
 
-  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo {
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin*/  {
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
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 164275c..42d7120 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
@@ -2,7 +2,7 @@
 library from "org-dartlang-test:///main.dart" as main {
 
   part myPart.dart;
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → main::Foo*
       : super dart.core::Object::•()
       ;
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 eda5685..418248d 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
@@ -2,7 +2,7 @@
 library from "org-dartlang-test:///main.dart" as main {
 
   part myPart.dart;
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → main::Foo*
       : super dart.core::Object::•()
       ;
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 488e237..13582f4 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
@@ -2,7 +2,7 @@
 library from "org-dartlang-test:///main.dart" as main {
 
   part myPart.dart;
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → main::Foo*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml
index 8aa50fc..96943e2 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml
@@ -61,7 +61,7 @@
 
         enum CompilationStrategy { direct, toKernel, toData, fromData }
     expectedLibraryCount: 2
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false # For now, libraries with errors cannot have bodies rebuild.
   - entry: main.dart
     useExperimentalInvalidation: true
     worldType: updated
@@ -88,4 +88,4 @@
 
         enum CompilationStrategy { direct, toKernel, toData, fromData }
     expectedLibraryCount: 2
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false # For now, libraries with errors cannot have bodies rebuild.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
index db672db..eff9cc3 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
@@ -28,7 +28,7 @@
       return "${this.{main::Foo::message}}";
     }
   }
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
index efb24e4..61e0b68 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
@@ -28,7 +28,7 @@
       return "${this.{main::Foo::message}}!!!";
     }
   }
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
index 6872d26..a601b28 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
@@ -21,7 +21,7 @@
       return "${this.{main::Foo::message}}?!?";
     }
   }
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
index 05b87bb..a766d58 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
@@ -32,7 +32,7 @@
     }
   }
   @#C1
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
index 05b87bb..a766d58 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
@@ -32,7 +32,7 @@
     }
   }
   @#C1
-  class CompilationStrategy extends dart.core::Object {
+  class CompilationStrategy extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect
index e14d840..c3488019 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
index 775fa51..330e86a 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
index 2a323b6..d94840c 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
index 5da4981..4448e20 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect
index 79519c1..0a98dfb 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.5.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect
index e14d840..c3488019 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
index ced3bbf..d55ef0b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
@@ -14,7 +14,7 @@
 
   import "org-dartlang-test:///lib.dart";
 
-  class Bar extends dart.core::Object {
+  class Bar extends dart.core::Object /*hasConstConstructor*/  {
     final field lib::Foo* x;
     const constructor •() → lib2::Bar*
       : lib2::Bar::x = invalid-expression "This assertion failed.", super dart.core::Object::•()
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect
index b212595..ea9b7e7 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.3.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
@@ -14,7 +14,7 @@
 
   import "org-dartlang-test:///lib.dart";
 
-  class Bar extends dart.core::Object {
+  class Bar extends dart.core::Object /*hasConstConstructor*/  {
     final field lib::Foo* x;
     const constructor •() → lib2::Bar*
       : lib2::Bar::x = #C1, super dart.core::Object::•()
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect
index e14d840..c3488019 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
index fd1eaf9..6beddd6 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect
index e14d840..c3488019 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.3.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect
index e14d840..c3488019 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
index b96fc85..ec21fb4 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect
index 06f21af..f105755 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.3.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///lib.dart" as lib {
 
-  class Foo extends dart.core::Object {
+  class Foo extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •(dart.core::int* i) → lib::Foo*
       : assert(i.{dart.core::num::>}(0)), super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
index 4874153..3cae5cc 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
@@ -3,19 +3,3 @@
 # BSD-style license that can be found in the LICENSE.md file.
 
 # Status file for the test suite ../test/incremental_load_from_dill_test.dart.
-
-no_outline_change_1: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_2: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_6: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_7: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_9: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_10: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_11: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_12: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_13: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_14: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_21: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_24: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_27: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_33: Crash # Doesn't work on DillLibraryBuilders.
-no_outline_change_34: Crash # Doesn't work on DillLibraryBuilders.
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
new file mode 100644
index 0000000..612b7ef
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
@@ -0,0 +1,43 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   set field1(value) {}
+//              ^^^^^
+//
+// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   set field2(value) {}
+//              ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field dynamic field1 = null;
+  field core::int* field2 = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class I extends core::Object {
+  field core::int* field1 = null;
+  field dynamic field2 = null;
+  synthetic constructor •() → self::I*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  get field1() → core::int*
+    return null;
+  get field2() → core::int*
+    return null;
+  set field1(invalid-type value) → void {}
+  set field2(invalid-type value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
new file mode 100644
index 0000000..f362386
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
@@ -0,0 +1,56 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get a => null;
+//       ^
+//
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get a => null;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class I1 extends core::Object {
+  field core::int* x = null;
+  synthetic constructor •() → self::I1*
+    : super core::Object::•()
+    ;
+}
+class I2 extends self::I1 {
+  field core::int* y = null;
+  synthetic constructor •() → self::I2*
+    : super self::I1::•()
+    ;
+}
+class A extends core::Object {
+  final field self::I1* a = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  final field self::I2* a = null;
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+}
+class C1 extends core::Object implements self::A, self::B {
+  synthetic constructor •() → self::C1*
+    : super core::Object::•()
+    ;
+  get a() → invalid-type
+    return null;
+}
+class C2 extends core::Object implements self::B, self::A {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  get a() → invalid-type
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
new file mode 100644
index 0000000..5ca29a6
--- /dev/null
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
@@ -0,0 +1,58 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get a => null;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class I1 extends core::Object {
+  field core::int* x = null;
+  synthetic constructor •() → self::I1*
+    : super core::Object::•()
+    ;
+}
+class I2 extends core::Object {
+  field core::int* y = null;
+  synthetic constructor •() → self::I2*
+    : super core::Object::•()
+    ;
+}
+class I3 extends core::Object implements self::I1, self::I2 {
+  field core::int* x = null;
+  field core::int* y = null;
+  synthetic constructor •() → self::I3*
+    : super core::Object::•()
+    ;
+}
+class A extends core::Object {
+  final field self::I1* a = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  final field self::I2* a = null;
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+}
+class C1 extends core::Object implements self::A, self::B {
+  synthetic constructor •() → self::C1*
+    : super core::Object::•()
+    ;
+  get a() → self::I3*
+    return null;
+}
+class C2 extends core::Object implements self::A, self::B {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  get a() → invalid-type
+    return null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.outline.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.outline.expect
index da1258f..b4b1520 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* t;
   const constructor •(self::C::T* t) → self::C<self::C::T*>*
     : self::C::t = t, super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
index 6aa1ff0..508226b 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* t;
   const constructor •(self::C::T* t) → self::C<self::C::T*>*
     : self::C::t = t, super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
index 6aa1ff0..508226b 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* t;
   const constructor •(self::C::T* t) → self::C<self::C::T*>*
     : self::C::t = t, super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.outline.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.outline.expect
index cbb70eb..8622004 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.outline.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::num* = core::num*> extends core::Object {
+class C<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* x;
   const constructor •(self::C::T* x) → self::C<self::C::T*>*
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D<T extends core::num* = core::num*> extends core::Object {
+class D<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
index c6802a7..b25e914 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::num* = core::num*> extends core::Object {
+class C<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* x;
   const constructor •(self::C::T* x) → self::C<self::C::T*>*
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D<T extends core::num* = core::num*> extends core::Object {
+class D<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
index c6802a7..b25e914 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::num* = core::num*> extends core::Object {
+class C<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   final field self::C::T* x;
   const constructor •(self::C::T* x) → self::C<self::C::T*>*
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D<T extends core::num* = core::num*> extends core::Object {
+class D<T extends core::num* = core::num*> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index 2aa6d59..7a7aebc 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
index 0fda0a1..9abd5f3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
index 0fda0a1..9abd5f3 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index 5b2f604..88aeaca 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
index 8a2ff24..b83b8fe 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
index 8a2ff24..b83b8fe 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.outline.expect
index e9ee04c..dcbe03a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
index 2a1ae24..b9774d6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
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 7d1a7f3..41a115e 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
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.outline.expect
index e9ee04c..dcbe03a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
index b93b09c..bb1c4d6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
index b93b09c..bb1c4d6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.outline.expect
index 401d558..6bf8275 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(dynamic l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
index cbdc206..ae2a9b6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(dynamic l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
index cbdc206..ae2a9b6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(dynamic l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.outline.expect
index 4c70c66..0a774f4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
index 2b285f4..ecbef42 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
index 2b285f4..ecbef42 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.outline.expect
index e9ee04c..dcbe03a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
index 402205d..f2402c0 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
index 402205d..f2402c0 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
index 74ed489..ba15078 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F<unrelated T extends core::Object* = dynamic> = () →* void;
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.outline.expect
index e9ee04c..dcbe03a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
index c30db0b..b618351 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
index c30db0b..b618351 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.outline.expect
index 1f341e9..50ccca4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F = () →* void;
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
index 8e70fef..c31b27b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
@@ -4,7 +4,7 @@
 
 @#C1
 typedef F = () →* void;
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
index 8e70fef..c31b27b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 
 @#C1
 typedef F = () →* void;
-class Foo extends core::Object {
+class Foo extends core::Object /*hasConstConstructor*/  {
   const constructor •(core::List<core::String*>* l) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
new file mode 100644
index 0000000..bf74c35
--- /dev/null
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
@@ -0,0 +1,66 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   f(x, {y}) {}
+//   ^
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   f(x, {y}) {}
+//     ^
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   f(x, {y}) {}
+//         ^
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   h(x, {y}) {}
+//         ^
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   g(x, {y}) {}
+//     ^
+//
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   g(x, {y}) {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method f(self::A* x, {self::A* y = #C1}) → self::A* {}
+  method g(self::A* x, {self::A* y = #C1}) → self::A* {}
+  method h(self::A* x, {self::A* y = #C1}) → self::A* {}
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  method f(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
+  method g(invalid-type x, {invalid-type y = #C1}) → self::A* {}
+  method h(self::A* x, {invalid-type y = #C1}) → self::A* {}
+}
+class I extends core::Object {
+  synthetic constructor •() → self::I*
+    : super core::Object::•()
+    ;
+  method f(self::I* x, {self::I* y = #C1}) → self::I* {}
+  method g(self::I* x, {self::I* y = #C1}) → self::A* {}
+  method h(self::A* x, {self::I* y = #C1}) → self::A* {}
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
new file mode 100644
index 0000000..863160b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
@@ -0,0 +1,71 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int*;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int*;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+  abstract get x() → core::num*;
+}
+abstract class D extends core::Object {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+  abstract get x() → core::double*;
+}
+class E extends self::A implements self::B {
+  field core::int* x = null;
+  synthetic constructor •() → self::E*
+    : super self::A::•()
+    ;
+}
+class F extends self::A implements self::C {
+  field invalid-type x = null;
+  synthetic constructor •() → self::F*
+    : super self::A::•()
+    ;
+}
+class G extends self::A implements self::D {
+  field invalid-type x = null;
+  synthetic constructor •() → self::G*
+    : super self::A::•()
+    ;
+}
+class H extends self::C implements self::D {
+  field invalid-type x = null;
+  synthetic constructor •() → self::H*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
index 33d450e..75fcb77 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
@@ -33,7 +33,7 @@
   synthetic constructor •() → self::F*
     ;
 }
-abstract class _G&Object&B = core::Object with self::B {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
index a6eac70..37866ab 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B = core::Object with self::B {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
index f2ba8da..ae76c80 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B extends core::Object implements self::B {
+abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
index f3a0cea..496e5d9 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
@@ -33,7 +33,7 @@
   synthetic constructor •() → self::F*
     ;
 }
-abstract class _G&Object&B = core::Object with self::B {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
index 15bcc2c..f22d679 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
@@ -38,7 +38,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B = core::Object with self::B {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
index 485fda2..92238fe 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
@@ -38,7 +38,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B extends core::Object implements self::B {
+abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.outline.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.outline.expect
index f7f66a7..e528298 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.outline.expect
@@ -7,7 +7,7 @@
     ;
   abstract method m(dynamic a, (dynamic, self::I::E*) →* core::String* f) → core::String*;
 }
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> /*hasConstConstructor*/  {
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
     ;
@@ -18,7 +18,7 @@
   synthetic constructor •() → self::M*
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.expect
index fcd1d67..235db8a 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.expect
@@ -15,7 +15,7 @@
     ;
   abstract method m(dynamic a, (dynamic, self::I::E*) →* core::String* f) → core::String*;
 }
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> /*hasConstConstructor*/  {
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
     ;
@@ -27,7 +27,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.transformed.expect
index fcd1d67..235db8a 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_5.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
     ;
   abstract method m(dynamic a, (dynamic, self::I::E*) →* core::String* f) → core::String*;
 }
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<self::A::E*> /*hasConstConstructor*/  {
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
     ;
@@ -27,7 +27,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.outline.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.outline.expect
index d10152ae..ae2e3bd 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.outline.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> /*hasConstConstructor*/  {
   final field self::A::E* value = null;
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
@@ -16,7 +16,7 @@
   synthetic constructor •() → self::M*
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.expect
index 62bff19..c6c1c34 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.expect
@@ -12,7 +12,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> /*hasConstConstructor*/  {
   final field self::A::E* value = null;
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
@@ -24,7 +24,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.transformed.expect
index 62bff19..c6c1c34 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements inf::I<self::A::E*> /*hasConstConstructor*/  {
   final field self::A::E* value = null;
   const constructor •() → self::A<self::A::E*>*
     : super core::Object::•()
@@ -24,7 +24,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M {
+class B<E extends core::Object* = dynamic> extends self::A<self::B::E*> implements self::M /*hasConstConstructor*/  {
   const constructor •() → self::B<self::B::E*>*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.outline.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.outline.expect
index 4b3a052..deae9bd 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.outline.expect
@@ -20,7 +20,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> /*hasConstConstructor*/  {
   final field test::A::E* value = null;
   const constructor •() → test::A<test::A::E*>*
     : super core::Object::•()
@@ -31,7 +31,7 @@
   synthetic constructor •() → test::M*
     ;
 }
-class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M {
+class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M /*hasConstConstructor*/  {
   const constructor •() → test::B<test::B::E*>*
     : super test::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.expect
index fe2a499..94b0561 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.expect
@@ -27,7 +27,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> /*hasConstConstructor*/  {
   final field test::A::E* value = null;
   const constructor •() → test::A<test::A::E*>*
     : super core::Object::•()
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M {
+class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M /*hasConstConstructor*/  {
   const constructor •() → test::B<test::B::E*>*
     : super test::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.transformed.expect
index fe2a499..94b0561 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_generic_instantiations_in_library_cycle_a.dart.strong.transformed.expect
@@ -27,7 +27,7 @@
 
 import "org-dartlang-testcase:///infer_types_on_generic_instantiations_in_library_cycle_a.dart";
 
-abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> {
+abstract class A<E extends core::Object* = dynamic> extends core::Object implements self::I<test::A::E*> /*hasConstConstructor*/  {
   final field test::A::E* value = null;
   const constructor •() → test::A<test::A::E*>*
     : super core::Object::•()
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M {
+class B<E extends core::Object* = dynamic> extends test::A<test::B::E*> implements test::M /*hasConstConstructor*/  {
   const constructor •() → test::B<test::B::E*>*
     : super test::A::•()
     ;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
index f34fca1..b62af69 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = const <self::E*>[self::E::v1];
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
index 54268ce..0ea8ae2 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
index 54268ce..0ea8ae2 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
index c337f19..21b7146 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = const <self::E*>[self::E::v1];
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
index 8286aa9..908dd56 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
index 8286aa9..908dd56 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class E extends core::Object {
+class E extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::E*>* values = #C4;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
index 07c3f61..4c1c933 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
@@ -14,7 +14,7 @@
   synthetic constructor •() → self::M1*
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::String*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::String*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.expect
index 826dbaa..4047181 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.expect
@@ -17,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::String*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::String*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.transformed.expect
index ce826f6..93f81ed 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::String*> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::String*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
index 6ad60a0..eea31bf 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
@@ -14,7 +14,7 @@
   synthetic constructor •() → self::M1*
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::int*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.expect
index 15a2b6c..80e9549 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.expect
@@ -17,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::int*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.transformed.expect
index dd85f9f..af9251c 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::int*> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
index e769695..66697a5 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
@@ -26,7 +26,7 @@
   synthetic constructor •() → self::M1*
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::Comparable<dynamic>*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::Comparable<dynamic>*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.expect
index e44fcb9..7206b5a 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.expect
@@ -29,7 +29,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::Comparable<dynamic>*> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int*, core::Comparable<dynamic>*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.transformed.expect
index d17f94c..b4286e8 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::Comparable<dynamic>*> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int*, core::Comparable<dynamic>*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M1&M0*
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
index c0a8ae0..7bcc04e 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
@@ -10,7 +10,7 @@
   synthetic constructor •() → self::J<self::J::X*>*
     ;
 }
-abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> = self::I<self::_M0&I&J::X*> with self::J<self::_M0&I&J::Y*> {
+abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> = self::I<self::_M0&I&J::X*> with self::J<self::_M0&I&J::Y*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_M0&I&J<self::_M0&I&J::X*, self::_M0&I&J::Y*>*
     : super self::I::•()
     ;
@@ -27,7 +27,7 @@
   synthetic constructor •() → self::M2*
     ;
 }
-abstract class _A&M2&M0 = self::M2 with self::M0<core::int*, core::double*> {
+abstract class _A&M2&M0 = self::M2 with self::M0<core::int*, core::double*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.expect
index a7ffa02..a700290 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.expect
@@ -12,7 +12,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> = self::I<self::_M0&I&J::X*> with self::J<self::_M0&I&J::Y*> {
+abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> = self::I<self::_M0&I&J::X*> with self::J<self::_M0&I&J::Y*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_M0&I&J<self::_M0&I&J::X*, self::_M0&I&J::Y*>*
     : super self::I::•()
     ;
@@ -32,7 +32,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 = self::M2 with self::M0<core::int*, core::double*> {
+abstract class _A&M2&M0 = self::M2 with self::M0<core::int*, core::double*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.transformed.expect
index c25154e4..847459d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> extends self::I<self::_M0&I&J::X*> implements self::J<self::_M0&I&J::Y*> {
+abstract class _M0&I&J<X extends core::Object* = dynamic, Y extends core::Object* = dynamic> extends self::I<self::_M0&I&J::X*> implements self::J<self::_M0&I&J::Y*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_M0&I&J<self::_M0&I&J::X*, self::_M0&I&J::Y*>*
     : super self::I::•()
     ;
@@ -32,7 +32,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 extends self::M2 implements self::M0<core::int*, core::double*> {
+abstract class _A&M2&M0 extends self::M2 implements self::M0<core::int*, core::double*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
index 6c5c378..6cc10f5 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
@@ -18,7 +18,7 @@
   synthetic constructor •() → self::M2<self::M2::T*>*
     ;
 }
-abstract class _A&M2&M0 = self::M2<core::int*> with self::M0<core::Map<core::int*, core::int*>*> {
+abstract class _A&M2&M0 = self::M2<core::int*> with self::M0<core::Map<core::int*, core::int*>*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.expect
index 3512c8c..ced4a8d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.expect
@@ -22,7 +22,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 = self::M2<core::int*> with self::M0<core::Map<core::int*, core::int*>*> {
+abstract class _A&M2&M0 = self::M2<core::int*> with self::M0<core::Map<core::int*, core::int*>*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.transformed.expect
index 6247867..2ddd62d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 extends self::M2<core::int*> implements self::M0<core::Map<core::int*, core::int*>*> {
+abstract class _A&M2&M0 extends self::M2<core::int*> implements self::M0<core::Map<core::int*, core::int*>*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M2&M0*
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
index 5f56095..c8dd799 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
@@ -14,7 +14,7 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> {
+abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.expect
index 62f31c1..f773d9b 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.expect
@@ -17,7 +17,7 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> {
+abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.transformed.expect
index 31c23b9..c4c5d78 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 extends self::M0<core::int*> implements self::M1<core::int*> {
+abstract class _A&M0&M1 extends self::M0<core::int*> implements self::M1<core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
index 523042e..059aa18 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
@@ -18,12 +18,12 @@
   synthetic constructor •() → self::M2<self::M2::T*>*
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> {
+abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int*> {
+abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1&M2*
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.expect
index 2ed4120..7fd2d2e 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.expect
@@ -22,12 +22,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> {
+abstract class _A&M0&M1 = self::M0<core::int*> with self::M1<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int*> {
+abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&M0&M1&M2*
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.transformed.expect
index d8f1efe..59d9df7 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.strong.transformed.expect
@@ -22,12 +22,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 extends self::M0<core::int*> implements self::M1<core::int*> {
+abstract class _A&M0&M1 extends self::M0<core::int*> implements self::M1<core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M0&M1*
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 extends self::_A&M0&M1 implements self::M2<core::int*> {
+abstract class _A&M0&M1&M2 extends self::_A&M0&M1 implements self::M2<core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_A&M0&M1&M2*
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
index d520fcd..4a322ab 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
@@ -27,12 +27,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
index 79557a6..439d8bf 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
@@ -30,12 +30,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
index 1fed224..b4b8a61 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
@@ -22,12 +22,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
index 26a4751..d0df383 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
@@ -25,12 +25,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
index 9990964..d440c3a 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
@@ -27,12 +27,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
index 468cb8ce..2643b49 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
@@ -30,12 +30,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
index acf7065..946f92c 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
@@ -29,12 +29,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
index 47897de..9389ac6 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
@@ -32,12 +32,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
index 1ce9cd4..0209712 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.outline.expect
@@ -25,7 +25,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     ;
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
index 310bddf..d38852e 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.expect
@@ -26,7 +26,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     return <self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>{};
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
index 310bddf..d38852e 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
@@ -26,7 +26,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     return <self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>{};
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
index 1ce9cd4..0209712 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.outline.expect
@@ -25,7 +25,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     ;
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
index 6895096..f5712f5 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
@@ -26,7 +26,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     return #C10;
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
index 6895096..f5712f5 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
@@ -26,7 +26,7 @@
   get v9() → core::Map<self::Foo::T*, (self::Foo::T*) →* self::Foo::T*>*
     return #C10;
 }
-class Bar<T extends core::Object* = dynamic> extends core::Object {
+class Bar<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::Bar<self::Bar::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
new file mode 100644
index 0000000..4b59c09
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract get x() → core::int*;
+  abstract set x(core::double* value) → void;
+}
+class B extends self::A {
+  field invalid-type x = null;
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
new file mode 100644
index 0000000..1f6563a
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var y;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract get x() → self::A*;
+  abstract set x(self::B* value) → void;
+  abstract get y() → self::B*;
+  abstract set y(self::A* value) → void;
+}
+abstract class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+class C extends self::B {
+  field self::A* x = null;
+  field invalid-type y = null;
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
new file mode 100644
index 0000000..cbb9102
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract set x(core::num* value) → void;
+}
+abstract class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  abstract get x() → core::int*;
+}
+class C extends self::B {
+  field invalid-type x = null;
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.outline.expect b/pkg/front_end/testcases/inference_new/switch.dart.outline.expect
index 2479571..ccbc21c 100644
--- a/pkg/front_end/testcases/inference_new/switch.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/switch.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.strong.expect b/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
index f3d6d77..8d636a2 100644
--- a/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
index f3d6d77..8d636a2 100644
--- a/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
+class C<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.outline.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.outline.expect
index baafca82..aa555ba 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
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 461a137..3259378 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
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 461a137..3259378 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
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 461a137..3259378 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
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 461a137..3259378 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect
index 5242181..bd10355 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
index c5a0a64..0cfc574 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
index c5a0a64..0cfc574 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
index c5a0a64..0cfc574 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
index c5a0a64..0cfc574 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect
index 9e91c1b..e7882ab 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
index 5129218..2a32553 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
index 5129218..2a32553 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
index 5129218..2a32553 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
index 5129218..2a32553 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect
index 9e91c1b..e7882ab 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
index 2153b49..cdd56ea 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
index 2153b49..cdd56ea 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
index 2153b49..cdd56ea 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
index 2153b49..cdd56ea 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect
index 54f0057..511d101 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
index 0c3e5d7..a133a76 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
index 0c3e5d7..a133a76 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
index 0c3e5d7..a133a76 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
index 0c3e5d7..a133a76 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect
index 8fb7e64..2ed3a81 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
index af2b2c3..3bea7e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
index af2b2c3..3bea7e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
index af2b2c3..3bea7e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
index af2b2c3..3bea7e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect
index 8fb7e64..2ed3a81 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
index a0dbc15..26f06e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
index a0dbc15..26f06e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
index a0dbc15..26f06e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
index a0dbc15..26f06e0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.outline.expect
index 755fbee..0606425 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method error() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.expect
index 27df1f8..551b8f0 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 41e1503..1f469d7 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.expect
index 27df1f8..551b8f0 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 41e1503..1f469d7 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart b/pkg/front_end/testcases/late_lowering/issue40373.dart
new file mode 100644
index 0000000..db745ee
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.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.
+
+class C {
+  num pi = 3.14;
+  late num p1 = this.pi;
+  late final p2 = this.pi;
+}
+
+main() {
+  expect(3.14, new C().p1);
+  expect(3.14, new C().p2);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.outline.expect
new file mode 100644
index 0000000..ec71902
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field core::num pi;
+  field core::num? _#C#p1;
+  field core::num? _#C#p2;
+  field dynamic _#C#p2#isSet;
+  synthetic constructor •() → self::C
+    ;
+  get p1() → core::num;
+  set p1(core::num #t1) → void;
+  get p2() → core::num;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect
new file mode 100644
index 0000000..10090e4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::num pi = 3.14;
+  field core::num? _#C#p1 = null;
+  field core::num? _#C#p2 = null;
+  field dynamic _#C#p2#isSet = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get p1() → core::num
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
+  set p1(core::num #t2) → void
+    this.{self::C::_#C#p1} = #t2;
+  get p2() → core::num
+    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+}
+static method main() → dynamic {
+  self::expect(3.14, new self::C::•().{self::C::p1});
+  self::expect(3.14, new self::C::•().{self::C::p2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect
new file mode 100644
index 0000000..10090e4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::num pi = 3.14;
+  field core::num? _#C#p1 = null;
+  field core::num? _#C#p2 = null;
+  field dynamic _#C#p2#isSet = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get p1() → core::num
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
+  set p1(core::num #t2) → void
+    this.{self::C::_#C#p1} = #t2;
+  get p2() → core::num
+    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+}
+static method main() → dynamic {
+  self::expect(3.14, new self::C::•().{self::C::p1});
+  self::expect(3.14, new self::C::•().{self::C::p2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
new file mode 100644
index 0000000..10090e4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::num pi = 3.14;
+  field core::num? _#C#p1 = null;
+  field core::num? _#C#p2 = null;
+  field dynamic _#C#p2#isSet = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get p1() → core::num
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
+  set p1(core::num #t2) → void
+    this.{self::C::_#C#p1} = #t2;
+  get p2() → core::num
+    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+}
+static method main() → dynamic {
+  self::expect(3.14, new self::C::•().{self::C::p1});
+  self::expect(3.14, new self::C::•().{self::C::p2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
new file mode 100644
index 0000000..10090e4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::num pi = 3.14;
+  field core::num? _#C#p1 = null;
+  field core::num? _#C#p2 = null;
+  field dynamic _#C#p2#isSet = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get p1() → core::num
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
+  set p1(core::num #t2) → void
+    this.{self::C::_#C#p1} = #t2;
+  get p2() → core::num
+    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+}
+static method main() → dynamic {
+  self::expect(3.14, new self::C::•().{self::C::p1});
+  self::expect(3.14, new self::C::•().{self::C::p2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart b/pkg/front_end/testcases/late_lowering/issue40373b.dart
new file mode 100644
index 0000000..25a2a5e
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.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.
+
+late final g;
+
+class C {
+  static late final s;
+  late final v;
+}
+
+main() {
+  late final l;
+
+  g = "Lily";
+  C.s = "was";
+  var c = new C();
+  c.v = "here";
+  l = "Run, Forrest, run";
+
+  expect("Lily", g);
+  expect("was", C.s);
+  expect("here", c.v);
+  expect("Run, Forrest, run", l);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.outline.expect
new file mode 100644
index 0000000..fc0f631
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  static field dynamic _#s;
+  static field core::bool _#s#isSet;
+  field dynamic _#C#v;
+  field core::bool _#C#v#isSet;
+  synthetic constructor •() → self::C
+    ;
+  static get s() → dynamic;
+  static set s(dynamic #t1) → void;
+  get v() → dynamic;
+  set v(dynamic #t2) → void;
+}
+static field dynamic _#g;
+static field core::bool _#g#isSet;
+static get g() → dynamic;
+static set g(dynamic #t3) → void;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect
new file mode 100644
index 0000000..ba0c369
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  static field dynamic _#s = null;
+  static field core::bool _#s#isSet = false;
+  field dynamic _#C#v = null;
+  field core::bool _#C#v#isSet = false;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static get s() → dynamic
+    return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateInitializationErrorImpl::•("Field 's' has not been initialized.");
+  static set s(dynamic #t1) → void
+    if(self::C::_#s#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 's' has already been initialized.");
+    else {
+      self::C::_#s#isSet = true;
+      self::C::_#s = #t1;
+    }
+  get v() → dynamic
+    return this.{self::C::_#C#v#isSet} ?{dynamic} this.{self::C::_#C#v} : throw new _in::LateInitializationErrorImpl::•("Field 'v' has not been initialized.");
+  set v(dynamic #t2) → void
+    if(this.{self::C::_#C#v#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'v' has already been initialized.");
+    else {
+      this.{self::C::_#C#v#isSet} = true;
+      this.{self::C::_#C#v} = #t2;
+    }
+}
+static field dynamic _#g = null;
+static field core::bool _#g#isSet = false;
+static get g() → dynamic
+  return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateInitializationErrorImpl::•("Field 'g' has not been initialized.");
+static set g(dynamic #t3) → void
+  if(self::_#g#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'g' has already been initialized.");
+  else {
+    self::_#g#isSet = true;
+    self::_#g = #t3;
+  }
+static method main() → dynamic {
+  final dynamic l;
+  core::bool #l#isSet = false;
+  function #l#get() → dynamic
+    return #l#isSet ?{dynamic} l : throw new _in::LateInitializationErrorImpl::•("Local 'l' has not been initialized.");
+  function #l#set(dynamic #t4) → dynamic
+    if(#l#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'l' has already been initialized.");
+    else {
+      #l#isSet = true;
+      return l = #t4;
+    }
+  self::g = "Lily";
+  self::C::s = "was";
+  self::C c = new self::C::•();
+  c.{self::C::v} = "here";
+  #l#set.call("Run, Forrest, run");
+  self::expect("Lily", self::g);
+  self::expect("was", self::C::s);
+  self::expect("here", c.{self::C::v});
+  self::expect("Run, Forrest, run", #l#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect
new file mode 100644
index 0000000..ba0c369
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  static field dynamic _#s = null;
+  static field core::bool _#s#isSet = false;
+  field dynamic _#C#v = null;
+  field core::bool _#C#v#isSet = false;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static get s() → dynamic
+    return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateInitializationErrorImpl::•("Field 's' has not been initialized.");
+  static set s(dynamic #t1) → void
+    if(self::C::_#s#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 's' has already been initialized.");
+    else {
+      self::C::_#s#isSet = true;
+      self::C::_#s = #t1;
+    }
+  get v() → dynamic
+    return this.{self::C::_#C#v#isSet} ?{dynamic} this.{self::C::_#C#v} : throw new _in::LateInitializationErrorImpl::•("Field 'v' has not been initialized.");
+  set v(dynamic #t2) → void
+    if(this.{self::C::_#C#v#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'v' has already been initialized.");
+    else {
+      this.{self::C::_#C#v#isSet} = true;
+      this.{self::C::_#C#v} = #t2;
+    }
+}
+static field dynamic _#g = null;
+static field core::bool _#g#isSet = false;
+static get g() → dynamic
+  return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateInitializationErrorImpl::•("Field 'g' has not been initialized.");
+static set g(dynamic #t3) → void
+  if(self::_#g#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'g' has already been initialized.");
+  else {
+    self::_#g#isSet = true;
+    self::_#g = #t3;
+  }
+static method main() → dynamic {
+  final dynamic l;
+  core::bool #l#isSet = false;
+  function #l#get() → dynamic
+    return #l#isSet ?{dynamic} l : throw new _in::LateInitializationErrorImpl::•("Local 'l' has not been initialized.");
+  function #l#set(dynamic #t4) → dynamic
+    if(#l#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'l' has already been initialized.");
+    else {
+      #l#isSet = true;
+      return l = #t4;
+    }
+  self::g = "Lily";
+  self::C::s = "was";
+  self::C c = new self::C::•();
+  c.{self::C::v} = "here";
+  #l#set.call("Run, Forrest, run");
+  self::expect("Lily", self::g);
+  self::expect("was", self::C::s);
+  self::expect("here", c.{self::C::v});
+  self::expect("Run, Forrest, run", #l#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect
new file mode 100644
index 0000000..ba0c369
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  static field dynamic _#s = null;
+  static field core::bool _#s#isSet = false;
+  field dynamic _#C#v = null;
+  field core::bool _#C#v#isSet = false;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static get s() → dynamic
+    return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateInitializationErrorImpl::•("Field 's' has not been initialized.");
+  static set s(dynamic #t1) → void
+    if(self::C::_#s#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 's' has already been initialized.");
+    else {
+      self::C::_#s#isSet = true;
+      self::C::_#s = #t1;
+    }
+  get v() → dynamic
+    return this.{self::C::_#C#v#isSet} ?{dynamic} this.{self::C::_#C#v} : throw new _in::LateInitializationErrorImpl::•("Field 'v' has not been initialized.");
+  set v(dynamic #t2) → void
+    if(this.{self::C::_#C#v#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'v' has already been initialized.");
+    else {
+      this.{self::C::_#C#v#isSet} = true;
+      this.{self::C::_#C#v} = #t2;
+    }
+}
+static field dynamic _#g = null;
+static field core::bool _#g#isSet = false;
+static get g() → dynamic
+  return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateInitializationErrorImpl::•("Field 'g' has not been initialized.");
+static set g(dynamic #t3) → void
+  if(self::_#g#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'g' has already been initialized.");
+  else {
+    self::_#g#isSet = true;
+    self::_#g = #t3;
+  }
+static method main() → dynamic {
+  final dynamic l;
+  core::bool #l#isSet = false;
+  function #l#get() → dynamic
+    return #l#isSet ?{dynamic} l : throw new _in::LateInitializationErrorImpl::•("Local 'l' has not been initialized.");
+  function #l#set(dynamic #t4) → dynamic
+    if(#l#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'l' has already been initialized.");
+    else {
+      #l#isSet = true;
+      return l = #t4;
+    }
+  self::g = "Lily";
+  self::C::s = "was";
+  self::C c = new self::C::•();
+  c.{self::C::v} = "here";
+  #l#set.call("Run, Forrest, run");
+  self::expect("Lily", self::g);
+  self::expect("was", self::C::s);
+  self::expect("here", c.{self::C::v});
+  self::expect("Run, Forrest, run", #l#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect
new file mode 100644
index 0000000..ba0c369
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  static field dynamic _#s = null;
+  static field core::bool _#s#isSet = false;
+  field dynamic _#C#v = null;
+  field core::bool _#C#v#isSet = false;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static get s() → dynamic
+    return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateInitializationErrorImpl::•("Field 's' has not been initialized.");
+  static set s(dynamic #t1) → void
+    if(self::C::_#s#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 's' has already been initialized.");
+    else {
+      self::C::_#s#isSet = true;
+      self::C::_#s = #t1;
+    }
+  get v() → dynamic
+    return this.{self::C::_#C#v#isSet} ?{dynamic} this.{self::C::_#C#v} : throw new _in::LateInitializationErrorImpl::•("Field 'v' has not been initialized.");
+  set v(dynamic #t2) → void
+    if(this.{self::C::_#C#v#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'v' has already been initialized.");
+    else {
+      this.{self::C::_#C#v#isSet} = true;
+      this.{self::C::_#C#v} = #t2;
+    }
+}
+static field dynamic _#g = null;
+static field core::bool _#g#isSet = false;
+static get g() → dynamic
+  return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateInitializationErrorImpl::•("Field 'g' has not been initialized.");
+static set g(dynamic #t3) → void
+  if(self::_#g#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'g' has already been initialized.");
+  else {
+    self::_#g#isSet = true;
+    self::_#g = #t3;
+  }
+static method main() → dynamic {
+  final dynamic l;
+  core::bool #l#isSet = false;
+  function #l#get() → dynamic
+    return #l#isSet ?{dynamic} l : throw new _in::LateInitializationErrorImpl::•("Local 'l' has not been initialized.");
+  function #l#set(dynamic #t4) → dynamic
+    if(#l#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'l' has already been initialized.");
+    else {
+      #l#isSet = true;
+      return l = #t4;
+    }
+  self::g = "Lily";
+  self::C::s = "was";
+  self::C c = new self::C::•();
+  c.{self::C::v} = "here";
+  #l#set.call("Run, Forrest, run");
+  self::expect("Lily", self::g);
+  self::expect("was", self::C::s);
+  self::expect("here", c.{self::C::v});
+  self::expect("Run, Forrest, run", #l#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
index 619e509..e0a070f 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
index 9b14dc5..9e5e4e1 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
index 9b14dc5..9e5e4e1 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
index 9b14dc5..9e5e4e1 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
index 9b14dc5..9e5e4e1 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
index 6fd79a1..10a2e03 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
index 126b0d7..4d78e46 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
index 126b0d7..4d78e46 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index 126b0d7..4d78e46 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index 126b0d7..4d78e46 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
index 274c943..1bf3e67 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
index 9c3f037..ea54cfd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
index 9c3f037..ea54cfd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
index 9c3f037..ea54cfd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
index 9c3f037..ea54cfd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect
index 35db692..dd0572a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
index 4499a18..6c0bb20 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
index 4499a18..6c0bb20 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
index 4499a18..6c0bb20 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
index 4499a18..6c0bb20 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect
index 81d34cf..681b16d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
index 3ccf892..883b25a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
index 3ccf892..883b25a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
index 3ccf892..883b25a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
index 3ccf892..883b25a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect
index 9cba406..02046fb 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
index f4f95e3..bb8676d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
index f4f95e3..bb8676d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
index f4f95e3..bb8676d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
index f4f95e3..bb8676d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
index e0b1ab5..159d80f 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
index 49d7ba3..aa8b4d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
index 49d7ba3..aa8b4d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
index 49d7ba3..aa8b4d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
index 49d7ba3..aa8b4d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
index d67a9a2..802698c 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
index db2ed0b..59a762a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
index db2ed0b..59a762a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
index db2ed0b..59a762a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
index db2ed0b..59a762a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect
index 81d34cf..681b16d 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
index c925621..dc6b6ad 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
index c925621..dc6b6ad 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
index c925621..dc6b6ad 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
index c925621..dc6b6ad 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect
index 9cba406..02046fb 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
index d1984d9..3d8ddf1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
index d1984d9..3d8ddf1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
index d1984d9..3d8ddf1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
index d1984d9..3d8ddf1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect
index 81d34cf..681b16d 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
index 363c922..25a5097 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
index 363c922..25a5097 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
index 363c922..25a5097 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
index 363c922..25a5097 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect
index 9cba406..02046fb 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
index 7f4cd1b..eaf2671 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
index 7f4cd1b..eaf2671 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
index 7f4cd1b..eaf2671 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
index 7f4cd1b..eaf2671 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
index 517b399..f377c7e 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
index dbfe477..6a2319d 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
index dbfe477..6a2319d 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
index dbfe477..6a2319d 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
index dbfe477..6a2319d 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
index d5e4386..b5c1e15 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
index e970906..f0bc8b7 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
index e970906..f0bc8b7 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
index e970906..f0bc8b7 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
index e970906..f0bc8b7 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect
index bccbe28..cfc71b3 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
index 9363ab8..25dee5a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
index 9363ab8..25dee5a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
index 9363ab8..25dee5a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
index 9363ab8..25dee5a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect
index 9cba406..02046fb 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
index 5b37f46..b313971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
index 5b37f46..b313971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
index 5b37f46..b313971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
index 5b37f46..b313971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.outline.expect b/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
index 25da1db..7c07f78 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -26,7 +26,7 @@
   method foo(core::int x) → dynamic
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
index 1b470d9..4646abe 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -79,7 +79,7 @@
     this.{self::A::_#A#b} = #t2;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
   const constructor •() → self::B
     : super core::Object::•()
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 d54ab7b..a0a1523 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -79,7 +79,7 @@
     this.{self::A::_#A#b} = #t2;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
index f7e7212..c886bcf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -79,7 +79,7 @@
     this.{self::A::_#A#b} = #t2;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
   const constructor •() → self::B
     : super core::Object::•()
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 3ae52e7..a7094a7 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -79,7 +79,7 @@
     this.{self::A::_#A#b} = #t2;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.outline.expect b/pkg/front_end/testcases/late_lowering/override.dart.outline.expect
index 35697bc..93117d1 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
index 2fb9901..8e2fcee 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
index 2fb9901..8e2fcee 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
index 2fb9901..8e2fcee 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
index 2fb9901..8e2fcee 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.outline.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.outline.expect
index b09c8c1..00f4708 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
index 2a08564..7b6d380 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
index 2a08564..7b6d380 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
index 2a08564..7b6d380 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
index 2a08564..7b6d380 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.outline.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.outline.expect
index 5092f40..97237ce 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.outline.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* x;
   const constructor •(core::int* x) → self::A*
     : self::A::x = x, super core::Object::•()
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
index 60b3c97..4b21762 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* x;
   const constructor •(core::int* x) → self::A*
     : self::A::x = x, super core::Object::•()
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
index 60b3c97..4b21762 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   final field core::int* x;
   const constructor •(core::int* x) → self::A*
     : self::A::x = x, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.outline.expect b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.outline.expect
index 0d12318..2602561 100644
--- a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.expect b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.expect
index ee9e3f6..88ac3ae 100644
--- a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.transformed.expect
index ee9e3f6..88ac3ae 100644
--- a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.expect b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.expect
index ee9e3f6..88ac3ae 100644
--- a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.transformed.expect
index ee9e3f6..88ac3ae 100644
--- a/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assign_type_variable.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assignability.dart.outline.expect b/pkg/front_end/testcases/nnbd/assignability.dart.outline.expect
index 14b99fd..5697d0b 100644
--- a/pkg/front_end/testcases/nnbd/assignability.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/assignability.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/assignability.dart.strong.expect b/pkg/front_end/testcases/nnbd/assignability.dart.strong.expect
index 803bc0a..9c3d453 100644
--- a/pkg/front_end/testcases/nnbd/assignability.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/assignability.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/assignability.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/assignability.dart.strong.transformed.expect
index 803bc0a..9c3d453 100644
--- a/pkg/front_end/testcases/nnbd/assignability.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/assignability.dart.weak.expect b/pkg/front_end/testcases/nnbd/assignability.dart.weak.expect
index 55036c6..ddfc6a4 100644
--- a/pkg/front_end/testcases/nnbd/assignability.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/assignability.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/assignability.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/assignability.dart.weak.transformed.expect
index 55036c6..ddfc6a4 100644
--- a/pkg/front_end/testcases/nnbd/assignability.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/call.dart.outline.expect b/pkg/front_end/testcases/nnbd/call.dart.outline.expect
index 4b7665c..49f525c 100644
--- a/pkg/front_end/testcases/nnbd/call.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/call.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/call.dart.strong.expect b/pkg/front_end/testcases/nnbd/call.dart.strong.expect
index 93617a2..886ef64 100644
--- a/pkg/front_end/testcases/nnbd/call.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/call.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/call.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/call.dart.strong.transformed.expect
index 93617a2..886ef64 100644
--- a/pkg/front_end/testcases/nnbd/call.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/call.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/call.dart.weak.expect b/pkg/front_end/testcases/nnbd/call.dart.weak.expect
index 88fb216..855a891 100644
--- a/pkg/front_end/testcases/nnbd/call.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/call.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/call.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/call.dart.weak.transformed.expect
index 88fb216..855a891 100644
--- a/pkg/front_end/testcases/nnbd/call.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/call.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.outline.expect b/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
index ff2d865..d046e9f 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "constants_lib.dart" as con;
@@ -43,7 +43,7 @@
 
 typedef F1<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 typedef F2 = <T extends core::Object* = dynamic>(T*) →* T*;
-class Class<T extends core::Object* = dynamic> extends core::Object {
+class Class<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field con::Class::T* field;
   const constructor •(con::Class::T* field) → con::Class<con::Class::T*>*
     : con::Class::field = field, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
index c787b65..12632c3 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -99,7 +99,7 @@
 
 typedef F1<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 typedef F2 = <T extends core::Object* = dynamic>(T*) →* T*;
-class Class<T extends core::Object* = dynamic> extends core::Object {
+class Class<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field con::Class::T* field;
   const constructor •(con::Class::T* field) → con::Class<con::Class::T*>*
     : con::Class::field = field, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
index c787b65..12632c3 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -99,7 +99,7 @@
 
 typedef F1<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 typedef F2 = <T extends core::Object* = dynamic>(T*) →* T*;
-class Class<T extends core::Object* = dynamic> extends core::Object {
+class Class<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field con::Class::T* field;
   const constructor •(con::Class::T* field) → con::Class<con::Class::T*>*
     : con::Class::field = field, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
index fdb1f8e..794e075 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -96,7 +96,7 @@
 
 typedef F1<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 typedef F2 = <T extends core::Object* = dynamic>(T*) →* T*;
-class Class<T extends core::Object* = dynamic> extends core::Object {
+class Class<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field con::Class::T* field;
   const constructor •(con::Class::T* field) → con::Class<con::Class::T*>*
     : con::Class::field = field, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
index fdb1f8e..794e075 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -96,7 +96,7 @@
 
 typedef F1<invariant T extends core::Object* = dynamic> = (T*) →* T*;
 typedef F2 = <T extends core::Object* = dynamic>(T*) →* T*;
-class Class<T extends core::Object* = dynamic> extends core::Object {
+class Class<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field con::Class::T* field;
   const constructor •(con::Class::T* field) → con::Class<con::Class::T*>*
     : con::Class::field = field, super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect
index 7dc40d1..3c5a7ae 100644
--- a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect
index c56d12d..c3bd5bc 100644
--- a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect
@@ -1,10 +1,19 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Error: Non-nullable variable 'x' must be assigned before it can be used.
+//   return x;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
 static method foo() → core::int {
   core::int x;
+  return (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Error: Non-nullable variable 'x' must be assigned before it can be used.
   return x;
+         ^" in x) as{TypeError,ForNonNullableByDefault} core::int;
 }
 static method bar() → core::int {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect
index c56d12d..c3bd5bc 100644
--- a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect
@@ -1,10 +1,19 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Error: Non-nullable variable 'x' must be assigned before it can be used.
+//   return x;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
 static method foo() → core::int {
   core::int x;
+  return (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Error: Non-nullable variable 'x' must be assigned before it can be used.
   return x;
+         ^" in x) as{TypeError,ForNonNullableByDefault} core::int;
 }
 static method bar() → core::int {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect
index c56d12d..176e174 100644
--- a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect
@@ -1,4 +1,11 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Warning: Non-nullable variable 'x' is used before it's assigned.
+//   return x;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect
index c56d12d..176e174 100644
--- a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect
@@ -1,4 +1,11 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart:10:10: Warning: Non-nullable variable 'x' is used before it's assigned.
+//   return x;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.outline.expect
index c33f97f..bffcb5f 100644
--- a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.expect
index 3dac54e..fe5b9b3 100644
--- a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.transformed.expect
index 3dac54e..fe5b9b3 100644
--- a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.expect
index 3dac54e..fe5b9b3 100644
--- a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.transformed.expect
index 3dac54e..fe5b9b3 100644
--- a/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/demote_closure_types.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
index 6f8ee32..3847c08 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -162,7 +162,7 @@
   synthetic constructor •() → self::Boo
     ;
 }
-abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Coo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -179,7 +179,7 @@
   synthetic constructor •() → self::Eoo
     ;
 }
-abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -193,7 +193,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -207,7 +207,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Joo&Boo&Never extends self::Boo {
+abstract class _Joo&Boo&Never extends self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Joo&Boo&Never
     : super self::Boo::•()
     ;
@@ -224,29 +224,29 @@
   synthetic constructor •() → self::Loo
     ;
 }
-abstract class Moo1 extends self::Aoo implements self::Boo {
+abstract class Moo1 extends self::Aoo implements self::Boo /*isMixinDeclaration*/  {
 }
-abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo {
+abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo2&Aoo&Boo
     ;
 }
-abstract class Moo2 extends self::_Moo2&Aoo&Boo {
+abstract class Moo2 extends self::_Moo2&Aoo&Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo3 extends core::Object implements self::Aoo, self::Boo {
+abstract class Moo3 extends core::Object implements self::Aoo, self::Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo4 extends self::Aoo {
+abstract class Moo4 extends self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo {
+abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo5&Aoo&Never
     ;
 }
-abstract class Moo5 extends self::_Moo5&Aoo&Never {
+abstract class Moo5 extends self::_Moo5&Aoo&Never /*isMixinDeclaration*/  {
 }
-abstract class Moo6 extends core::Object {
+abstract class Moo6 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class Moo7 extends core::Object implements self::Aoo {
+abstract class Moo7 extends core::Object implements self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class Moo8 extends core::Object {
+abstract class Moo8 extends core::Object /*isMixinDeclaration*/  {
 }
 class Noo = core::Object with self::Aoo {
   synthetic constructor •() → self::Noo
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
index a48c33f..443c33e 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -164,7 +164,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Coo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -184,7 +184,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -214,7 +214,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Joo&Boo&Never extends self::Boo {
+abstract class _Joo&Boo&Never extends self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Joo&Boo&Never
     : super self::Boo::•()
     ;
@@ -234,31 +234,31 @@
     : super core::Object::•()
     ;
 }
-abstract class Moo1 extends self::Aoo implements self::Boo {
+abstract class Moo1 extends self::Aoo implements self::Boo /*isMixinDeclaration*/  {
 }
-abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo {
+abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo2&Aoo&Boo
     : super core::Object::•()
     ;
 }
-abstract class Moo2 extends self::_Moo2&Aoo&Boo {
+abstract class Moo2 extends self::_Moo2&Aoo&Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo3 extends core::Object implements self::Aoo, self::Boo {
+abstract class Moo3 extends core::Object implements self::Aoo, self::Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo4 extends self::Aoo {
+abstract class Moo4 extends self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo {
+abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo5&Aoo&Never
     : super core::Object::•()
     ;
 }
-abstract class Moo5 extends self::_Moo5&Aoo&Never {
+abstract class Moo5 extends self::_Moo5&Aoo&Never /*isMixinDeclaration*/  {
 }
-abstract class Moo6 extends core::Object {
+abstract class Moo6 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class Moo7 extends core::Object implements self::Aoo {
+abstract class Moo7 extends core::Object implements self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class Moo8 extends core::Object {
+abstract class Moo8 extends core::Object /*isMixinDeclaration*/  {
 }
 class Noo = core::Object with self::Aoo {
   synthetic constructor •() → self::Noo
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
index e46d7ae..d14af9b 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -164,7 +164,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Coo&Boo&Aoo extends self::Boo implements self::Aoo {
+abstract class _Coo&Boo&Aoo extends self::Boo implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Coo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -184,7 +184,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&Boo&Aoo extends self::Boo implements self::Aoo {
+abstract class _Foo&Boo&Aoo extends self::Boo implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Foo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -194,12 +194,12 @@
     : super self::_Foo&Boo&Aoo::•()
     ;
 }
-class Goo extends self::Boo implements self::Aoo {
+class Goo extends self::Boo implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Goo
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo {
+abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,12 +209,12 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo extends core::Object implements self::Boo, self::Aoo {
+class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
 }
-abstract class _Joo&Boo&Never extends self::Boo {
+abstract class _Joo&Boo&Never extends self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Joo&Boo&Never
     : super self::Boo::•()
     ;
@@ -234,43 +234,43 @@
     : super core::Object::•()
     ;
 }
-abstract class Moo1 extends self::Aoo implements self::Boo {
+abstract class Moo1 extends self::Aoo implements self::Boo /*isMixinDeclaration*/  {
 }
-abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo {
+abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo2&Aoo&Boo
     : super core::Object::•()
     ;
 }
-abstract class Moo2 extends self::_Moo2&Aoo&Boo {
+abstract class Moo2 extends self::_Moo2&Aoo&Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo3 extends core::Object implements self::Aoo, self::Boo {
+abstract class Moo3 extends core::Object implements self::Aoo, self::Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo4 extends self::Aoo {
+abstract class Moo4 extends self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo {
+abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo5&Aoo&Never
     : super core::Object::•()
     ;
 }
-abstract class Moo5 extends self::_Moo5&Aoo&Never {
+abstract class Moo5 extends self::_Moo5&Aoo&Never /*isMixinDeclaration*/  {
 }
-abstract class Moo6 extends core::Object {
+abstract class Moo6 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class Moo7 extends core::Object implements self::Aoo {
+abstract class Moo7 extends core::Object implements self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class Moo8 extends core::Object {
+abstract class Moo8 extends core::Object /*isMixinDeclaration*/  {
 }
-class Noo extends core::Object implements self::Aoo {
+class Noo extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Noo
     : super core::Object::•()
     ;
 }
-class NooDynamic extends core::Object implements self::Aoo {
+class NooDynamic extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::NooDynamic
     : super core::Object::•()
     ;
 }
-class NooVoid extends core::Object implements self::Aoo {
+class NooVoid extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::NooVoid
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
index e72e454..6bb2ecb 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -164,7 +164,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Coo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Coo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -184,7 +184,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo {
+abstract class _Foo&Boo&Aoo = self::Boo with self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -214,7 +214,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Joo&Boo&Never extends self::Boo {
+abstract class _Joo&Boo&Never extends self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Joo&Boo&Never
     : super self::Boo::•()
     ;
@@ -234,31 +234,31 @@
     : super core::Object::•()
     ;
 }
-abstract class Moo1 extends self::Aoo implements self::Boo {
+abstract class Moo1 extends self::Aoo implements self::Boo /*isMixinDeclaration*/  {
 }
-abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo {
+abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo2&Aoo&Boo
     : super core::Object::•()
     ;
 }
-abstract class Moo2 extends self::_Moo2&Aoo&Boo {
+abstract class Moo2 extends self::_Moo2&Aoo&Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo3 extends core::Object implements self::Aoo, self::Boo {
+abstract class Moo3 extends core::Object implements self::Aoo, self::Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo4 extends self::Aoo {
+abstract class Moo4 extends self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo {
+abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo5&Aoo&Never
     : super core::Object::•()
     ;
 }
-abstract class Moo5 extends self::_Moo5&Aoo&Never {
+abstract class Moo5 extends self::_Moo5&Aoo&Never /*isMixinDeclaration*/  {
 }
-abstract class Moo6 extends core::Object {
+abstract class Moo6 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class Moo7 extends core::Object implements self::Aoo {
+abstract class Moo7 extends core::Object implements self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class Moo8 extends core::Object {
+abstract class Moo8 extends core::Object /*isMixinDeclaration*/  {
 }
 class Noo = core::Object with self::Aoo {
   synthetic constructor •() → self::Noo
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
index dffeb69b..470a8e7 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -164,7 +164,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Coo&Boo&Aoo extends self::Boo implements self::Aoo {
+abstract class _Coo&Boo&Aoo extends self::Boo implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Coo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -184,7 +184,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&Boo&Aoo extends self::Boo implements self::Aoo {
+abstract class _Foo&Boo&Aoo extends self::Boo implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Foo&Boo&Aoo
     : super self::Boo::•()
     ;
@@ -194,12 +194,12 @@
     : super self::_Foo&Boo&Aoo::•()
     ;
 }
-class Goo extends self::Boo implements self::Aoo {
+class Goo extends self::Boo implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Goo
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo {
+abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,12 +209,12 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo extends core::Object implements self::Boo, self::Aoo {
+class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
 }
-abstract class _Joo&Boo&Never extends self::Boo {
+abstract class _Joo&Boo&Never extends self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Joo&Boo&Never
     : super self::Boo::•()
     ;
@@ -234,43 +234,43 @@
     : super core::Object::•()
     ;
 }
-abstract class Moo1 extends self::Aoo implements self::Boo {
+abstract class Moo1 extends self::Aoo implements self::Boo /*isMixinDeclaration*/  {
 }
-abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo {
+abstract class _Moo2&Aoo&Boo extends core::Object implements self::Aoo, self::Boo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo2&Aoo&Boo
     : super core::Object::•()
     ;
 }
-abstract class Moo2 extends self::_Moo2&Aoo&Boo {
+abstract class Moo2 extends self::_Moo2&Aoo&Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo3 extends core::Object implements self::Aoo, self::Boo {
+abstract class Moo3 extends core::Object implements self::Aoo, self::Boo /*isMixinDeclaration*/  {
 }
-abstract class Moo4 extends self::Aoo {
+abstract class Moo4 extends self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo {
+abstract class _Moo5&Aoo&Never extends core::Object implements self::Aoo /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Moo5&Aoo&Never
     : super core::Object::•()
     ;
 }
-abstract class Moo5 extends self::_Moo5&Aoo&Never {
+abstract class Moo5 extends self::_Moo5&Aoo&Never /*isMixinDeclaration*/  {
 }
-abstract class Moo6 extends core::Object {
+abstract class Moo6 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class Moo7 extends core::Object implements self::Aoo {
+abstract class Moo7 extends core::Object implements self::Aoo /*isMixinDeclaration*/  {
 }
-abstract class Moo8 extends core::Object {
+abstract class Moo8 extends core::Object /*isMixinDeclaration*/  {
 }
-class Noo extends core::Object implements self::Aoo {
+class Noo extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Noo
     : super core::Object::•()
     ;
 }
-class NooDynamic extends core::Object implements self::Aoo {
+class NooDynamic extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::NooDynamic
     : super core::Object::•()
     ;
 }
-class NooVoid extends core::Object implements self::Aoo {
+class NooVoid extends core::Object implements self::Aoo /*isEliminatedMixin*/  {
   synthetic constructor •() → self::NooVoid
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.outline.expect b/pkg/front_end/testcases/nnbd/forin.dart.outline.expect
index 33cd4d6..6232118 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.strong.expect b/pkg/front_end/testcases/nnbd/forin.dart.strong.expect
index 0f795fe..d6e6324 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 ac3b55d..b65a75c 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.weak.expect b/pkg/front_end/testcases/nnbd/forin.dart.weak.expect
index 7a50a15..36438f5 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 39aa91b..d263365 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart b/pkg/front_end/testcases/nnbd/function_types.dart
index 67c0108..d9bb916 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart
+++ b/pkg/front_end/testcases/nnbd/function_types.dart
@@ -18,7 +18,7 @@
 }
 
 main() {
-  void Function() g;
+  void Function() g = () {};
   void Function()? f = g;
 
   var fBar = bar();
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
index 56f5079..39a0f40 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
index 7531780..639f4a9 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -27,7 +27,7 @@
 static method foobar(() →? dynamic x) → () →? dynamic
   return null;
 static method main() → dynamic {
-  () → void g;
+  () → void g = () → core::Null? {};
   () →? void f = g;
   () → void fBar = self::bar();
   () →? void fBaz = self::baz();
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
index 7531780..639f4a9 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -27,7 +27,7 @@
 static method foobar(() →? dynamic x) → () →? dynamic
   return null;
 static method main() → dynamic {
-  () → void g;
+  () → void g = () → core::Null? {};
   () →? void f = g;
   () → void fBar = self::bar();
   () →? void fBaz = self::baz();
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
index 7531780..639f4a9 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -27,7 +27,7 @@
 static method foobar(() →? dynamic x) → () →? dynamic
   return null;
 static method main() → dynamic {
-  () → void g;
+  () → void g = () → core::Null? {};
   () →? void f = g;
   () → void fBar = self::bar();
   () →? void fBaz = self::baz();
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
index 7531780..639f4a9 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -27,7 +27,7 @@
 static method foobar(() →? dynamic x) → () →? dynamic
   return null;
 static method main() → dynamic {
-  () → void g;
+  () → void g = () → core::Null? {};
   () →? void f = g;
   () → void fBar = self::bar();
   () →? void fBaz = self::baz();
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
index acb7609..0221dc8 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
index dfb0fb2..be101f6 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
index dfb0fb2..be101f6 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
index dfb0fb2..be101f6 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
index dfb0fb2..be101f6 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.outline.expect
index 4706d9d..8ab794b 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -9,7 +9,7 @@
 static method main() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 import self as self2;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.expect
index 840dfca..ff3f272 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_in_lib.dart" as inf;
@@ -17,7 +17,7 @@
   core::print(self::reify<() → inf::Foo>(z));
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inf;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.transformed.expect
index 840dfca..ff3f272 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_in_lib.dart" as inf;
@@ -17,7 +17,7 @@
   core::print(self::reify<() → inf::Foo>(z));
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inf;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.expect
index 840dfca..ff3f272 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_in_lib.dart" as inf;
@@ -17,7 +17,7 @@
   core::print(self::reify<() → inf::Foo>(z));
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inf;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.transformed.expect
index 840dfca..ff3f272 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_in.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_in_lib.dart" as inf;
@@ -17,7 +17,7 @@
   core::print(self::reify<() → inf::Foo>(z));
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inf;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.outline.expect
index d160bcf..ffc3253 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.expect
index b217fb1..99987735 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_out_lib.dart" as inf;
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.transformed.expect
index b217fb1..99987735 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_out_lib.dart" as inf;
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.expect
index b217fb1..99987735 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_out_lib.dart" as inf;
diff --git a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.transformed.expect
index b217fb1..99987735 100644
--- a/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_from_opt_out.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "infer_from_opt_out_lib.dart" as inf;
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.outline.expect
index b4b9798..1c9be60 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.expect
index 37919d9..ac0794c 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
index 37919d9..ac0794c 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.expect
index 37919d9..ac0794c 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
index 37919d9..ac0794c 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.outline.expect
index 990cd89..039586e0 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.outline.expect
@@ -74,7 +74,7 @@
     ;
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inh;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.strong.expect
index b0151bf..8edb631 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.strong.expect
@@ -86,7 +86,7 @@
     ;
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inh;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.weak.expect
index b0151bf..8edb631 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_in.dart.weak.expect
@@ -86,7 +86,7 @@
     ;
 }
 
-library;
+library /*isNonNullableByDefault*/;
 import self as inh;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
index bc326ca..dafa598 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "inheritance_from_opt_out_lib.dart" as inh;
 import "dart:core" as core;
@@ -72,7 +72,7 @@
   synthetic constructor •() → inh::LegacyClass5<inh::LegacyClass5::T*>*
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
   synthetic constructor •() → inh::LegacyClass7<inh::LegacyClass7::T*>*
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
index 3c23fa9..8706c95 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "inheritance_from_opt_out_lib.dart" as inh;
 import "dart:core" as core;
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
index 7104872..187a284 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "inheritance_from_opt_out_lib.dart" as inh;
 import "dart:core" as core;
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
index 3c23fa9..8706c95 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "inheritance_from_opt_out_lib.dart" as inh;
 import "dart:core" as core;
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
index 7104872..187a284 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "inheritance_from_opt_out_lib.dart" as inh;
 import "dart:core" as core;
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
index d27719d..2359ed4 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
index 977e568..05572ee 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
index 977e568..05572ee 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.expect
index 977e568..05572ee 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.transformed.expect
index 977e568..05572ee 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39659.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue39659.dart.outline.expect
index 896fae3..e9150e2 100644
--- a/pkg/front_end/testcases/nnbd/issue39659.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue39659.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39659.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue39659.dart.strong.expect
index 10cdb88..910ce4f 100644
--- a/pkg/front_end/testcases/nnbd/issue39659.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue39659.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue39659.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue39659.dart.strong.transformed.expect
index 10cdb88..910ce4f 100644
--- a/pkg/front_end/testcases/nnbd/issue39659.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue39659.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue39659.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue39659.dart.weak.expect
index 5d169f7..0579729 100644
--- a/pkg/front_end/testcases/nnbd/issue39659.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue39659.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue39659.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue39659.dart.weak.transformed.expect
index 5d169f7..0579729 100644
--- a/pkg/front_end/testcases/nnbd/issue39659.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue39659.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.outline.expect
index bbacb29..bc24ff1 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.strong.expect
index a838ef1..14a6598 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.strong.transformed.expect
index a838ef1..14a6598 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
index a838ef1..14a6598 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
index a838ef1..14a6598 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.outline.expect
index 755fbee..0606425 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method error() → dynamic
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.expect
index 2d29b22..44e9546 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 e732a36..83177be 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.expect
index 2d29b22..44e9546 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 e732a36..83177be 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/issue40134.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40134.dart.outline.expect
index 4da8085..f26dd6e 100644
--- a/pkg/front_end/testcases/nnbd/issue40134.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue40134.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue40134.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40134.dart.strong.expect
index e1c88be..0389f74 100644
--- a/pkg/front_end/testcases/nnbd/issue40134.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue40134.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue40134.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40134.dart.strong.transformed.expect
index e1c88be..0389f74 100644
--- a/pkg/front_end/testcases/nnbd/issue40134.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40134.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue40134.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40134.dart.weak.expect
index e1c88be..0389f74 100644
--- a/pkg/front_end/testcases/nnbd/issue40134.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue40134.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue40134.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40134.dart.weak.transformed.expect
index e1c88be..0389f74 100644
--- a/pkg/front_end/testcases/nnbd/issue40134.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40134.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect
index 2874413..5e60610 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect
index ae125e8..ac11cde 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect
index ae125e8..ac11cde 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.expect
index ae125e8..ac11cde 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.transformed.expect
index ae125e8..ac11cde 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect
index 8872e99..1a9d471 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect
index 57d21df..e8d7ee9 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.expect
@@ -1,4 +1,16 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:14: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:24: Warning: Operand of null-aware operation '!' has type 'C' which excludes null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/issue_39286_2.dart'.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//                        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect
index 57d21df..e8d7ee9 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.strong.transformed.expect
@@ -1,4 +1,16 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:14: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:24: Warning: Operand of null-aware operation '!' has type 'C' which excludes null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/issue_39286_2.dart'.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//                        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.expect
index 57d21df..e8d7ee9 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.expect
@@ -1,4 +1,16 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:14: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:24: Warning: Operand of null-aware operation '!' has type 'C' which excludes null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/issue_39286_2.dart'.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//                        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.transformed.expect
index 57d21df..e8d7ee9 100644
--- a/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue_39286_2.dart.weak.transformed.expect
@@ -1,4 +1,16 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:14: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue_39286_2.dart:15:24: Warning: Operand of null-aware operation '!' has type 'C' which excludes null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/issue_39286_2.dart'.
+//   x..f()!.g()['Hi!']!..h()!.y = 2;
+//                        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/late.dart.outline.expect b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
index 88ea1d5..afcd786 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
index 854f872..aa6f48b 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
index 854f872..aa6f48b 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/late.dart.weak.expect b/pkg/front_end/testcases/nnbd/late.dart.weak.expect
index 854f872..aa6f48b 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
index 854f872..aa6f48b 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/later.dart.outline.expect b/pkg/front_end/testcases/nnbd/later.dart.outline.expect
index c3b7544..6e60e3f 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -23,7 +23,7 @@
   method foo(core::int x) → dynamic
     ;
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   late final field core::int x = 42;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index e96accc..dc130bf 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -74,7 +74,7 @@
     ;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   late final field core::int x = 42;
   const constructor •() → self::B
     : super core::Object::•()
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 982ee0c..b552816 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -75,7 +75,7 @@
     ;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   late final field core::int x = 42;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index 09e7b68..ec03818 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -74,7 +74,7 @@
     ;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   late final field core::int x = 42;
   const constructor •() → self::B
     : super core::Object::•()
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 c96bcbb..92d0bcf 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -75,7 +75,7 @@
     ;
   method foo(core::int x) → dynamic {}
 }
-class B extends core::Object {
+class B extends core::Object /*hasConstConstructor*/  {
   late final field core::int x = 42;
   const constructor •() → self::B
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.outline.expect b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.outline.expect
index 5fe8d31..5b45a7e 100644
--- a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.expect
index 635fce3..b8f0b54 100644
--- a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.transformed.expect
index 635fce3..b8f0b54 100644
--- a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.expect
index 635fce3..b8f0b54 100644
--- a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.transformed.expect
index 635fce3..b8f0b54 100644
--- a/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/lhs_of_if_null.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect
index 00f17da..b622770 100644
--- a/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect
index 788fdeb..5cc723c 100644
--- a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect
index 64a625b..78ee25b 100644
--- a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect
index e72bdc9..4b2756e 100644
--- a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect
index eda5511..80f0ed3 100644
--- a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
index dcd675f..331438b 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
@@ -75,7 +75,7 @@
 static method main() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 import self as mem;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
index c6a3171..a926f8b 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
@@ -71,7 +71,7 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as mem;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
index c6a3171..a926f8b 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as mem;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
index c6a3171..a926f8b 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
@@ -71,7 +71,7 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as mem;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
index c6a3171..a926f8b 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
@@ -71,7 +71,7 @@
 }
 static method main() → dynamic {}
 
-library;
+library /*isNonNullableByDefault*/;
 import self as mem;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
index 50ad3f4..bf466c5 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
@@ -1,4 +1,4 @@
-library main;
+library main /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
index 20453f0..85e1534 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
@@ -1,4 +1,4 @@
-library main;
+library main /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
index 20453f0..85e1534 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library main;
+library main /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
index 20453f0..85e1534 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
@@ -1,4 +1,4 @@
-library main;
+library main /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
index 20453f0..85e1534 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library main;
+library main /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.outline.expect
index a1fe8bf..32b8bce 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.strong.expect
index 123a821..02f979f 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.weak.expect
index 123a821..02f979f 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_in.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.outline.expect
index 5dc40b0..346613a 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.outline.expect
@@ -80,7 +80,7 @@
 static method testOptOut() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.strong.expect
index 2b26e9b..828c85b 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.strong.expect
@@ -125,7 +125,7 @@
               ^" in mes::nonNullableVar as{TypeError} core::String*;
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.weak.expect
index 2b26e9b..828c85b 100644
--- a/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/messages_with_types_opt_out.dart.weak.expect
@@ -125,7 +125,7 @@
               ^" in mes::nonNullableVar as{TypeError} core::String*;
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.outline.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.outline.expect
index 18f2365..e04c31a 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
index 46eca1c..cf64382 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
index 46eca1c..cf64382 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.expect
index de95e8d..0a032ba 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.transformed.expect
index de95e8d..0a032ba 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart
new file mode 100644
index 0000000..1de618f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.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
+
+import 'mixin_from_opt_in_lib.dart';
+
+class Class extends Object with Mixin {}
+
+main() {
+  print(new Class().method(null));
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..36ff7da
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_in_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin*
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class*
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+}
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin
+    ;
+  method method(core::int? i) → core::int
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..f71915b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_in_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin*
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Object&Mixin::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{self::Class::method}(null));
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..7dd0788
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_in_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
+
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin*
+    : super core::Object::•()
+    ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_in_lib.dart */ method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Object&Mixin::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{self::Class::method}(null));
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t2 = i in #t2.{core::num::==}(null) ?{core::int} 0 : #t2{core::int};
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..f71915b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_in_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin*
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Object&Mixin::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{self::Class::method}(null));
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..7dd0788
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_in_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
+
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin*
+    : super core::Object::•()
+    ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_in_lib.dart */ method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Object&Mixin::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{self::Class::method}(null));
+}
+
+library /*isNonNullableByDefault*/;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t2 = i in #t2.{core::num::==}(null) ?{core::int} 0 : #t2{core::int};
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_lib.dart
new file mode 100644
index 0000000..5159fb1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Mixin {
+  int method(int? i) => i ?? 0;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart
new file mode 100644
index 0000000..b5433d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.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 'mixin_from_opt_out_lib.dart';
+
+class Class extends Object with Mixin {}
+
+main() {
+  print(new Class().method(null));
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..7e6b375
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_out_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class
+    ;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin*
+    ;
+  method method(core::int* i) → core::int*
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..342e2d1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_out_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Object&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{mix::Mixin::method}(null));
+}
+
+library;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin*
+    : super core::Object::•()
+    ;
+  method method(core::int* i) → core::int*
+    return let final core::int* #t1 = i in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..8106b0b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_out_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
+
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin
+    : super core::Object::•()
+    ;
+  method /*isNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ method(core::int* i) → core::int*
+    return let final core::int* #t1 = i in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Object&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{mix::Mixin::method}(null));
+}
+
+library;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin*
+    : super core::Object::•()
+    ;
+  method method(core::int* i) → core::int*
+    return let final core::int* #t2 = i in #t2.{core::num::==}(null) ?{core::int*} 0 : #t2;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect
new file mode 100644
index 0000000..342e2d1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_out_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
+
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin
+    : super core::Object::•()
+    ;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Object&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{mix::Mixin::method}(null));
+}
+
+library;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin*
+    : super core::Object::•()
+    ;
+  method method(core::int* i) → core::int*
+    return let final core::int* #t1 = i in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..8106b0b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "mixin_from_opt_out_lib.dart" as mix;
+
+import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
+
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  const synthetic constructor •() → self::_Class&Object&Mixin
+    : super core::Object::•()
+    ;
+  method /*isNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ method(core::int* i) → core::int*
+    return let final core::int* #t1 = i in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+}
+class Class extends self::_Class&Object&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Object&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::Class::•().{mix::Mixin::method}(null));
+}
+
+library;
+import self as mix;
+import "dart:core" as core;
+
+class Mixin extends core::Object {
+  synthetic constructor •() → mix::Mixin*
+    : super core::Object::•()
+    ;
+  method method(core::int* i) → core::int*
+    return let final core::int* #t2 = i in #t2.{core::num::==}(null) ?{core::int*} 0 : #t2;
+}
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out_lib.dart b/pkg/front_end/testcases/nnbd/mixin_from_opt_out_lib.dart
new file mode 100644
index 0000000..fd695de
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out_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.
+
+// @dart=2.6
+
+class Mixin {
+  int method(int i) => i ?? 0;
+}
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart b/pkg/front_end/testcases/nnbd/never_opt_out.dart
new file mode 100644
index 0000000..1d9981b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.6
+
+import 'never_opt_out_lib.dart';
+
+Never optOutNever;
+var inferredOptOutNever = optInNever;
+
+main() {
+  Never localNever = null;
+  Null localNull = null;
+  var inferredLocalNever = optInNever;
+
+  localNever = localNever;
+  optOutNever = localNever;
+  optInNever = localNever;
+  localNull = localNever;
+  inferredOptOutNever = localNever;
+  inferredLocalNever = localNever;
+
+  localNever = optOutNever;
+  optOutNever = optOutNever;
+  optInNever = optOutNever;
+  localNull = optOutNever;
+  inferredOptOutNever = optOutNever;
+  inferredLocalNever = optOutNever;
+
+  localNever = optInNever;
+  optOutNever = optInNever;
+  optInNever = optInNever;
+  localNull = optInNever;
+  inferredOptOutNever = optInNever;
+  inferredLocalNever = optInNever;
+
+  localNever = localNull;
+  optOutNever = localNull;
+  optInNever = localNull;
+  localNull = localNull;
+  inferredOptOutNever = localNull;
+  inferredLocalNever = localNull;
+
+  localNever = inferredOptOutNever;
+  optOutNever = inferredOptOutNever;
+  optInNever = inferredOptOutNever;
+  localNull = inferredOptOutNever;
+  inferredOptOutNever = inferredOptOutNever;
+  inferredLocalNever = inferredOptOutNever;
+
+  localNever = inferredLocalNever;
+  optOutNever = inferredLocalNever;
+  optInNever = inferredLocalNever;
+  localNull = inferredLocalNever;
+  inferredOptOutNever = inferredLocalNever;
+  inferredLocalNever = inferredLocalNever;
+
+  throws(() => optOutNever = throwing());
+  throws(() => localNever = throwing());
+  throws(() => optOutNever = throwing());
+  throws(() => optInNever = throwing());
+  throws(() => inferredOptOutNever = throwing());
+  throws(() => inferredLocalNever = throwing());
+}
+
+class B extends A {
+  Null neverField;
+  Null neverMethod(Null value) => value;
+  Null get neverProperty => null;
+  void set neverProperty(Null value) {}
+
+  Null nullField;
+  Null nullMethod(Null value) => value;
+  Null get nullProperty => null;
+  void set nullProperty(Null value) {}
+}
+
+class C extends A {
+  Never neverField;
+  Never neverMethod(Never value) => value;
+  Never get neverProperty => null;
+  void set neverProperty(Never value) {}
+
+  Never nullField;
+  Never nullMethod(Never value) => value;
+  Never get nullProperty => null;
+  void set nullProperty(Never value) {}
+}
+
+throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.outline.expect
new file mode 100644
index 0000000..b2ec5db
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.outline.expect
@@ -0,0 +1,77 @@
+library;
+import self as self;
+import "never_opt_out_lib.dart" as nev;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///never_opt_out_lib.dart";
+
+class B extends nev::A {
+  field core::Null? neverField;
+  field core::Null? nullField;
+  synthetic constructor •() → self::B*
+    ;
+  method neverMethod(core::Null? value) → core::Null?
+    ;
+  get neverProperty() → core::Null?
+    ;
+  set neverProperty(core::Null? value) → void
+    ;
+  method nullMethod(core::Null? value) → core::Null?
+    ;
+  get nullProperty() → core::Null?
+    ;
+  set nullProperty(core::Null? value) → void
+    ;
+}
+class C extends nev::A {
+  field Never* neverField;
+  field Never* nullField;
+  synthetic constructor •() → self::C*
+    ;
+  method neverMethod(Never* value) → Never*
+    ;
+  get neverProperty() → Never*
+    ;
+  set neverProperty(Never* value) → void
+    ;
+  method nullMethod(Never* value) → Never*
+    ;
+  get nullProperty() → Never*
+    ;
+  set nullProperty(Never* value) → void
+    ;
+}
+static field Never* optOutNever;
+static field core::Null? inferredOptOutNever;
+static method main() → dynamic
+  ;
+static method throws(() →* void f) → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as nev;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///never_opt_out.dart";
+
+class A extends core::Object {
+  field Never neverField;
+  field core::Null? nullField;
+  synthetic constructor •() → nev::A
+    ;
+  method neverMethod(Never value) → Never
+    ;
+  get neverProperty() → Never
+    ;
+  set neverProperty(Never value) → void
+    ;
+  method nullMethod(core::Null? value) → core::Null?
+    ;
+  get nullProperty() → core::Null?
+    ;
+  set nullProperty(core::Null? value) → void
+    ;
+}
+static field Never optInNever;
+static method throwing() → Never
+  ;
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect
new file mode 100644
index 0000000..0fb13f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect
@@ -0,0 +1,138 @@
+library;
+import self as self;
+import "never_opt_out_lib.dart" as nev;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///never_opt_out_lib.dart";
+
+class B extends nev::A {
+  field core::Null? neverField = null;
+  field core::Null? nullField = null;
+  synthetic constructor •() → self::B*
+    : super nev::A::•()
+    ;
+  method neverMethod(core::Null? value) → core::Null?
+    return value;
+  get neverProperty() → core::Null?
+    return null;
+  set neverProperty(core::Null? value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return null;
+  set nullProperty(core::Null? value) → void {}
+}
+class C extends nev::A {
+  field Never* neverField = null;
+  field Never* nullField = null;
+  synthetic constructor •() → self::C*
+    : super nev::A::•()
+    ;
+  method neverMethod(Never* value) → Never*
+    return value;
+  get neverProperty() → Never*
+    return null;
+  set neverProperty(Never* value) → void {}
+  method nullMethod(Never* value) → Never*
+    return value;
+  get nullProperty() → Never*
+    return null;
+  set nullProperty(Never* value) → void {}
+}
+static field Never* optOutNever;
+static field core::Null? inferredOptOutNever = nev::optInNever;
+static method main() → dynamic {
+  Never* localNever = null;
+  core::Null? localNull = null;
+  Never inferredLocalNever = nev::optInNever;
+  localNever = localNever;
+  self::optOutNever = localNever;
+  nev::optInNever = localNever;
+  localNull = localNever;
+  self::inferredOptOutNever = localNever;
+  inferredLocalNever = localNever;
+  localNever = self::optOutNever;
+  self::optOutNever = self::optOutNever;
+  nev::optInNever = self::optOutNever;
+  localNull = self::optOutNever;
+  self::inferredOptOutNever = self::optOutNever;
+  inferredLocalNever = self::optOutNever;
+  localNever = nev::optInNever;
+  self::optOutNever = nev::optInNever;
+  nev::optInNever = nev::optInNever;
+  localNull = nev::optInNever;
+  self::inferredOptOutNever = nev::optInNever;
+  inferredLocalNever = nev::optInNever;
+  localNever = localNull;
+  self::optOutNever = localNull;
+  nev::optInNever = localNull as{TypeError} Never;
+  localNull = localNull;
+  self::inferredOptOutNever = localNull;
+  inferredLocalNever = localNull as{TypeError} Never;
+  localNever = self::inferredOptOutNever;
+  self::optOutNever = self::inferredOptOutNever;
+  nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
+  localNull = self::inferredOptOutNever;
+  self::inferredOptOutNever = self::inferredOptOutNever;
+  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  localNever = inferredLocalNever;
+  self::optOutNever = inferredLocalNever;
+  nev::optInNever = inferredLocalNever;
+  localNull = inferredLocalNever;
+  self::inferredOptOutNever = inferredLocalNever;
+  inferredLocalNever = inferredLocalNever;
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => localNever = nev::throwing());
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => nev::optInNever = nev::throwing());
+  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never => inferredLocalNever = nev::throwing());
+}
+static method throws(() →* void f) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be assigned to a variable of type 'Null?'.
+//  - 'Type' is from 'dart:core'.
+//   Null get nullProperty => Null;
+//                            ^
+//
+import self as nev;
+import "dart:core" as core;
+import "never_opt_out.dart" as self;
+
+import "org-dartlang-testcase:///never_opt_out.dart";
+
+class A extends core::Object {
+  field Never neverField = throw "Should not reach here";
+  field core::Null? nullField = null;
+  synthetic constructor •() → nev::A
+    : super core::Object::•()
+    ;
+  method neverMethod(Never value) → Never
+    return value;
+  get neverProperty() → Never
+    return throw "Should not reach here";
+  set neverProperty(Never value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be assigned to a variable of type 'Null?'.
+ - 'Type' is from 'dart:core'.
+  Null get nullProperty => Null;
+                           ^" in core::Null? as{TypeError,ForNonNullableByDefault} core::Null?;
+  set nullProperty(core::Null? value) → void {}
+}
+static field Never optInNever = self::optOutNever;
+static method throwing() → Never
+  return throw "Never!";
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..bf726fb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,75 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "never_opt_out_lib.dart" as nev;
+
+import "org-dartlang-testcase:///never_opt_out_lib.dart";
+
+static field Never* optOutNever;
+static field core::Null? inferredOptOutNever = nev::optInNever;
+static method main() → dynamic {
+  Never* localNever = null;
+  core::Null? localNull = null;
+  Never inferredLocalNever = nev::optInNever;
+  localNever = localNever;
+  self::optOutNever = localNever;
+  nev::optInNever = localNever;
+  localNull = localNever;
+  self::inferredOptOutNever = localNever;
+  inferredLocalNever = localNever;
+  localNever = self::optOutNever;
+  self::optOutNever = self::optOutNever;
+  nev::optInNever = self::optOutNever;
+  localNull = self::optOutNever;
+  self::inferredOptOutNever = self::optOutNever;
+  inferredLocalNever = self::optOutNever;
+  localNever = nev::optInNever;
+  self::optOutNever = nev::optInNever;
+  nev::optInNever = nev::optInNever;
+  localNull = nev::optInNever;
+  self::inferredOptOutNever = nev::optInNever;
+  inferredLocalNever = nev::optInNever;
+  localNever = localNull;
+  self::optOutNever = localNull;
+  nev::optInNever = localNull as{TypeError} Never;
+  localNull = localNull;
+  self::inferredOptOutNever = localNull;
+  inferredLocalNever = localNull as{TypeError} Never;
+  localNever = self::inferredOptOutNever;
+  self::optOutNever = self::inferredOptOutNever;
+  nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
+  localNull = self::inferredOptOutNever;
+  self::inferredOptOutNever = self::inferredOptOutNever;
+  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  localNever = inferredLocalNever;
+  self::optOutNever = inferredLocalNever;
+  nev::optInNever = inferredLocalNever;
+  localNull = inferredLocalNever;
+  self::inferredOptOutNever = inferredLocalNever;
+  inferredLocalNever = inferredLocalNever;
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => localNever = nev::throwing());
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => nev::optInNever = nev::throwing());
+  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never => inferredLocalNever = nev::throwing());
+}
+static method throws(() →* void f) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as nev;
+import "never_opt_out.dart" as self;
+
+import "org-dartlang-testcase:///never_opt_out.dart";
+
+static field Never optInNever = self::optOutNever;
+static method throwing() → Never
+  return throw "Never!";
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect
new file mode 100644
index 0000000..e4651a2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect
@@ -0,0 +1,135 @@
+library;
+import self as self;
+import "never_opt_out_lib.dart" as nev;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///never_opt_out_lib.dart";
+
+class B extends nev::A {
+  field core::Null? neverField = null;
+  field core::Null? nullField = null;
+  synthetic constructor •() → self::B*
+    : super nev::A::•()
+    ;
+  method neverMethod(core::Null? value) → core::Null?
+    return value;
+  get neverProperty() → core::Null?
+    return null;
+  set neverProperty(core::Null? value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return null;
+  set nullProperty(core::Null? value) → void {}
+}
+class C extends nev::A {
+  field Never* neverField = null;
+  field Never* nullField = null;
+  synthetic constructor •() → self::C*
+    : super nev::A::•()
+    ;
+  method neverMethod(Never* value) → Never*
+    return value;
+  get neverProperty() → Never*
+    return null;
+  set neverProperty(Never* value) → void {}
+  method nullMethod(Never* value) → Never*
+    return value;
+  get nullProperty() → Never*
+    return null;
+  set nullProperty(Never* value) → void {}
+}
+static field Never* optOutNever;
+static field core::Null? inferredOptOutNever = nev::optInNever;
+static method main() → dynamic {
+  Never* localNever = null;
+  core::Null? localNull = null;
+  Never inferredLocalNever = nev::optInNever;
+  localNever = localNever;
+  self::optOutNever = localNever;
+  nev::optInNever = localNever;
+  localNull = localNever;
+  self::inferredOptOutNever = localNever;
+  inferredLocalNever = localNever;
+  localNever = self::optOutNever;
+  self::optOutNever = self::optOutNever;
+  nev::optInNever = self::optOutNever;
+  localNull = self::optOutNever;
+  self::inferredOptOutNever = self::optOutNever;
+  inferredLocalNever = self::optOutNever;
+  localNever = nev::optInNever;
+  self::optOutNever = nev::optInNever;
+  nev::optInNever = nev::optInNever;
+  localNull = nev::optInNever;
+  self::inferredOptOutNever = nev::optInNever;
+  inferredLocalNever = nev::optInNever;
+  localNever = localNull;
+  self::optOutNever = localNull;
+  nev::optInNever = localNull as{TypeError} Never;
+  localNull = localNull;
+  self::inferredOptOutNever = localNull;
+  inferredLocalNever = localNull as{TypeError} Never;
+  localNever = self::inferredOptOutNever;
+  self::optOutNever = self::inferredOptOutNever;
+  nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
+  localNull = self::inferredOptOutNever;
+  self::inferredOptOutNever = self::inferredOptOutNever;
+  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  localNever = inferredLocalNever;
+  self::optOutNever = inferredLocalNever;
+  nev::optInNever = inferredLocalNever;
+  localNull = inferredLocalNever;
+  self::inferredOptOutNever = inferredLocalNever;
+  inferredLocalNever = inferredLocalNever;
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => localNever = nev::throwing());
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => nev::optInNever = nev::throwing());
+  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never => inferredLocalNever = nev::throwing());
+}
+static method throws(() →* void f) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Warning: Assigning value of type 'Type' to a variable of type 'Null?'.
+//  - 'Type' is from 'dart:core'.
+//   Null get nullProperty => Null;
+//                            ^
+//
+import self as nev;
+import "dart:core" as core;
+import "never_opt_out.dart" as self;
+
+import "org-dartlang-testcase:///never_opt_out.dart";
+
+class A extends core::Object {
+  field Never neverField = throw "Should not reach here";
+  field core::Null? nullField = null;
+  synthetic constructor •() → nev::A
+    : super core::Object::•()
+    ;
+  method neverMethod(Never value) → Never
+    return value;
+  get neverProperty() → Never
+    return throw "Should not reach here";
+  set neverProperty(Never value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return core::Null? as{TypeError,ForNonNullableByDefault} core::Null?;
+  set nullProperty(core::Null? value) → void {}
+}
+static field Never optInNever = self::optOutNever;
+static method throwing() → Never
+  return throw "Never!";
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..bf726fb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,75 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "never_opt_out_lib.dart" as nev;
+
+import "org-dartlang-testcase:///never_opt_out_lib.dart";
+
+static field Never* optOutNever;
+static field core::Null? inferredOptOutNever = nev::optInNever;
+static method main() → dynamic {
+  Never* localNever = null;
+  core::Null? localNull = null;
+  Never inferredLocalNever = nev::optInNever;
+  localNever = localNever;
+  self::optOutNever = localNever;
+  nev::optInNever = localNever;
+  localNull = localNever;
+  self::inferredOptOutNever = localNever;
+  inferredLocalNever = localNever;
+  localNever = self::optOutNever;
+  self::optOutNever = self::optOutNever;
+  nev::optInNever = self::optOutNever;
+  localNull = self::optOutNever;
+  self::inferredOptOutNever = self::optOutNever;
+  inferredLocalNever = self::optOutNever;
+  localNever = nev::optInNever;
+  self::optOutNever = nev::optInNever;
+  nev::optInNever = nev::optInNever;
+  localNull = nev::optInNever;
+  self::inferredOptOutNever = nev::optInNever;
+  inferredLocalNever = nev::optInNever;
+  localNever = localNull;
+  self::optOutNever = localNull;
+  nev::optInNever = localNull as{TypeError} Never;
+  localNull = localNull;
+  self::inferredOptOutNever = localNull;
+  inferredLocalNever = localNull as{TypeError} Never;
+  localNever = self::inferredOptOutNever;
+  self::optOutNever = self::inferredOptOutNever;
+  nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
+  localNull = self::inferredOptOutNever;
+  self::inferredOptOutNever = self::inferredOptOutNever;
+  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  localNever = inferredLocalNever;
+  self::optOutNever = inferredLocalNever;
+  nev::optInNever = inferredLocalNever;
+  localNull = inferredLocalNever;
+  self::inferredOptOutNever = inferredLocalNever;
+  inferredLocalNever = inferredLocalNever;
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => localNever = nev::throwing());
+  self::throws(() → Never => self::optOutNever = nev::throwing());
+  self::throws(() → Never => nev::optInNever = nev::throwing());
+  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never => inferredLocalNever = nev::throwing());
+}
+static method throws(() →* void f) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as nev;
+import "never_opt_out.dart" as self;
+
+import "org-dartlang-testcase:///never_opt_out.dart";
+
+static field Never optInNever = self::optOutNever;
+static method throwing() → Never
+  return throw "Never!";
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out_lib.dart b/pkg/front_end/testcases/nnbd/never_opt_out_lib.dart
new file mode 100644
index 0000000..06c5c16
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/never_opt_out_lib.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'never_opt_out.dart';
+
+Never throwing() => throw 'Never!';
+
+Never optInNever = optOutNever;
+
+class A {
+  Never neverField = throw "Should not reach here";
+  Never neverMethod(Never value) => value;
+  Never get neverProperty => throw "Should not reach here";
+  void set neverProperty(Never value) {}
+
+  Null nullField = null;
+  Null nullMethod(Null value) => value;
+  Null get nullProperty => Null;
+  void set nullProperty(Null value) {}
+}
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.outline.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.outline.expect
index 95bf118..e83db97 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.outline.expect
@@ -1,7 +1,7 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
-static method foo(Neverx, Never? y) → dynamic
+static method foo(Never x, Never? y) → dynamic
   ;
 static method main() → dynamic
   ;
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 3ec8d1f..65d01e2 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -76,7 +76,7 @@
 import self as self;
 import "dart:core" as core;
 
-static method foo(Neverx, Never? y) → dynamic {
+static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
   x.foo();
@@ -87,12 +87,12 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let finalNever? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
-  let finalNever? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let finalNever? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let finalNever? #t4 = y in #t4.{core::Object::==}(null) ?{dynamic} null : #t4{Never}.call();
-  let finalNever? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let finalNever? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
+  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} 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? #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'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
index 3ec8d1f..65d01e2 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -76,7 +76,7 @@
 import self as self;
 import "dart:core" as core;
 
-static method foo(Neverx, Never? y) → dynamic {
+static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
   x.foo();
@@ -87,12 +87,12 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let finalNever? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
-  let finalNever? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let finalNever? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let finalNever? #t4 = y in #t4.{core::Object::==}(null) ?{dynamic} null : #t4{Never}.call();
-  let finalNever? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let finalNever? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
+  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} 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? #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'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
index d147c4e..ae3949b 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -86,7 +86,7 @@
 import self as self;
 import "dart:core" as core;
 
-static method foo(Neverx, Never? y) → dynamic {
+static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
   x.foo();
@@ -97,12 +97,12 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let finalNever? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
-  let finalNever? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let finalNever? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let finalNever? #t4 = y in #t4.{core::Object::==}(null) ?{dynamic} null : #t4{Never}.call();
-  let finalNever? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let finalNever? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
+  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} 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? #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'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
index d147c4e..ae3949b 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -86,7 +86,7 @@
 import self as self;
 import "dart:core" as core;
 
-static method foo(Neverx, Never? y) → dynamic {
+static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
   x.foo();
@@ -97,12 +97,12 @@
   x.[]=(42, 42);
   x = x.+(1);
   x = x.+(1);
-  let finalNever? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{Never}.foo();
-  let finalNever? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let finalNever? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let finalNever? #t4 = y in #t4.{core::Object::==}(null) ?{dynamic} null : #t4{Never}.call();
-  let finalNever? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let finalNever? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
+  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{dynamic} 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? #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'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
index 56810f6..057a76f 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -37,11 +37,11 @@
   constructor bar(self::B::X% fieldOfB, self::B::Y fieldOfB2) → self::B<self::B::X%, self::B::Y>
     ;
 }
-abstract class M extends core::Object {
+abstract class M extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticFieldOfM;
   field core::int fieldOfM;
 }
-abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   generic-covariant-impl field self::N::X% fieldOfN;
   generic-covariant-impl field self::N::Y fieldOfN2;
 }
@@ -64,7 +64,7 @@
   constructor bar(core::int fieldOfC10) → self::C<self::C::X%, self::C::Y>
     ;
 }
-abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   static field core::int? staticFieldOfL;
   static field core::int staticFieldOfLInitialized;
   generic-covariant-impl field self::L::X? fieldOfL;
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
index 90d9ea5..bd5dcc7 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -66,11 +66,11 @@
     : self::B::fieldOfB = fieldOfB, self::B::fieldOfB2 = fieldOfB2, super core::Object::•()
     ;
 }
-abstract class M extends core::Object {
+abstract class M extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticFieldOfM = null;
   field core::int fieldOfM = null;
 }
-abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   generic-covariant-impl field self::N::X% fieldOfN = null;
   generic-covariant-impl field self::N::Y fieldOfN2 = null;
 }
@@ -95,7 +95,7 @@
     : self::C::fieldOfC10 = fieldOfC10, super core::Object::•()
     ;
 }
-abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   static field core::int? staticFieldOfL = null;
   static field core::int staticFieldOfLInitialized = 42;
   generic-covariant-impl field self::L::X? fieldOfL = null;
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
index 90d9ea5..bd5dcc7 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -66,11 +66,11 @@
     : self::B::fieldOfB = fieldOfB, self::B::fieldOfB2 = fieldOfB2, super core::Object::•()
     ;
 }
-abstract class M extends core::Object {
+abstract class M extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticFieldOfM = null;
   field core::int fieldOfM = null;
 }
-abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   generic-covariant-impl field self::N::X% fieldOfN = null;
   generic-covariant-impl field self::N::Y fieldOfN2 = null;
 }
@@ -95,7 +95,7 @@
     : self::C::fieldOfC10 = fieldOfC10, super core::Object::•()
     ;
 }
-abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   static field core::int? staticFieldOfL = null;
   static field core::int staticFieldOfLInitialized = 42;
   generic-covariant-impl field self::L::X? fieldOfL = null;
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
index 29e2dde..7f76fc6 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -66,11 +66,11 @@
     : self::B::fieldOfB = fieldOfB, self::B::fieldOfB2 = fieldOfB2, super core::Object::•()
     ;
 }
-abstract class M extends core::Object {
+abstract class M extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticFieldOfM = null;
   field core::int fieldOfM = null;
 }
-abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   generic-covariant-impl field self::N::X% fieldOfN = null;
   generic-covariant-impl field self::N::Y fieldOfN2 = null;
 }
@@ -95,7 +95,7 @@
     : self::C::fieldOfC10 = fieldOfC10, super core::Object::•()
     ;
 }
-abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   static field core::int? staticFieldOfL = null;
   static field core::int staticFieldOfLInitialized = 42;
   generic-covariant-impl field self::L::X? fieldOfL = null;
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
index 29e2dde..7f76fc6 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -66,11 +66,11 @@
     : self::B::fieldOfB = fieldOfB, self::B::fieldOfB2 = fieldOfB2, super core::Object::•()
     ;
 }
-abstract class M extends core::Object {
+abstract class M extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticFieldOfM = null;
   field core::int fieldOfM = null;
 }
-abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class N<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   generic-covariant-impl field self::N::X% fieldOfN = null;
   generic-covariant-impl field self::N::Y fieldOfN2 = null;
 }
@@ -95,7 +95,7 @@
     : self::C::fieldOfC10 = fieldOfC10, super core::Object::•()
     ;
 }
-abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+abstract class L<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object /*isMixinDeclaration*/  {
   static field core::int? staticFieldOfL = null;
   static field core::int staticFieldOfLInitialized = 42;
   generic-covariant-impl field self::L::X? fieldOfL = null;
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart
new file mode 100644
index 0000000..fa74007
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.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 'nsm_from_opt_in_lib.dart';
+
+abstract class B2 extends A implements C2 {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+abstract class C2 {
+  int method(int i, {optional});
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..00778a8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "nsm_from_opt_in_lib.dart" as nsm;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
+
+abstract class B2 extends nsm::A implements self::C2 {
+  synthetic constructor •() → self::B2*
+    ;
+  @core::override
+  method noSuchMethod(core::Invocation* invocation) → dynamic
+    ;
+  abstract forwarding-stub method method(core::int* i, {dynamic optional}) → core::int*;
+}
+abstract class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    ;
+  abstract method method(core::int* i, {dynamic optional}) → core::int*;
+}
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as nsm;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → nsm::A
+    ;
+  method method(core::int? i) → core::int
+    ;
+}
+abstract class B1 extends nsm::A implements nsm::C1 {
+  synthetic constructor •() → nsm::B1
+    ;
+  @core::override
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    ;
+  abstract forwarding-stub method method(core::int? i, {dynamic optional}) → core::int;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → nsm::C1
+    ;
+  abstract method method(core::int? i, {dynamic optional}) → core::int;
+}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..10bcb6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "nsm_from_opt_in_lib.dart" as nsm;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
+
+abstract class B2 extends nsm::A implements self::C2 {
+  synthetic constructor •() → self::B2*
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+abstract class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as nsm;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → nsm::A
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+abstract class B1 extends nsm::A implements nsm::C1 {
+  synthetic constructor •() → nsm::B1
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → nsm::C1
+    : super core::Object::•()
+    ;
+  abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..10bcb6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "nsm_from_opt_in_lib.dart" as nsm;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
+
+abstract class B2 extends nsm::A implements self::C2 {
+  synthetic constructor •() → self::B2*
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+abstract class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as nsm;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → nsm::A
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+abstract class B1 extends nsm::A implements nsm::C1 {
+  synthetic constructor •() → nsm::B1
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → nsm::C1
+    : super core::Object::•()
+    ;
+  abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..10bcb6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "nsm_from_opt_in_lib.dart" as nsm;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
+
+abstract class B2 extends nsm::A implements self::C2 {
+  synthetic constructor •() → self::B2*
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+abstract class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as nsm;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → nsm::A
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+abstract class B1 extends nsm::A implements nsm::C1 {
+  synthetic constructor •() → nsm::B1
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → nsm::C1
+    : super core::Object::•()
+    ;
+  abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..10bcb6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "nsm_from_opt_in_lib.dart" as nsm;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
+
+abstract class B2 extends nsm::A implements self::C2 {
+  synthetic constructor •() → self::B2*
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+abstract class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as nsm;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → nsm::A
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+}
+abstract class B1 extends nsm::A implements nsm::C1 {
+  synthetic constructor •() → nsm::B1
+    : super nsm::A::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract forwarding-stub method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → nsm::C1
+    : super core::Object::•()
+    ;
+  abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart
new file mode 100644
index 0000000..20d29b9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.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.
+
+class A {
+  int method(int? i) => i ?? 0;
+}
+
+abstract class B1 extends A implements C1 {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+abstract class C1 {
+  int method(int? i, {optional});
+}
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart b/pkg/front_end/testcases/nnbd/null_access.dart
index 35b7f16..6a14198 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart
+++ b/pkg/front_end/testcases/nnbd/null_access.dart
@@ -9,23 +9,30 @@
   void operator []=(int key, int value) {}
   Class get nonNullableClass => this;
   Class call() => this;
+  NullableIndexClass get nonNullableNullableIndexClass => NullableIndexClass();
+}
+
+class NullableIndexClass {
+  int? operator [](int key) => key;
+  void operator []=(int key, int value) {}
 }
 
 main() {}
 
 errors(Class? nullableClass, Class nonNullableClass, int? nullableInt,
-    int nonNullableInt) {
+    int nonNullableInt, NullableIndexClass? nullableNullableIndexClass) {
   -nullableInt; // error
   nullableInt + 2; // error
   nullableClass[nonNullableInt]; // error
   nullableClass[nonNullableInt] = nonNullableInt; // error
   nullableClass[nonNullableInt] += nonNullableInt; // error
-  nullableClass[nonNullableInt] ??= nonNullableInt; // error
+  nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
 
   nullableClass?.nonNullableClass[nonNullableInt]; // ok
   nullableClass?.nonNullableClass[nonNullableInt] = nonNullableInt; // ok
   nullableClass?.nonNullableClass[nonNullableInt] += nonNullableInt; // ok
-  nullableClass?.nonNullableClass[nonNullableInt] ??= nonNullableInt; // ok
+  nullableClass?.nonNullableNullableIndexClass[nonNullableInt] ??=
+      nonNullableInt; // ok
 
   nullableClass.nonNullableField; // error
   nullableClass.nonNullableField = 2; // error
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_access.dart.outline.expect
index a5ae9e3..5f23d7a 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -15,8 +15,18 @@
     ;
   method call() → self::Class
     ;
+  get nonNullableNullableIndexClass() → self::NullableIndexClass
+    ;
+}
+class NullableIndexClass extends core::Object {
+  synthetic constructor •() → self::NullableIndexClass
+    ;
+  operator [](core::int key) → core::int?
+    ;
+  operator []=(core::int key, core::int value) → void
+    ;
 }
 static method main() → dynamic
   ;
-static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt) → dynamic
+static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt, self::NullableIndexClass? nullableNullableIndexClass) → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
index 642146a..39e0fe7 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
@@ -1,83 +1,97 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:18:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:24:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 //   -nullableInt; // error
 //   ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:19:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:25:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nullableInt + 2; // error
 //               ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:20:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:26:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt]; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:21:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:27:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] = nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]' cannot be called on 'NullableIndexClass?' because it is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]=' cannot be called on 'NullableIndexClass?' because it is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:30:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:37:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:31:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:38:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField = 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField += 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:41:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:48:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nonNullableClass.nullableField += 2; // error
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:42:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:49:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nullableClass?.nullableField += 2; // error
 //                                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:54:35: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   nullableClass?.nonNullableClass.nonNullableField ??= 0; // ok
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?. instead.
 //   nullableClass(); // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?.call instead.
 //   nullableClass(); // error
 //                ^
 //
+// pkg/front_end/testcases/nnbd/null_access.dart:59:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass(); // ok
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:60:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass.nonNullableClass(); // ok
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -94,56 +108,66 @@
     return this;
   method call() → self::Class
     return this;
+  get nonNullableNullableIndexClass() → self::NullableIndexClass
+    return new self::NullableIndexClass::•();
+}
+class NullableIndexClass extends core::Object {
+  synthetic constructor •() → self::NullableIndexClass
+    : super core::Object::•()
+    ;
+  operator [](core::int key) → core::int?
+    return key;
+  operator []=(core::int key, core::int value) → void {}
 }
 static method main() → dynamic {}
-static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt) → dynamic {
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:18:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt, self::NullableIndexClass? nullableNullableIndexClass) → dynamic {
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:24:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
   -nullableInt; // error
   ^" in nullableInt.{core::int::unary-}();
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:19:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:25:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nullableInt + 2; // error
               ^" in nullableInt.{core::num::+}(2);
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:20:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:26:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt]; // error
                ^" in nullableClass.{self::Class::[]}(nonNullableInt);
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:21:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:27:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] = nonNullableInt; // error
                ^" in nullableClass.{self::Class::[]=}(nonNullableInt, nonNullableInt);
-  let final self::Class? #t5 = nullableClass in let final core::int #t6 = nonNullableInt in let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+  let final self::Class? #t5 = nullableClass in let final core::int #t6 = nonNullableInt in let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] += nonNullableInt; // error
-               ^" in #t5.{self::Class::[]=}(#t6, (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+               ^" in #t5.{self::Class::[]=}(#t6, (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] += nonNullableInt; // error
                ^" in #t5.{self::Class::[]}(#t6)).{core::num::+}(nonNullableInt));
-  let final self::Class? #t9 = nullableClass in let final core::int #t10 = nonNullableInt in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-  nullableClass[nonNullableInt] ??= nonNullableInt; // error
-               ^" in #t9.{self::Class::[]}(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-  nullableClass[nonNullableInt] ??= nonNullableInt; // error
-               ^" in #t9.{self::Class::[]=}(#t10, nonNullableInt) : null;
+  let final self::NullableIndexClass? #t9 = nullableNullableIndexClass in let final core::int #t10 = nonNullableInt in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]' cannot be called on 'NullableIndexClass?' because it is potentially null.
+ - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+  nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+                            ^" in #t9.{self::NullableIndexClass::[]}(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]=' cannot be called on 'NullableIndexClass?' because it is potentially null.
+ - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+  nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+                            ^" in #t9.{self::NullableIndexClass::[]=}(#t10, nonNullableInt) : null;
   let final self::Class? #t13 = nullableClass in #t13.{core::Object::==}(null) ?{core::int?} null : #t13{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]}(nonNullableInt);
   let final self::Class? #t14 = nullableClass in #t14.{core::Object::==}(null) ?{core::int?} null : #t14{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t15 = nullableClass in #t15.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t16 = #t15{self::Class}.{self::Class::nonNullableClass} in let final core::int #t17 = nonNullableInt in #t16.{self::Class::[]=}(#t17, #t16.{self::Class::[]}(#t17).{core::num::+}(nonNullableInt));
-  let final self::Class? #t18 = nullableClass in #t18.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t19 = #t18{self::Class}.{self::Class::nonNullableClass} in let final core::int #t20 = nonNullableInt in #t19.{self::Class::[]}(#t20).{core::num::==}(null) ?{core::int} #t19.{self::Class::[]=}(#t20, nonNullableInt) : null;
-  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:30:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final self::Class? #t18 = nullableClass in #t18.{core::Object::==}(null) ?{core::int?} null : let final self::NullableIndexClass #t19 = #t18{self::Class}.{self::Class::nonNullableNullableIndexClass} in let final core::int #t20 = nonNullableInt in #t19.{self::NullableIndexClass::[]}(#t20).{core::num::==}(null) ?{core::int} #t19.{self::NullableIndexClass::[]=}(#t20, nonNullableInt) : null;
+  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:37:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField; // error
                 ^^^^^^^^^^^^^^^^" in nullableClass.{self::Class::nonNullableField};
-  let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:31:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:38:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField = 2; // error
                 ^^^^^^^^^^^^^^^^" in nullableClass.{self::Class::nonNullableField} = 2;
-  let final self::Class? #t23 = nullableClass in let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final self::Class? #t23 = nullableClass in let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField += 2; // error
-                ^^^^^^^^^^^^^^^^" in #t23.{self::Class::nonNullableField} = (let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+                ^^^^^^^^^^^^^^^^" in #t23.{self::Class::nonNullableField} = (let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField += 2; // error
@@ -153,21 +177,21 @@
   let final self::Class? #t28 = nullableClass in #t28.{core::Object::==}(null) ?{core::int?} null : #t28.{self::Class::nonNullableField} = #t28.{self::Class::nonNullableField}.{core::num::+}(2);
   let final self::Class? #t29 = nullableClass in #t29.{core::Object::==}(null) ?{core::int?} null : #t29{self::Class}.{self::Class::nonNullableClass}.{self::Class::nonNullableField};
   let final self::Class? #t30 = nullableClass in #t30.{core::Object::==}(null) ?{core::int?} null : #t30{self::Class}.{self::Class::nonNullableClass}.{self::Class::nonNullableField} = 2;
-  let final self::Class #t31 = nonNullableClass in #t31.{self::Class::nullableField} = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:41:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final self::Class #t31 = nonNullableClass in #t31.{self::Class::nullableField} = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:48:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nonNullableClass.nullableField += 2; // error
                                  ^" in #t31.{self::Class::nullableField}.{core::num::+}(2);
-  let final self::Class? #t33 = nullableClass in #t33.{core::Object::==}(null) ?{core::int?} null : #t33.{self::Class::nullableField} = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:42:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final self::Class? #t33 = nullableClass in #t33.{core::Object::==}(null) ?{core::int?} null : #t33.{self::Class::nullableField} = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:49:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nullableClass?.nullableField += 2; // error
                                ^" in #t33.{self::Class::nullableField}.{core::num::+}(2);
   let final self::Class? #t35 = nullableClass in #t35.{core::Object::==}(null) ?{core::int?} null : #t35.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t35.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t36 = nullableClass in #t36.{core::Object::==}(null) ?{core::int?} null : #t36.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t36.{self::Class::nullableField} = 0 : null;
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t38 = #t37{self::Class}.{self::Class::nonNullableClass} in #t38{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t38{self::Class}.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nullableField} = 0 : null;
-  let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+  let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
   nullableClass(); // error
-               ^" in let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+               ^" in let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?. instead.
   nullableClass(); // error
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
index 642146a..39e0fe7 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
@@ -1,83 +1,97 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:18:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:24:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 //   -nullableInt; // error
 //   ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:19:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:25:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nullableInt + 2; // error
 //               ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:20:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:26:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt]; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:21:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:27:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] = nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]' cannot be called on 'NullableIndexClass?' because it is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]=' cannot be called on 'NullableIndexClass?' because it is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:30:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:37:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:31:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:38:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField = 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField += 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:41:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:48:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nonNullableClass.nullableField += 2; // error
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:42:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:49:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   nullableClass?.nullableField += 2; // error
 //                                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:54:35: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   nullableClass?.nonNullableClass.nonNullableField ??= 0; // ok
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?. instead.
 //   nullableClass(); // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?.call instead.
 //   nullableClass(); // error
 //                ^
 //
+// pkg/front_end/testcases/nnbd/null_access.dart:59:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass(); // ok
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:60:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass.nonNullableClass(); // ok
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -94,56 +108,66 @@
     return this;
   method call() → self::Class
     return this;
+  get nonNullableNullableIndexClass() → self::NullableIndexClass
+    return new self::NullableIndexClass::•();
+}
+class NullableIndexClass extends core::Object {
+  synthetic constructor •() → self::NullableIndexClass
+    : super core::Object::•()
+    ;
+  operator [](core::int key) → core::int?
+    return key;
+  operator []=(core::int key, core::int value) → void {}
 }
 static method main() → dynamic {}
-static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt) → dynamic {
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:18:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt, self::NullableIndexClass? nullableNullableIndexClass) → dynamic {
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:24:3: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
   -nullableInt; // error
   ^" in nullableInt.{core::int::unary-}();
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:19:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:25:15: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nullableInt + 2; // error
               ^" in nullableInt.{core::num::+}(2);
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:20:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:26:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt]; // error
                ^" in nullableClass.{self::Class::[]}(nonNullableInt);
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:21:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:27:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] = nonNullableInt; // error
                ^" in nullableClass.{self::Class::[]=}(nonNullableInt, nonNullableInt);
-  let final self::Class? #t5 = nullableClass in let final core::int #t6 = nonNullableInt in let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+  let final self::Class? #t5 = nullableClass in let final core::int #t6 = nonNullableInt in let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] += nonNullableInt; // error
-               ^" in #t5.{self::Class::[]=}(#t6, (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:22:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+               ^" in #t5.{self::Class::[]=}(#t6, (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:28:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
   nullableClass[nonNullableInt] += nonNullableInt; // error
                ^" in #t5.{self::Class::[]}(#t6)).{core::num::+}(nonNullableInt));
-  let final self::Class? #t9 = nullableClass in let final core::int #t10 = nonNullableInt in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-  nullableClass[nonNullableInt] ??= nonNullableInt; // error
-               ^" in #t9.{self::Class::[]}(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:23:16: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-  nullableClass[nonNullableInt] ??= nonNullableInt; // error
-               ^" in #t9.{self::Class::[]=}(#t10, nonNullableInt) : null;
+  let final self::NullableIndexClass? #t9 = nullableNullableIndexClass in let final core::int #t10 = nonNullableInt in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]' cannot be called on 'NullableIndexClass?' because it is potentially null.
+ - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+  nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+                            ^" in #t9.{self::NullableIndexClass::[]}(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:29:29: Error: Operator '[]=' cannot be called on 'NullableIndexClass?' because it is potentially null.
+ - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+  nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+                            ^" in #t9.{self::NullableIndexClass::[]=}(#t10, nonNullableInt) : null;
   let final self::Class? #t13 = nullableClass in #t13.{core::Object::==}(null) ?{core::int?} null : #t13{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]}(nonNullableInt);
   let final self::Class? #t14 = nullableClass in #t14.{core::Object::==}(null) ?{core::int?} null : #t14{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t15 = nullableClass in #t15.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t16 = #t15{self::Class}.{self::Class::nonNullableClass} in let final core::int #t17 = nonNullableInt in #t16.{self::Class::[]=}(#t17, #t16.{self::Class::[]}(#t17).{core::num::+}(nonNullableInt));
-  let final self::Class? #t18 = nullableClass in #t18.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t19 = #t18{self::Class}.{self::Class::nonNullableClass} in let final core::int #t20 = nonNullableInt in #t19.{self::Class::[]}(#t20).{core::num::==}(null) ?{core::int} #t19.{self::Class::[]=}(#t20, nonNullableInt) : null;
-  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:30:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final self::Class? #t18 = nullableClass in #t18.{core::Object::==}(null) ?{core::int?} null : let final self::NullableIndexClass #t19 = #t18{self::Class}.{self::Class::nonNullableNullableIndexClass} in let final core::int #t20 = nonNullableInt in #t19.{self::NullableIndexClass::[]}(#t20).{core::num::==}(null) ?{core::int} #t19.{self::NullableIndexClass::[]=}(#t20, nonNullableInt) : null;
+  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:37:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField; // error
                 ^^^^^^^^^^^^^^^^" in nullableClass.{self::Class::nonNullableField};
-  let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:31:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:38:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField = 2; // error
                 ^^^^^^^^^^^^^^^^" in nullableClass.{self::Class::nonNullableField} = 2;
-  let final self::Class? #t23 = nullableClass in let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+  let final self::Class? #t23 = nullableClass in let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField += 2; // error
-                ^^^^^^^^^^^^^^^^" in #t23.{self::Class::nonNullableField} = (let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:32:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
+                ^^^^^^^^^^^^^^^^" in #t23.{self::Class::nonNullableField} = (let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:39:17: Error: Property 'nonNullableField' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try accessing using ?. instead.
   nullableClass.nonNullableField += 2; // error
@@ -153,21 +177,21 @@
   let final self::Class? #t28 = nullableClass in #t28.{core::Object::==}(null) ?{core::int?} null : #t28.{self::Class::nonNullableField} = #t28.{self::Class::nonNullableField}.{core::num::+}(2);
   let final self::Class? #t29 = nullableClass in #t29.{core::Object::==}(null) ?{core::int?} null : #t29{self::Class}.{self::Class::nonNullableClass}.{self::Class::nonNullableField};
   let final self::Class? #t30 = nullableClass in #t30.{core::Object::==}(null) ?{core::int?} null : #t30{self::Class}.{self::Class::nonNullableClass}.{self::Class::nonNullableField} = 2;
-  let final self::Class #t31 = nonNullableClass in #t31.{self::Class::nullableField} = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:41:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final self::Class #t31 = nonNullableClass in #t31.{self::Class::nullableField} = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:48:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nonNullableClass.nullableField += 2; // error
                                  ^" in #t31.{self::Class::nullableField}.{core::num::+}(2);
-  let final self::Class? #t33 = nullableClass in #t33.{core::Object::==}(null) ?{core::int?} null : #t33.{self::Class::nullableField} = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:42:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  let final self::Class? #t33 = nullableClass in #t33.{core::Object::==}(null) ?{core::int?} null : #t33.{self::Class::nullableField} = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:49:32: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   nullableClass?.nullableField += 2; // error
                                ^" in #t33.{self::Class::nullableField}.{core::num::+}(2);
   let final self::Class? #t35 = nullableClass in #t35.{core::Object::==}(null) ?{core::int?} null : #t35.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t35.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t36 = nullableClass in #t36.{core::Object::==}(null) ?{core::int?} null : #t36.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t36.{self::Class::nullableField} = 0 : null;
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t38 = #t37{self::Class}.{self::Class::nonNullableClass} in #t38{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t38{self::Class}.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nullableField} = 0 : null;
-  let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+  let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
   nullableClass(); // error
-               ^" in let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:50:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+               ^" in let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?. instead.
   nullableClass(); // error
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
index e4fc4d9..bf94e0a 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
@@ -1,83 +1,97 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:18:3: Warning: Operator 'unary-' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:24:3: Warning: Operator 'unary-' is called on 'int?' which is potentially null.
 //   -nullableInt; // error
 //   ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:19:15: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:25:15: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nullableInt + 2; // error
 //               ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:20:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:26:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt]; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:21:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:27:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] = nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Warning: Operator '[]' is called on 'NullableIndexClass?' which is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Warning: Operator '[]=' is called on 'NullableIndexClass?' which is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:30:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:37:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:31:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:38:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField = 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:32:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:39:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField += 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:41:34: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:48:34: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nonNullableClass.nullableField += 2; // error
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:42:32: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:49:32: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nullableClass?.nullableField += 2; // error
 //                                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Warning: Method 'call' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:54:35: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   nullableClass?.nonNullableClass.nonNullableField ??= 0; // ok
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Warning: Method 'call' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?. instead.
 //   nullableClass(); // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Warning: Expression of type 'Class?' is used as a function, but it's potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Warning: Expression of type 'Class?' is used as a function, but it's potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?.call instead.
 //   nullableClass(); // error
 //                ^
 //
+// pkg/front_end/testcases/nnbd/null_access.dart:59:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass(); // ok
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:60:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass.nonNullableClass(); // ok
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -94,19 +108,29 @@
     return this;
   method call() → self::Class
     return this;
+  get nonNullableNullableIndexClass() → self::NullableIndexClass
+    return new self::NullableIndexClass::•();
+}
+class NullableIndexClass extends core::Object {
+  synthetic constructor •() → self::NullableIndexClass
+    : super core::Object::•()
+    ;
+  operator [](core::int key) → core::int?
+    return key;
+  operator []=(core::int key, core::int value) → void {}
 }
 static method main() → dynamic {}
-static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt) → dynamic {
+static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt, self::NullableIndexClass? nullableNullableIndexClass) → dynamic {
   nullableInt.{core::int::unary-}();
   nullableInt.{core::num::+}(2);
   nullableClass.{self::Class::[]}(nonNullableInt);
   nullableClass.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t1 = nullableClass in let final core::int #t2 = nonNullableInt in #t1.{self::Class::[]=}(#t2, #t1.{self::Class::[]}(#t2).{core::num::+}(nonNullableInt));
-  let final self::Class? #t3 = nullableClass in let final core::int #t4 = nonNullableInt in #t3.{self::Class::[]}(#t4).{core::num::==}(null) ?{core::int} #t3.{self::Class::[]=}(#t4, nonNullableInt) : null;
+  let final self::NullableIndexClass? #t3 = nullableNullableIndexClass in let final core::int #t4 = nonNullableInt in #t3.{self::NullableIndexClass::[]}(#t4).{core::num::==}(null) ?{core::int} #t3.{self::NullableIndexClass::[]=}(#t4, nonNullableInt) : null;
   let final self::Class? #t5 = nullableClass in #t5.{core::Object::==}(null) ?{core::int?} null : #t5{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]}(nonNullableInt);
   let final self::Class? #t6 = nullableClass in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t7 = nullableClass in #t7.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t8 = #t7{self::Class}.{self::Class::nonNullableClass} in let final core::int #t9 = nonNullableInt in #t8.{self::Class::[]=}(#t9, #t8.{self::Class::[]}(#t9).{core::num::+}(nonNullableInt));
-  let final self::Class? #t10 = nullableClass in #t10.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t11 = #t10{self::Class}.{self::Class::nonNullableClass} in let final core::int #t12 = nonNullableInt in #t11.{self::Class::[]}(#t12).{core::num::==}(null) ?{core::int} #t11.{self::Class::[]=}(#t12, nonNullableInt) : null;
+  let final self::Class? #t10 = nullableClass in #t10.{core::Object::==}(null) ?{core::int?} null : let final self::NullableIndexClass #t11 = #t10{self::Class}.{self::Class::nonNullableNullableIndexClass} in let final core::int #t12 = nonNullableInt in #t11.{self::NullableIndexClass::[]}(#t12).{core::num::==}(null) ?{core::int} #t11.{self::NullableIndexClass::[]=}(#t12, nonNullableInt) : null;
   nullableClass.{self::Class::nonNullableField};
   nullableClass.{self::Class::nonNullableField} = 2;
   let final self::Class? #t13 = nullableClass in #t13.{self::Class::nonNullableField} = #t13.{self::Class::nonNullableField}.{core::num::+}(2);
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
index e4fc4d9..bf94e0a 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
@@ -1,83 +1,97 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:18:3: Warning: Operator 'unary-' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:24:3: Warning: Operator 'unary-' is called on 'int?' which is potentially null.
 //   -nullableInt; // error
 //   ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:19:15: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:25:15: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nullableInt + 2; // error
 //               ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:20:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:26:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt]; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:21:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:27:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] = nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:22:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:28:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 //   nullableClass[nonNullableInt] += nonNullableInt; // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Warning: Operator '[]' is called on 'Class?' which is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Warning: Operator '[]' is called on 'NullableIndexClass?' which is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:23:16: Warning: Operator '[]=' is called on 'Class?' which is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
-//   nullableClass[nonNullableInt] ??= nonNullableInt; // error
-//                ^
+// pkg/front_end/testcases/nnbd/null_access.dart:29:29: Warning: Operator '[]=' is called on 'NullableIndexClass?' which is potentially null.
+//  - 'NullableIndexClass' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nullableNullableIndexClass[nonNullableInt] ??= nonNullableInt; // error
+//                             ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:30:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:37:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:31:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:38:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField = 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:32:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:39:17: Warning: Property 'nonNullableField' is accessed on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try accessing using ?. instead.
 //   nullableClass.nonNullableField += 2; // error
 //                 ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:41:34: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:48:34: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nonNullableClass.nullableField += 2; // error
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:42:32: Warning: Operator '+' is called on 'int?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:49:32: Warning: Operator '+' is called on 'int?' which is potentially null.
 //   nullableClass?.nullableField += 2; // error
 //                                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Warning: Method 'call' is called on 'Class?' which is potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:54:35: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   nullableClass?.nonNullableClass.nonNullableField ??= 0; // ok
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Warning: Method 'call' is called on 'Class?' which is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?. instead.
 //   nullableClass(); // error
 //                ^
 //
-// pkg/front_end/testcases/nnbd/null_access.dart:50:16: Warning: Expression of type 'Class?' is used as a function, but it's potentially null.
+// pkg/front_end/testcases/nnbd/null_access.dart:57:16: Warning: Expression of type 'Class?' is used as a function, but it's potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 // Try calling using ?.call instead.
 //   nullableClass(); // error
 //                ^
 //
+// pkg/front_end/testcases/nnbd/null_access.dart:59:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass(); // ok
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_access.dart:60:3: Warning: Operand of null-aware operation '?.' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
+//   nonNullableClass?.nonNullableClass.nonNullableClass(); // ok
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -94,19 +108,29 @@
     return this;
   method call() → self::Class
     return this;
+  get nonNullableNullableIndexClass() → self::NullableIndexClass
+    return new self::NullableIndexClass::•();
+}
+class NullableIndexClass extends core::Object {
+  synthetic constructor •() → self::NullableIndexClass
+    : super core::Object::•()
+    ;
+  operator [](core::int key) → core::int?
+    return key;
+  operator []=(core::int key, core::int value) → void {}
 }
 static method main() → dynamic {}
-static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt) → dynamic {
+static method errors(self::Class? nullableClass, self::Class nonNullableClass, core::int? nullableInt, core::int nonNullableInt, self::NullableIndexClass? nullableNullableIndexClass) → dynamic {
   nullableInt.{core::int::unary-}();
   nullableInt.{core::num::+}(2);
   nullableClass.{self::Class::[]}(nonNullableInt);
   nullableClass.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t1 = nullableClass in let final core::int #t2 = nonNullableInt in #t1.{self::Class::[]=}(#t2, #t1.{self::Class::[]}(#t2).{core::num::+}(nonNullableInt));
-  let final self::Class? #t3 = nullableClass in let final core::int #t4 = nonNullableInt in #t3.{self::Class::[]}(#t4).{core::num::==}(null) ?{core::int} #t3.{self::Class::[]=}(#t4, nonNullableInt) : null;
+  let final self::NullableIndexClass? #t3 = nullableNullableIndexClass in let final core::int #t4 = nonNullableInt in #t3.{self::NullableIndexClass::[]}(#t4).{core::num::==}(null) ?{core::int} #t3.{self::NullableIndexClass::[]=}(#t4, nonNullableInt) : null;
   let final self::Class? #t5 = nullableClass in #t5.{core::Object::==}(null) ?{core::int?} null : #t5{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]}(nonNullableInt);
   let final self::Class? #t6 = nullableClass in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Class}.{self::Class::nonNullableClass}.{self::Class::[]=}(nonNullableInt, nonNullableInt);
   let final self::Class? #t7 = nullableClass in #t7.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t8 = #t7{self::Class}.{self::Class::nonNullableClass} in let final core::int #t9 = nonNullableInt in #t8.{self::Class::[]=}(#t9, #t8.{self::Class::[]}(#t9).{core::num::+}(nonNullableInt));
-  let final self::Class? #t10 = nullableClass in #t10.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t11 = #t10{self::Class}.{self::Class::nonNullableClass} in let final core::int #t12 = nonNullableInt in #t11.{self::Class::[]}(#t12).{core::num::==}(null) ?{core::int} #t11.{self::Class::[]=}(#t12, nonNullableInt) : null;
+  let final self::Class? #t10 = nullableClass in #t10.{core::Object::==}(null) ?{core::int?} null : let final self::NullableIndexClass #t11 = #t10{self::Class}.{self::Class::nonNullableNullableIndexClass} in let final core::int #t12 = nonNullableInt in #t11.{self::NullableIndexClass::[]}(#t12).{core::num::==}(null) ?{core::int} #t11.{self::NullableIndexClass::[]=}(#t12, nonNullableInt) : null;
   nullableClass.{self::Class::nonNullableField};
   nullableClass.{self::Class::nonNullableField} = 2;
   let final self::Class? #t13 = nullableClass in #t13.{self::Class::nonNullableField} = #t13.{self::Class::nonNullableField}.{core::num::+}(2);
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.outline.expect
index af3d1e9..1570628 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
index f74ed66..267161a 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.transformed.expect
index f74ed66..267161a 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
index f74ed66..267161a 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.transformed.expect
index f74ed66..267161a 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect
index aa7235a..23ccd44 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
index bffb6ce..26ca627 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -1,4 +1,90 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:14:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:15:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field = 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:16:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:17:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:18:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:19:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method()!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:20:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:8: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:22:7: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c + c!;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:23:6: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   (c + c)!;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:10: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:17: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:18: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:5: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:12: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:22: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:20: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                    ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
index bffb6ce..26ca627 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.transformed.expect
@@ -1,4 +1,90 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:14:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:15:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field = 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:16:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:17:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:18:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:19:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method()!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:20:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:8: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:22:7: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c + c!;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:23:6: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   (c + c)!;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:10: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:17: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:18: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:5: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:12: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:22: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:20: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                    ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
index bffb6ce..26ca627 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
@@ -1,4 +1,90 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:14:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:15:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field = 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:16:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:17:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:18:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:19:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method()!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:20:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:8: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:22:7: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c + c!;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:23:6: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   (c + c)!;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:10: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:17: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:18: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:5: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:12: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:22: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:20: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                    ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_check.dart.weak.transformed.expect
index bffb6ce..26ca627 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.weak.transformed.expect
@@ -1,4 +1,90 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:14:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:15:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field = 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:16:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:17:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:18:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.field!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:19:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c!.method()!.toString();
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:20:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:3: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//   ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:21:8: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c! + c!;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:22:7: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   c + c!;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:23:6: Warning: Operand of null-aware operation '!' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_check.dart'.
+//   (c + c)!;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:10: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:17: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:26:18: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !o! ? !o! : !!o!!;
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:5: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:12: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:22: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/null_check.dart:27:20: Warning: Operand of null-aware operation '!' has type 'bool' which excludes null.
+//   !(o!) ? (!o)! : (!(!o)!)!;
+//                    ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check_context.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_check_context.dart.outline.expect
index 61468b9..1e606c3 100644
--- a/pkg/front_end/testcases/nnbd/null_check_context.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_check_context.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.expect
index c4bea6d..a9e189a 100644
--- a/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.transformed.expect
index c4bea6d..a9e189a 100644
--- a/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_check_context.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.expect
index c4bea6d..a9e189a 100644
--- a/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.transformed.expect
index c4bea6d..a9e189a 100644
--- a/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_check_context.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
index 6eb9d37..307f52e 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
index 7f40a02..4b8eb0a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
index 7f40a02..4b8eb0a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
index 0a88580..1667166 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
index 0a88580..1667166 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect
index 433ed24..7cc6fec 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect
index 60aef17..1e6793a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect
index 60aef17..1e6793a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.expect
index 60aef17..1e6793a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.transformed.expect
index 60aef17..1e6793a 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
index 32edac1..6e17131 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
index 93172a1..ad010f7 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
index 93172a1..ad010f7 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
index 0f12197..559dca6 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
index 0f12197..559dca6 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
index 32edac1..6e17131 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
index 08bb2f4..51808db 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
index 08bb2f4..51808db 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
index 47d4d98..dce5931 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
index 47d4d98..dce5931 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect
index 6b81c57..c13bf31 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
index 2afae89..111b12b 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
@@ -1,4 +1,47 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1 + c1[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1 + c2[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1;
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1 + Extension(c2)[1];
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1 + c1[1];
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1 + Extension(c2)?.[1]!;
+//                       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
index 2afae89..111b12b 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
@@ -1,4 +1,47 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1 + c1[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1 + c2[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1;
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1 + Extension(c2)[1];
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1 + c1[1];
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1 + Extension(c2)?.[1]!;
+//                       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
index 2afae89..111b12b 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
@@ -1,4 +1,47 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1 + c1[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1 + c2[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1;
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1 + Extension(c2)[1];
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1 + c1[1];
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1 + Extension(c2)?.[1]!;
+//                       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
index 2afae89..111b12b 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
@@ -1,4 +1,47 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.[0] ??= 1 + c1[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c2?.[0] ??= 1 + c2[1];
+//     ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1;
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:16: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c2)?.[0] ??= 1 + Extension(c2)[1];
+//                ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:12: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   c1?.field?.[0] ??= 1 + c1[1];
+//            ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:23: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?.[0] ??= 1 + Extension(c2)?.[1]!;
+//                       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.outline.expect
index 6a74223..64040bc 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -13,7 +13,7 @@
   method nonNullableMethod() → self::A
     ;
 }
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
index 509f924..9699336 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -24,7 +24,7 @@
   method nonNullableMethod() → self::A
     return this.{self::Class::nonNullableField};
 }
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
index 509f924..9699336 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -24,7 +24,7 @@
   method nonNullableMethod() → self::A
     return this.{self::Class::nonNullableField};
 }
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
index ca860c8..dc3992f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -24,7 +24,7 @@
   method nonNullableMethod() → self::A
     return this.{self::Class::nonNullableField};
 }
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
index ca860c8..dc3992f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
@@ -24,7 +24,7 @@
   method nonNullableMethod() → self::A
     return this.{self::Class::nonNullableField};
 }
-class A extends core::Object {
+class A extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::A
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
index 937afc3..f1b5ac6 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
index bf6195b..a19cb5b 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
index bf6195b..a19cb5b 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.expect
index d3205a9..7efdb66 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
index d3205a9..7efdb66 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
index 5309a2b..24ecf42f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
index 3adb898..9ab6069 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
index 3adb898..9ab6069 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.expect
index 3adb898..9ab6069 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
index 3adb898..9ab6069 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect
index 8b1efd6..d88e541e 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
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 4572332..a326cf2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 4572332..a326cf2 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 cd79d91..a00b574 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
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 cd79d91..a00b574 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
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect
index b08c2be2..11d7a43 100644
--- a/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect
index 02ebaa2..fa10991 100644
--- a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect
index 02ebaa2..fa10991 100644
--- a/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.weak.expect
index 02ebaa2..fa10991 100644
--- a/pkg/front_end/testcases/nnbd/opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/opt_out.dart.weak.transformed.expect
index 02ebaa2..fa10991 100644
--- a/pkg/front_end/testcases/nnbd/opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/opt_out.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
index ab6f690..cae508d 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 import "dart:test";
@@ -6,7 +6,7 @@
 static method main() → dynamic
   ;
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
index 1f952a2..9a4131e 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:test" as test;
 
@@ -8,7 +8,7 @@
   test::Class? c = new test::Class::•();
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
index 1f952a2..9a4131e 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:test" as test;
 
@@ -8,7 +8,7 @@
   test::Class? c = new test::Class::•();
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
index 33e8f39..0faff12 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:test" as test;
 
@@ -8,7 +8,7 @@
   test::Class? c = new test::Class::•();
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
index 33e8f39..0faff12 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:test" as test;
 
@@ -8,7 +8,7 @@
   test::Class? c = new test::Class::•();
 }
 
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect
index b56b2a7..5f5e178 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect
index 0dee541..ac1c56b 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect
index 0dee541..ac1c56b 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect
index ff1e157..0b34a21 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect
index ff1e157..0b34a21 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required.dart.outline.expect b/pkg/front_end/testcases/nnbd/required.dart.outline.expect
index bac1604..ff5e088 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required.dart.strong.expect b/pkg/front_end/testcases/nnbd/required.dart.strong.expect
index 335594b..ed0ee8e 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
index 335594b..ed0ee8e 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required.dart.weak.expect b/pkg/front_end/testcases/nnbd/required.dart.weak.expect
index 35a4cfc..4c8f81d 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/required.dart.weak.transformed.expect
index 35a4cfc..4c8f81d 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
index bfd9052..8dab663 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
index c706ee0..41566f3 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
index c706ee0..41566f3 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
index f8837f9..8f475d6 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
index f8837f9..8f475d6 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/return_late.dart.outline.expect b/pkg/front_end/testcases/nnbd/return_late.dart.outline.expect
index b09c8c1..00f4708 100644
--- a/pkg/front_end/testcases/nnbd/return_late.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/return_late.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/return_late.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_late.dart.strong.expect
index 7829fc4..66e9443 100644
--- a/pkg/front_end/testcases/nnbd/return_late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_late.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/return_late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_late.dart.strong.transformed.expect
index 3da0607..15e6379 100644
--- a/pkg/front_end/testcases/nnbd/return_late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_late.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/return_late.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_late.dart.weak.expect
index 7829fc4..66e9443 100644
--- a/pkg/front_end/testcases/nnbd/return_late.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_late.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/return_late.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_late.dart.weak.transformed.expect
index 3da0607..15e6379 100644
--- a/pkg/front_end/testcases/nnbd/return_late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_late.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.outline.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.outline.expect
index 11c3840..604aeff 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.expect
index 69c985e..f35cdbd 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
index 69c985e..f35cdbd 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.expect
index 0a8d639..e32de91 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
index 0a8d639..e32de91 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect
index a1a8eaa..d0b4248 100644
--- a/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
 static method foo() → Never
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect
index 9a621b6..7047a3b 100644
--- a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect
@@ -1,7 +1,7 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
-static method foo() → Never{
+static method foo() → Never {
   while (true) {
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect
index 9a621b6..7047a3b 100644
--- a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect
@@ -1,7 +1,7 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
-static method foo() → Never{
+static method foo() → Never {
   while (true) {
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.weak.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.weak.expect
index 9a621b6..7047a3b 100644
--- a/pkg/front_end/testcases/nnbd/simple_never.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.weak.expect
@@ -1,7 +1,7 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
-static method foo() → Never{
+static method foo() → Never {
   while (true) {
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.weak.transformed.expect
index 9a621b6..7047a3b 100644
--- a/pkg/front_end/testcases/nnbd/simple_never.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.weak.transformed.expect
@@ -1,7 +1,7 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 
-static method foo() → Never{
+static method foo() → Never {
   while (true) {
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart
index 89fe8b0..1a513c4 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart
@@ -6,13 +6,44 @@
 // non-nullable types being used in positions typically occupied by those of
 // nullable types, that is, in various null-aware expressions.
 
-warning(String s, List<String> l) {
-  s?.length;
-  s?..length;
-  s ?? "foo";
-  s ??= "foo";
-  [...?l];
-  s!;
+extension E on String {
+  int get foo => 42;
+  void operator[]=(int index, int value) {}
+  int operator[](int index) => 42;
+}
+
+class A {
+  String operator[](int index) => "foo";
+  void operator[]=(int index, String value) {}
+}
+
+class B extends A {
+  void test() {
+    super[42] ??= "bar"; // Warning.
+  }
+}
+
+warning(String s, List<String> l, Map<String, int> m) {
+  s?.length; // Warning.
+  s?..length; // Warning.
+  s ?? "foo"; // Warning.
+  s ??= "foo"; // Warning.
+  [...?l]; // Warning.
+  var a = {...?l}; // Warning.
+  <String>{...?l}; // Warning.
+  var b = {...?m}; // Warning.
+  <String, int>{...?m}; // Warning.
+  s!; // Warning.
+  s?.substring(0, 0); // Warning.
+  l?.length = 42; // Warning.
+  l?.length += 42; // Warning.
+  l?.length ??= 42; // Warning.
+  s?.foo; // Warning.
+  E(s)[42] ??= 42; // Warning.
+  l[42] ??= "foo"; // Warning.
+  l.length ??= 42; // Warning.
+  l?..length = 42; // Warning.
+  l?..length ??= 42; // Warning.
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect
index f2afe48..6834f82 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect
@@ -1,8 +1,33 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
-static method warning(core::String s, core::List<core::String> l) → dynamic
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  operator [](core::int index) → core::String
+    ;
+  operator []=(core::int index, core::String value) → void
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    ;
+  method test() → void
+    ;
+}
+extension E on core::String {
+  get foo = self::E|get#foo;
+  operator []= = self::E|[]=;
+  operator [] = self::E|[];
+}
+static method E|get#foo(final core::String #this) → core::int
+  ;
+static method E|[]=(final core::String #this, core::int index, core::int value) → void
+  ;
+static method E|[](final core::String #this, core::int index) → core::int
+  ;
+static method warning(core::String s, core::List<core::String> l, core::Map<core::String, core::int> m) → dynamic
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect
index 19938b7..5f0452d 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect
@@ -1,19 +1,187 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:22:10: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//     super[42] ??= "bar"; // Warning.
+//          ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:28:3: Warning: Operand of null-aware operation '?..' has type 'String' which excludes null.
+//   s?..length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:29:3: Warning: Operand of null-aware operation '??' has type 'String' which excludes null.
+//   s ?? "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:30:3: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   s ??= "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:31:8: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   [...?l]; // Warning.
+//        ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:32:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   var a = {...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:33:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   <String>{...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:34:16: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   var b = {...?m}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:35:21: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   <String, int>{...?m}; // Warning.
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:36:3: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   s!; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:37:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.substring(0, 0); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:38:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:39:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length += 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:40:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:41:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.foo; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:42:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   E(s)[42] ??= 42; // Warning.
+//       ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:43:4: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   l[42] ??= "foo"; // Warning.
+//    ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:44:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l.length ??= 42; // Warning.
+//     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:45:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l?..length ??= 42; // Warning.
+//       ^
+//
 import self as self;
 import "dart:core" as core;
+import "dart:collection" as col;
 
-static method warning(core::String s, core::List<core::String> l) → dynamic {
-  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int?} null : #t1.{core::String::length};
-  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
-  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::String
+    return "foo";
+  operator []=(core::int index, core::String value) → void {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method test() → void {
+    let final core::int #t1 = 42 in super.{self::A::[]}(#t1).{core::String::==}(null) ?{core::String} super.{self::A::[]=}(#t1, "bar") : null;
+  }
+}
+extension E on core::String {
+  get foo = self::E|get#foo;
+  operator []= = self::E|[]=;
+  operator [] = self::E|[];
+}
+static method E|get#foo(final core::String #this) → core::int
+  return 42;
+static method E|[]=(final core::String #this, core::int index, core::int value) → void {}
+static method E|[](final core::String #this, core::int index) → core::int
+  return 42;
+static method warning(core::String s, core::List<core::String> l, core::Map<core::String, core::int> m) → dynamic {
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::int?} null : #t2.{core::String::length};
+  let final core::String #t3 = s in #t3.{core::String::==}(null) ?{core::String} null : let final void #t4 = #t3.{core::String::length} in #t3;
+  let final core::String #t5 = s in #t5.{core::String::==}(null) ?{core::String} "foo" : #t5;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
-    final core::Iterable<core::String>? #t6 = l;
-    if(!#t6.{core::Object::==}(null))
-      for (final core::String #t7 in #t6{core::Iterable<core::String>})
-        #t5.{core::List::add}(#t7);
-  } =>#t5;
+    final core::List<core::String> #t6 = <core::String>[];
+    final core::Iterable<core::String>? #t7 = l;
+    if(!#t7.{core::Object::==}(null))
+      for (final core::String #t8 in #t7{core::Iterable<core::String>})
+        #t6.{core::List::add}(#t8);
+  } =>#t6;
+  core::Set<core::String> a = block {
+    final core::Set<core::String> #t9 = col::LinkedHashSet::•<core::String>();
+    final core::Iterable<core::String>? #t10 = l;
+    if(!#t10.{core::Object::==}(null))
+      for (final dynamic #t11 in #t10{core::Iterable<core::String>}) {
+        final core::String #t12 = #t11 as{TypeError,ForNonNullableByDefault} core::String;
+        #t9.{core::Set::add}(#t12);
+      }
+  } =>#t9;
+  block {
+    final core::Set<core::String> #t13 = col::LinkedHashSet::•<core::String>();
+    final core::Iterable<core::String>? #t14 = l;
+    if(!#t14.{core::Object::==}(null))
+      for (final core::String #t15 in #t14{core::Iterable<core::String>})
+        #t13.{core::Set::add}(#t15);
+  } =>#t13;
+  core::Map<core::String, core::int> b = block {
+    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))
+      for (final core::MapEntry<core::String, core::int> #t18 in #t17{core::Map<core::String, core::int>}.{core::Map::entries})
+        #t16.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
+  } =>#t16;
+  block {
+    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))
+      for (final core::MapEntry<core::String, core::int> #t21 in #t20{core::Map<core::String, core::int>}.{core::Map::entries})
+        #t19.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
+  } =>#t19;
   s!;
+  let final core::String #t22 = s in #t22.{core::String::==}(null) ?{core::String?} null : #t22.{core::String::substring}(0, 0);
+  let final core::List<core::String> #t23 = l in #t23.{core::List::==}(null) ?{core::int?} null : #t23.{core::List::length} = 42;
+  let final core::List<core::String> #t24 = l in #t24.{core::List::==}(null) ?{core::int?} null : #t24.{core::List::length} = #t24.{core::List::length}.{core::num::+}(42);
+  let final core::List<core::String> #t25 = l in #t25.{core::List::==}(null) ?{core::int?} null : #t25.{core::List::length}.{core::num::==}(null) ?{core::int} #t25.{core::List::length} = 42 : null;
+  let final core::String #t26 = s in #t26.{core::String::==}(null) ?{core::int?} null : self::E|get#foo(#t26);
+  let final core::String #t27 = s in let final core::int #t28 = 42 in self::E|[](#t27, #t28).{core::num::==}(null) ?{core::int} self::E|[]=(#t27, #t28, 42) : null;
+  let final core::List<core::String> #t29 = l in let final core::int #t30 = 42 in #t29.{core::List::[]}(#t30).{core::String::==}(null) ?{core::String} #t29.{core::List::[]=}(#t30, "foo") : null;
+  let final core::List<core::String> #t31 = l in #t31.{core::List::length}.{core::num::==}(null) ?{core::int} #t31.{core::List::length} = 42 : null;
+  let final core::List<core::String> #t32 = l in #t32.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t33 = #t32.{core::List::length} = 42 in #t32;
+  let final core::List<core::String> #t34 = l in #t34.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t35 = let final core::List<core::String> #t36 = #t34 in #t36.{core::List::length}.{core::num::==}(null) ?{core::int} #t36.{core::List::length} = 42 : null in #t34;
 }
 static method main() → dynamic {}
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 a35cd49..3d6a2f4 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
@@ -1,24 +1,209 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:22:10: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//     super[42] ??= "bar"; // Warning.
+//          ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:28:3: Warning: Operand of null-aware operation '?..' has type 'String' which excludes null.
+//   s?..length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:29:3: Warning: Operand of null-aware operation '??' has type 'String' which excludes null.
+//   s ?? "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:30:3: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   s ??= "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:31:8: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   [...?l]; // Warning.
+//        ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:32:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   var a = {...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:33:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   <String>{...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:34:16: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   var b = {...?m}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:35:21: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   <String, int>{...?m}; // Warning.
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:36:3: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   s!; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:37:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.substring(0, 0); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:38:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:39:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length += 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:40:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:41:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.foo; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:42:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   E(s)[42] ??= 42; // Warning.
+//       ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:43:4: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   l[42] ??= "foo"; // Warning.
+//    ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:44:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l.length ??= 42; // Warning.
+//     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:45:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l?..length ??= 42; // Warning.
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
+import "dart:collection" as col;
 
-static method warning(core::String s, core::List<core::String> l) → dynamic {
-  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int?} null : #t1.{core::String::length};
-  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
-  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::String
+    return "foo";
+  operator []=(core::int index, core::String value) → void {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method test() → void {
+    let final core::int #t1 = 42 in super.{self::A::[]}(#t1).{core::String::==}(null) ?{core::String} super.{self::A::[]=}(#t1, "bar") : null;
+  }
+}
+extension E on core::String {
+  get foo = self::E|get#foo;
+  operator []= = self::E|[]=;
+  operator [] = self::E|[];
+}
+static method E|get#foo(final core::String #this) → core::int
+  return 42;
+static method E|[]=(final core::String #this, core::int index, core::int value) → void {}
+static method E|[](final core::String #this, core::int index) → core::int
+  return 42;
+static method warning(core::String s, core::List<core::String> l, core::Map<core::String, core::int> m) → dynamic {
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::int?} null : #t2.{core::String::length};
+  let final core::String #t3 = s in #t3.{core::String::==}(null) ?{core::String} null : let final void #t4 = #t3.{core::String::length} in #t3;
+  let final core::String #t5 = s in #t5.{core::String::==}(null) ?{core::String} "foo" : #t5;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
-    final core::Iterable<core::String>? #t6 = l;
-    if(!#t6.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t6{core::Iterable<core::String>}).{core::Iterable::iterator};
+    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};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::String #t7 = :sync-for-iterator.{core::Iterator::current};
-        #t5.{core::List::add}(#t7);
+        final core::String #t8 = :sync-for-iterator.{core::Iterator::current};
+        #t6.{core::List::add}(#t8);
       }
     }
-  } =>#t5;
+  } =>#t6;
+  core::Set<core::String> a = block {
+    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};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::String #t12 = #t11 as{TypeError,ForNonNullableByDefault} core::String;
+          #t9.{core::Set::add}(#t12);
+        }
+      }
+    }
+  } =>#t9;
+  block {
+    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};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::String #t15 = :sync-for-iterator.{core::Iterator::current};
+        #t13.{core::Set::add}(#t15);
+      }
+    }
+  } =>#t13;
+  core::Map<core::String, core::int> b = block {
+    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};
+      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});
+      }
+    }
+  } =>#t16;
+  block {
+    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};
+      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});
+      }
+    }
+  } =>#t19;
   s!;
+  let final core::String #t22 = s in #t22.{core::String::==}(null) ?{core::String?} null : #t22.{core::String::substring}(0, 0);
+  let final core::List<core::String> #t23 = l in #t23.{core::List::==}(null) ?{core::int?} null : #t23.{core::List::length} = 42;
+  let final core::List<core::String> #t24 = l in #t24.{core::List::==}(null) ?{core::int?} null : #t24.{core::List::length} = #t24.{core::List::length}.{core::num::+}(42);
+  let final core::List<core::String> #t25 = l in #t25.{core::List::==}(null) ?{core::int?} null : #t25.{core::List::length}.{core::num::==}(null) ?{core::int} #t25.{core::List::length} = 42 : null;
+  let final core::String #t26 = s in #t26.{core::String::==}(null) ?{core::int?} null : self::E|get#foo(#t26);
+  let final core::String #t27 = s in let final core::int #t28 = 42 in self::E|[](#t27, #t28).{core::num::==}(null) ?{core::int} self::E|[]=(#t27, #t28, 42) : null;
+  let final core::List<core::String> #t29 = l in let final core::int #t30 = 42 in #t29.{core::List::[]}(#t30).{core::String::==}(null) ?{core::String} #t29.{core::List::[]=}(#t30, "foo") : null;
+  let final core::List<core::String> #t31 = l in #t31.{core::List::length}.{core::num::==}(null) ?{core::int} #t31.{core::List::length} = 42 : null;
+  let final core::List<core::String> #t32 = l in #t32.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t33 = #t32.{core::List::length} = 42 in #t32;
+  let final core::List<core::String> #t34 = l in #t34.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t35 = let final core::List<core::String> #t36 = #t34 in #t36.{core::List::length}.{core::num::==}(null) ?{core::int} #t36.{core::List::length} = 42 : null in #t34;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect
index 19938b7..5f0452d 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect
@@ -1,19 +1,187 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:22:10: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//     super[42] ??= "bar"; // Warning.
+//          ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:28:3: Warning: Operand of null-aware operation '?..' has type 'String' which excludes null.
+//   s?..length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:29:3: Warning: Operand of null-aware operation '??' has type 'String' which excludes null.
+//   s ?? "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:30:3: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   s ??= "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:31:8: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   [...?l]; // Warning.
+//        ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:32:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   var a = {...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:33:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   <String>{...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:34:16: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   var b = {...?m}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:35:21: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   <String, int>{...?m}; // Warning.
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:36:3: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   s!; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:37:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.substring(0, 0); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:38:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:39:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length += 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:40:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:41:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.foo; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:42:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   E(s)[42] ??= 42; // Warning.
+//       ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:43:4: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   l[42] ??= "foo"; // Warning.
+//    ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:44:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l.length ??= 42; // Warning.
+//     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:45:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l?..length ??= 42; // Warning.
+//       ^
+//
 import self as self;
 import "dart:core" as core;
+import "dart:collection" as col;
 
-static method warning(core::String s, core::List<core::String> l) → dynamic {
-  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int?} null : #t1.{core::String::length};
-  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
-  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::String
+    return "foo";
+  operator []=(core::int index, core::String value) → void {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method test() → void {
+    let final core::int #t1 = 42 in super.{self::A::[]}(#t1).{core::String::==}(null) ?{core::String} super.{self::A::[]=}(#t1, "bar") : null;
+  }
+}
+extension E on core::String {
+  get foo = self::E|get#foo;
+  operator []= = self::E|[]=;
+  operator [] = self::E|[];
+}
+static method E|get#foo(final core::String #this) → core::int
+  return 42;
+static method E|[]=(final core::String #this, core::int index, core::int value) → void {}
+static method E|[](final core::String #this, core::int index) → core::int
+  return 42;
+static method warning(core::String s, core::List<core::String> l, core::Map<core::String, core::int> m) → dynamic {
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::int?} null : #t2.{core::String::length};
+  let final core::String #t3 = s in #t3.{core::String::==}(null) ?{core::String} null : let final void #t4 = #t3.{core::String::length} in #t3;
+  let final core::String #t5 = s in #t5.{core::String::==}(null) ?{core::String} "foo" : #t5;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
-    final core::Iterable<core::String>? #t6 = l;
-    if(!#t6.{core::Object::==}(null))
-      for (final core::String #t7 in #t6{core::Iterable<core::String>})
-        #t5.{core::List::add}(#t7);
-  } =>#t5;
+    final core::List<core::String> #t6 = <core::String>[];
+    final core::Iterable<core::String>? #t7 = l;
+    if(!#t7.{core::Object::==}(null))
+      for (final core::String #t8 in #t7{core::Iterable<core::String>})
+        #t6.{core::List::add}(#t8);
+  } =>#t6;
+  core::Set<core::String> a = block {
+    final core::Set<core::String> #t9 = col::LinkedHashSet::•<core::String>();
+    final core::Iterable<core::String>? #t10 = l;
+    if(!#t10.{core::Object::==}(null))
+      for (final dynamic #t11 in #t10{core::Iterable<core::String>}) {
+        final core::String #t12 = #t11 as{TypeError,ForNonNullableByDefault} core::String;
+        #t9.{core::Set::add}(#t12);
+      }
+  } =>#t9;
+  block {
+    final core::Set<core::String> #t13 = col::LinkedHashSet::•<core::String>();
+    final core::Iterable<core::String>? #t14 = l;
+    if(!#t14.{core::Object::==}(null))
+      for (final core::String #t15 in #t14{core::Iterable<core::String>})
+        #t13.{core::Set::add}(#t15);
+  } =>#t13;
+  core::Map<core::String, core::int> b = block {
+    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))
+      for (final core::MapEntry<core::String, core::int> #t18 in #t17{core::Map<core::String, core::int>}.{core::Map::entries})
+        #t16.{core::Map::[]=}(#t18.{core::MapEntry::key}, #t18.{core::MapEntry::value});
+  } =>#t16;
+  block {
+    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))
+      for (final core::MapEntry<core::String, core::int> #t21 in #t20{core::Map<core::String, core::int>}.{core::Map::entries})
+        #t19.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
+  } =>#t19;
   s!;
+  let final core::String #t22 = s in #t22.{core::String::==}(null) ?{core::String?} null : #t22.{core::String::substring}(0, 0);
+  let final core::List<core::String> #t23 = l in #t23.{core::List::==}(null) ?{core::int?} null : #t23.{core::List::length} = 42;
+  let final core::List<core::String> #t24 = l in #t24.{core::List::==}(null) ?{core::int?} null : #t24.{core::List::length} = #t24.{core::List::length}.{core::num::+}(42);
+  let final core::List<core::String> #t25 = l in #t25.{core::List::==}(null) ?{core::int?} null : #t25.{core::List::length}.{core::num::==}(null) ?{core::int} #t25.{core::List::length} = 42 : null;
+  let final core::String #t26 = s in #t26.{core::String::==}(null) ?{core::int?} null : self::E|get#foo(#t26);
+  let final core::String #t27 = s in let final core::int #t28 = 42 in self::E|[](#t27, #t28).{core::num::==}(null) ?{core::int} self::E|[]=(#t27, #t28, 42) : null;
+  let final core::List<core::String> #t29 = l in let final core::int #t30 = 42 in #t29.{core::List::[]}(#t30).{core::String::==}(null) ?{core::String} #t29.{core::List::[]=}(#t30, "foo") : null;
+  let final core::List<core::String> #t31 = l in #t31.{core::List::length}.{core::num::==}(null) ?{core::int} #t31.{core::List::length} = 42 : null;
+  let final core::List<core::String> #t32 = l in #t32.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t33 = #t32.{core::List::length} = 42 in #t32;
+  let final core::List<core::String> #t34 = l in #t34.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t35 = let final core::List<core::String> #t36 = #t34 in #t36.{core::List::length}.{core::num::==}(null) ?{core::int} #t36.{core::List::length} = 42 : null in #t34;
 }
 static method main() → dynamic {}
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 a35cd49..3d6a2f4 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
@@ -1,24 +1,209 @@
-library;
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:22:10: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//     super[42] ??= "bar"; // Warning.
+//          ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:27:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:28:3: Warning: Operand of null-aware operation '?..' has type 'String' which excludes null.
+//   s?..length; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:29:3: Warning: Operand of null-aware operation '??' has type 'String' which excludes null.
+//   s ?? "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:30:3: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   s ??= "foo"; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:31:8: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   [...?l]; // Warning.
+//        ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:32:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   var a = {...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:33:16: Warning: Operand of null-aware operation '...?' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   <String>{...?l}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:34:16: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   var b = {...?m}; // Warning.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:35:21: Warning: Operand of null-aware operation '...?' has type 'Map<String, int>' which excludes null.
+//  - 'Map' is from 'dart:core'.
+//   <String, int>{...?m}; // Warning.
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:36:3: Warning: Operand of null-aware operation '!' has type 'String' which excludes null.
+//   s!; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:37:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.substring(0, 0); // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:38:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:39:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length += 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:40:3: Warning: Operand of null-aware operation '?.' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?.length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:41:3: Warning: Operand of null-aware operation '?.' has type 'String' which excludes null.
+//   s?.foo; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:42:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   E(s)[42] ??= 42; // Warning.
+//       ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:43:4: Warning: Operand of null-aware operation '??=' has type 'String' which excludes null.
+//   l[42] ??= "foo"; // Warning.
+//    ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:44:5: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l.length ??= 42; // Warning.
+//     ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:45:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length = 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:3: Warning: Operand of null-aware operation '?..' has type 'List<String>' which excludes null.
+//  - 'List' is from 'dart:core'.
+//   l?..length ??= 42; // Warning.
+//   ^
+//
+// pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart:46:7: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   l?..length ??= 42; // Warning.
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
+import "dart:collection" as col;
 
-static method warning(core::String s, core::List<core::String> l) → dynamic {
-  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int?} null : #t1.{core::String::length};
-  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
-  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::String
+    return "foo";
+  operator []=(core::int index, core::String value) → void {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method test() → void {
+    let final core::int #t1 = 42 in super.{self::A::[]}(#t1).{core::String::==}(null) ?{core::String} super.{self::A::[]=}(#t1, "bar") : null;
+  }
+}
+extension E on core::String {
+  get foo = self::E|get#foo;
+  operator []= = self::E|[]=;
+  operator [] = self::E|[];
+}
+static method E|get#foo(final core::String #this) → core::int
+  return 42;
+static method E|[]=(final core::String #this, core::int index, core::int value) → void {}
+static method E|[](final core::String #this, core::int index) → core::int
+  return 42;
+static method warning(core::String s, core::List<core::String> l, core::Map<core::String, core::int> m) → dynamic {
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::int?} null : #t2.{core::String::length};
+  let final core::String #t3 = s in #t3.{core::String::==}(null) ?{core::String} null : let final void #t4 = #t3.{core::String::length} in #t3;
+  let final core::String #t5 = s in #t5.{core::String::==}(null) ?{core::String} "foo" : #t5;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
-    final core::Iterable<core::String>? #t6 = l;
-    if(!#t6.{core::Object::==}(null)) {
-      core::Iterator<core::String>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String>*>(#t6{core::Iterable<core::String>}).{core::Iterable::iterator};
+    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};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::String #t7 = :sync-for-iterator.{core::Iterator::current};
-        #t5.{core::List::add}(#t7);
+        final core::String #t8 = :sync-for-iterator.{core::Iterator::current};
+        #t6.{core::List::add}(#t8);
       }
     }
-  } =>#t5;
+  } =>#t6;
+  core::Set<core::String> a = block {
+    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};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::String #t12 = #t11 as{TypeError,ForNonNullableByDefault} core::String;
+          #t9.{core::Set::add}(#t12);
+        }
+      }
+    }
+  } =>#t9;
+  block {
+    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};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::String #t15 = :sync-for-iterator.{core::Iterator::current};
+        #t13.{core::Set::add}(#t15);
+      }
+    }
+  } =>#t13;
+  core::Map<core::String, core::int> b = block {
+    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};
+      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});
+      }
+    }
+  } =>#t16;
+  block {
+    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};
+      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});
+      }
+    }
+  } =>#t19;
   s!;
+  let final core::String #t22 = s in #t22.{core::String::==}(null) ?{core::String?} null : #t22.{core::String::substring}(0, 0);
+  let final core::List<core::String> #t23 = l in #t23.{core::List::==}(null) ?{core::int?} null : #t23.{core::List::length} = 42;
+  let final core::List<core::String> #t24 = l in #t24.{core::List::==}(null) ?{core::int?} null : #t24.{core::List::length} = #t24.{core::List::length}.{core::num::+}(42);
+  let final core::List<core::String> #t25 = l in #t25.{core::List::==}(null) ?{core::int?} null : #t25.{core::List::length}.{core::num::==}(null) ?{core::int} #t25.{core::List::length} = 42 : null;
+  let final core::String #t26 = s in #t26.{core::String::==}(null) ?{core::int?} null : self::E|get#foo(#t26);
+  let final core::String #t27 = s in let final core::int #t28 = 42 in self::E|[](#t27, #t28).{core::num::==}(null) ?{core::int} self::E|[]=(#t27, #t28, 42) : null;
+  let final core::List<core::String> #t29 = l in let final core::int #t30 = 42 in #t29.{core::List::[]}(#t30).{core::String::==}(null) ?{core::String} #t29.{core::List::[]=}(#t30, "foo") : null;
+  let final core::List<core::String> #t31 = l in #t31.{core::List::length}.{core::num::==}(null) ?{core::int} #t31.{core::List::length} = 42 : null;
+  let final core::List<core::String> #t32 = l in #t32.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t33 = #t32.{core::List::length} = 42 in #t32;
+  let final core::List<core::String> #t34 = l in #t34.{core::List::==}(null) ?{core::List<core::String>} null : let final void #t35 = let final core::List<core::String> #t36 = #t34 in #t36.{core::List::length}.{core::num::==}(null) ?{core::int} #t36.{core::List::length} = 42 : null in #t34;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
index 78939a7..afffc19 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
index b23b0d3..afd873e 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
index b23b0d3..afd873e 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.expect
index b23b0d3..afd873e 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.transformed.expect
index b23b0d3..afd873e 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.outline.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.outline.expect
index 8f8831c..bb20d27 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.expect
index 249b918..19bd0eb 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
index 249b918..19bd0eb 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.expect
index c9f6d6a..2317ae7 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.transformed.expect
index c9f6d6a..2317ae7 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 //
 // Problems in library:
 //
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
index c19129b..9c418ba 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
index e9e87da..4db6f6e 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
index e9e87da..4db6f6e 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
index e9e87da..4db6f6e 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
index e9e87da..4db6f6e 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
@@ -1,4 +1,4 @@
-library;
+library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
index f84f93d..b57bf0f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#foo=, 2, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _C&Object&B = core::Object with self::B {
+abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
index 1f2525d..1a87161 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
@@ -21,7 +21,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _C&Object&B = core::Object with self::B {
+abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
index da816df..2f8a597 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _C&Object&B extends core::Object implements self::B {
+abstract class _C&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
index 3adb9f5..4c2e89f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
@@ -21,7 +21,7 @@
   no-such-method-forwarder method foo() → dynamic
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} dynamic;
 }
-abstract class _C&A&B = self::A with self::B {
+abstract class _C&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
index ad2597a..3c6a058 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
@@ -23,7 +23,7 @@
   no-such-method-forwarder method foo() → dynamic
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} dynamic;
 }
-abstract class _C&A&B = self::A with self::B {
+abstract class _C&A&B = self::A with self::B /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.transformed.expect
index 23455fe..42b6d98 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
   no-such-method-forwarder method foo() → dynamic
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} dynamic;
 }
-abstract class _C&A&B extends self::A implements self::B {
+abstract class _C&A&B extends self::A implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_C&A&B*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
index 3f045c4..edbb0ed 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
@@ -15,7 +15,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _B&Object&A = core::Object with self::A {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
index 238f1ad..3b19a6c 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&A = core::Object with self::A {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
index c985876..44e754a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&A extends core::Object implements self::A {
+abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
index f968d95..7dd0cad 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -16,7 +16,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _A&Object&M = core::Object with self::M {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -27,7 +27,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _B&Object&M = core::Object with self::M {
+abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
index 489451d..46f8531 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
@@ -18,7 +18,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     return null;
 }
-abstract class _A&Object&M = core::Object with self::M {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -30,7 +30,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&M = core::Object with self::M {
+abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
index 3d08a75..32bc4ba 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     return null;
 }
-abstract class _A&Object&M extends core::Object implements self::M {
+abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -32,7 +32,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&M extends core::Object implements self::M {
+abstract class _B&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
index de8e57b..cd0cff0 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -8,7 +8,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _B&Object&A = core::Object with self::A {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
index b7294d2..8b0741b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
@@ -10,7 +10,7 @@
     return null;
   }
 }
-abstract class _B&Object&A = core::Object with self::A {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
index 5da9029..2594975 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
     return null;
   }
 }
-abstract class _B&Object&A extends core::Object implements self::A {
+abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
index 6983d47..96ee192 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -13,7 +13,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _A&Object&M = core::Object with self::M {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
index 64693b8..9cef3ba 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -16,7 +16,7 @@
     return null;
   }
 }
-abstract class _A&Object&M = core::Object with self::M {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
index fe3fabb..53a2959 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
     return null;
   }
 }
-abstract class _A&Object&M extends core::Object implements self::M {
+abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 8875144..47a606d 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -5,7 +5,7 @@
 general/abstract_members: TypeCheckError
 general/bug30695: TypeCheckError
 general/bug30695: TypeCheckError
-general/ignore_function: TypeCheckError
+general/infer_field_from_multiple: TypeCheckError
 general/invalid_operator: TypeCheckError
 general/mixin_application_override: TypeCheckError
 general/override_check_accessor_after_inference: TypeCheckError
@@ -19,7 +19,6 @@
 general_nnbd_opt_out/abstract_members: TypeCheckError
 general_nnbd_opt_out/bug30695: TypeCheckError
 general_nnbd_opt_out/bug30695: TypeCheckError
-general_nnbd_opt_out/ignore_function: 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
@@ -29,17 +28,12 @@
 general_nnbd_opt_out/override_check_with_covariant_modifier: TypeCheckError
 general_nnbd_opt_out/override_setter_with_field: TypeCheckError
 
-inference/conflicting_fields: TypeCheckError
-inference/conflicts_can_happen2: Fail
-inference/conflicts_can_happen: Fail
 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/inconsistent_overrides: TypeCheckError
 inference/infer_assign_to_index: Fail
 inference/infer_assign_to_property: Fail
 inference/infer_assign_to_property_custom: Fail
-inference/infer_field_override_multiple: TypeCheckError
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_type_cast: Fail
 inference/infer_types_on_generic_instantiations_infer: TypeCheckError
@@ -47,13 +41,11 @@
 inference/mixin_inference_outwards_4: TypeCheckError
 inference/mixin_inference_unification_1: TypeCheckError
 inference/mixin_inference_unification_2: TypeCheckError
-inference_new/infer_field_getter_setter_mismatch: TypeCheckError
-inference_new/infer_field_override_accessors: TypeCheckError
-inference_new/infer_field_override_getter_overrides_setter: 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
 
 rasta/native_is_illegal: Pass # Issue 29763
 
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.outline.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.outline.expect
index dfa4ba4..5e82d74 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.outline.expect
@@ -10,7 +10,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
 Try removing the extra positional arguments.
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
index af2f9eb..f345e51 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
@@ -10,7 +10,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
 Try removing the extra positional arguments.
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
index af2f9eb..f345e51 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
 Try removing the extra positional arguments.
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.outline.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.outline.expect
index a7b1099..55cdfbb 100644
--- a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.outline.expect
@@ -13,7 +13,7 @@
   constructor •(dynamic x) → self::A*
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart:10:20: Error: Too few positional arguments: 1 required, 0 given.
   const B() : super();
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
index 1feb3f4..8fdc2b1 100644
--- a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart:10:20: Error: Too few positional arguments: 1 required, 0 given.
   const B() : super();
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
index 1feb3f4..8fdc2b1 100644
--- a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart:10:20: Error: Too few positional arguments: 1 required, 0 given.
   const B() : super();
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.outline.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.outline.expect
index 57359a4..8988c62 100644
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.outline.expect
@@ -13,7 +13,7 @@
   constructor •(dynamic x) → self::A*
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
   const B();
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
index 0ddc60f..3274e8e 100644
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
@@ -20,7 +20,7 @@
          ^"
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
   const B();
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
index 0ddc60f..3274e8e 100644
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
          ^"
     ;
 }
-class B extends self::A {
+class B extends self::A /*hasConstConstructor*/  {
   const constructor •() → self::B*
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart:10:9: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
   const B();
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
index 0451f5c..0624290 100644
--- a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
@@ -7,12 +7,12 @@
   synthetic constructor •() → self::Mixin*
     ;
 }
-abstract class _A&Object&Mixin = core::Object with self::Mixin {
+abstract class _A&Object&Mixin = core::Object with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&Object&Mixin*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&Mixin&Mixin = self::_A&Object&Mixin with self::Mixin {
+abstract class _A&Object&Mixin&Mixin = self::_A&Object&Mixin with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&Object&Mixin&Mixin*
     : super self::_A&Object&Mixin::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
index 6b3d464..c8be9f9 100644
--- a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
@@ -8,12 +8,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&Mixin = core::Object with self::Mixin {
+abstract class _A&Object&Mixin = core::Object with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&Object&Mixin*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&Mixin&Mixin = self::_A&Object&Mixin with self::Mixin {
+abstract class _A&Object&Mixin&Mixin = self::_A&Object&Mixin with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A&Object&Mixin&Mixin*
     : super self::_A&Object&Mixin::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.transformed.expect
index ea7db2b..3d74ab6 100644
--- a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.transformed.expect
@@ -8,13 +8,13 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&Mixin extends core::Object implements self::Mixin {
+abstract class _A&Object&Mixin extends core::Object implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic field = null;
   synthetic constructor •() → self::_A&Object&Mixin*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&Mixin&Mixin extends self::_A&Object&Mixin implements self::Mixin {
+abstract class _A&Object&Mixin&Mixin extends self::_A&Object&Mixin implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic field = null;
   synthetic constructor •() → self::_A&Object&Mixin&Mixin*
     : super self::_A&Object&Mixin::•()
diff --git a/pkg/front_end/testcases/rasta/enum.dart.outline.expect b/pkg/front_end/testcases/rasta/enum.dart.outline.expect
index 984ceeb..bd3b3c5 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = const <self::Foo*>[self::Foo::ec1, self::Foo::ec2];
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
index ced26a8..690a0ac 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C7;
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
index ced26a8..690a0ac 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Foo extends core::Object {
+class Foo extends core::Object /*isEnum*/  {
   final field core::int* index;
   final field core::String* _name;
   static const field core::List<self::Foo*>* values = #C7;
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
index 8d54f1e..0379890 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
@@ -12,7 +12,7 @@
   method foo() → dynamic
     ;
 }
-abstract class _Sub&Base&Mixin = self::Base with self::Mixin {
+abstract class _Sub&Base&Mixin = self::Base with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Sub&Base&Mixin*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
index 8aea3e8..655d4a7 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
@@ -14,7 +14,7 @@
   method foo() → dynamic
     return core::print("foo");
 }
-abstract class _Sub&Base&Mixin = self::Base with self::Mixin {
+abstract class _Sub&Base&Mixin = self::Base with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Sub&Base&Mixin*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
index 0c4886a..9c25751 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
   method foo() → dynamic
     return core::print("foo");
 }
-abstract class _Sub&Base&Mixin extends self::Base implements self::Mixin {
+abstract class _Sub&Base&Mixin extends self::Base implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_Sub&Base&Mixin*
     : super self::Base::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.outline.expect
index 02e6d34..3bfabf7 100644
--- a/pkg/front_end/testcases/rasta/issue_000034.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000034.dart.outline.expect
@@ -14,7 +14,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000034.dart:6:15: Error: This couldn't be parsed.
   const C() : this.x;
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
index e901592..0f316bb 100644
--- a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
@@ -14,7 +14,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000034.dart:6:15: Error: This couldn't be parsed.
   const C() : this.x;
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
index e901592..0f316bb 100644
--- a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const constructor •() → self::C*
     : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000034.dart:6:15: Error: This couldn't be parsed.
   const C() : this.x;
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
index cd96d0f..c4ff133 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
@@ -28,7 +28,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
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 9c3fa75..1673fff 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
@@ -62,7 +62,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
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 e576061..211952a 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
@@ -62,7 +62,7 @@
 import self as self;
 import "dart:core" as core;
 
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   static field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect
index ed8c072..47945f6 100644
--- a/pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
     : super core::Object::•()
     ;
 }
-class C extends self::A implements self::M1 {
+class C extends self::A implements self::M1 /*isEliminatedMixin*/  {
   field core::num* v2 = 0;
   synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
     : super self::A::•(v1, v2)
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
index c7a0e81..26f75a5 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
@@ -4,7 +4,7 @@
 
 import "package:expect/expect.dart";
 
-class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object {
+class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field core::List<self::A::U*>* field;
   constructor •(self::A::N* n, self::A::S* s) → self::A<self::A::N*, self::A::S*, self::A::U*>*
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
index 8718610..08f02742 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object {
+class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field core::List<self::A::U*>* field;
   constructor •(self::A::N* n, self::A::S* s) → self::A<self::A::N*, self::A::S*, self::A::U*>*
     : self::A::field = core::List::•<self::A::U*>(), super core::Object::•() {
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
index e5097ea..44a777c 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "package:expect/expect.dart";
 
-class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object {
+class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field core::List<self::A::U*>* field;
   constructor •(self::A::N* n, self::A::S* s) → self::A<self::A::N*, self::A::S*, self::A::U*>*
     : self::A::field = core::_GrowableList::•<self::A::U*>(0), super core::Object::•() {
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
index ef15719..99bda27 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
@@ -9,7 +9,7 @@
   method foo() → dynamic
     ;
 }
-abstract class _Foo&Object&Mixin = core::Object with self::Mixin {
+abstract class _Foo&Object&Mixin = core::Object with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
index c7b2aaa..6a193ab 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
@@ -10,7 +10,7 @@
   method foo() → dynamic
     return 87;
 }
-abstract class _Foo&Object&Mixin = core::Object with self::Mixin {
+abstract class _Foo&Object&Mixin = core::Object with self::Mixin /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
index 37e2112..5f31625 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
   method foo() → dynamic
     return 87;
 }
-abstract class _Foo&Object&Mixin extends core::Object implements self::Mixin {
+abstract class _Foo&Object&Mixin extends core::Object implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
   field dynamic field = null;
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
index 4d67319..1966a89 100644
--- a/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
@@ -13,7 +13,7 @@
   method f() → dynamic
     ;
 }
-abstract class _C&Super&Mixin<V extends core::Object* = dynamic> = self::Super<self::_C&Super&Mixin::V*> with mix::Mixin<self::_C&Super&Mixin::V*> {
+abstract class _C&Super&Mixin<V extends core::Object* = dynamic> = self::Super<self::_C&Super&Mixin::V*> with mix::Mixin<self::_C&Super&Mixin::V*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&Super&Mixin<self::_C&Super&Mixin::V*>*
     : super self::Super::•()
     ;
@@ -22,7 +22,7 @@
   synthetic constructor •() → self::C<self::C::V*>*
     ;
 }
-abstract class _D&Super&Mixin = self::Super<dynamic> with mix::Mixin<dynamic> {
+abstract class _D&Super&Mixin = self::Super<dynamic> with mix::Mixin<dynamic> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&Super&Mixin*
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
index 70eed77..30d7ed6 100644
--- a/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
@@ -14,7 +14,7 @@
   method f() → dynamic
     return 3;
 }
-abstract class _C&Super&Mixin<V extends core::Object* = dynamic> = self::Super<self::_C&Super&Mixin::V*> with mix::Mixin<self::_C&Super&Mixin::V*> {
+abstract class _C&Super&Mixin<V extends core::Object* = dynamic> = self::Super<self::_C&Super&Mixin::V*> with mix::Mixin<self::_C&Super&Mixin::V*> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&Super&Mixin<self::_C&Super&Mixin::V*>*
     : super self::Super::•()
     ;
@@ -24,7 +24,7 @@
     : super self::_C&Super&Mixin::•()
     ;
 }
-abstract class _D&Super&Mixin = self::Super<dynamic> with mix::Mixin<dynamic> {
+abstract class _D&Super&Mixin = self::Super<dynamic> with mix::Mixin<dynamic> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_D&Super&Mixin*
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect b/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
index 426b983..dbbd563 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
@@ -14,7 +14,7 @@
   method m() → dynamic
     ;
 }
-abstract class _C&A&M = self::A<self::A<dynamic>*> with self::M {
+abstract class _C&A&M = self::A<self::A<dynamic>*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&A&M*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
index e8d1b92..12c9067 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
@@ -16,7 +16,7 @@
   method m() → dynamic
     return 42;
 }
-abstract class _C&A&M = self::A<self::A<dynamic>*> with self::M {
+abstract class _C&A&M = self::A<self::A<dynamic>*> with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_C&A&M*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
index 2369578..90d83a5 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
   method m() → dynamic
     return 42;
 }
-abstract class _C&A&M extends self::A<self::A<dynamic>*> implements self::M {
+abstract class _C&A&M extends self::A<self::A<dynamic>*> implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_C&A&M*
     : super self::A::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34403.dart.outline.expect
index 0983f99..ea7359e 100644
--- a/pkg/front_end/testcases/regress/issue_34403.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_34403.dart.outline.expect
@@ -8,7 +8,7 @@
   constructor bar() → self::C<self::C::T*>*
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   constructor bar() → self2::E<self2::E::T*>*
     ;
 }
-class F<T extends core::Object* = dynamic> extends core::Object {
+class F<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self2::F<self2::F::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
index cd83b08..f6fd766 100644
--- a/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
@@ -93,7 +93,7 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
@@ -134,7 +134,7 @@
     : super core::Object::•()
     ;
 }
-class F<T extends core::Object* = dynamic> extends core::Object {
+class F<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → iss::F<iss::F::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
index cd83b08..f6fd766 100644
--- a/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
@@ -93,7 +93,7 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
@@ -134,7 +134,7 @@
     : super core::Object::•()
     ;
 }
-class F<T extends core::Object* = dynamic> extends core::Object {
+class F<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const constructor foo() → iss::F<iss::F::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
index 1988ac5..db5ac39 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.outline.expect
@@ -21,13 +21,13 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class M1 extends core::Object {
+abstract class M1 extends core::Object /*isMixinDeclaration*/  {
   get m() → core::int*
     ;
 }
-abstract class M2 extends core::Object {
+abstract class M2 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class M3 extends core::Object {
+abstract class M3 extends core::Object /*isMixinDeclaration*/  {
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1*
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
index 4410636..e254b75 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.strong.expect
@@ -45,13 +45,13 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class M1 extends core::Object {
+abstract class M1 extends core::Object /*isMixinDeclaration*/  {
   get m() → core::int*
     return 1;
 }
-abstract class M2 extends core::Object {
+abstract class M2 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class M3 extends core::Object {
+abstract class M3 extends core::Object /*isMixinDeclaration*/  {
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1*
diff --git a/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
index 4410636..e254b75 100644
--- a/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34563.dart.strong.transformed.expect
@@ -45,13 +45,13 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class M1 extends core::Object {
+abstract class M1 extends core::Object /*isMixinDeclaration*/  {
   get m() → core::int*
     return 1;
 }
-abstract class M2 extends core::Object {
+abstract class M2 extends core::Object /*isMixinDeclaration*/  {
 }
-abstract class M3 extends core::Object {
+abstract class M3 extends core::Object /*isMixinDeclaration*/  {
 }
 class C1 extends core::Object {
   synthetic constructor •() → self::C1*
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect
index 9684d36..1e62467 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.outline.expect
@@ -10,7 +10,7 @@
   synthetic constructor •() → self::MixMeIn*
     ;
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn {
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
     : super self::NoUnnamedConstuctor::_()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect
index 175b974..5ea619e 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.strong.expect
@@ -19,7 +19,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn {
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/  {
   synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
     : super self::NoUnnamedConstuctor::_()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect
index f15581b..837887c 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.strong.transformed.expect
@@ -19,7 +19,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn {
+abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
     : super self::NoUnnamedConstuctor::_()
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.transformed.expect
index e63cbdb..bf75e8d 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     ;
   method f(core::int* x) → void {}
 }
-class C extends self::B implements self::I<core::int*>, self::M {
+class C extends self::B implements self::I<core::int*>, self::M /*isEliminatedMixin*/  {
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.strong.transformed.expect
index fc8cb4a..99f6d1f 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_super_mixin.dart.strong.transformed.expect
@@ -19,7 +19,7 @@
     : super core::Object::•()
     ;
 }
-class C extends self::B implements self::I<core::int*>, self::M {
+class C extends self::B implements self::I<core::int*>, self::M /*isEliminatedMixin*/  {
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 743737c..64e77cd 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -34,8 +34,8 @@
 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/ignore_function: TypeCheckError
 general/incomplete_field_formal_parameter: RuntimeError
+general/infer_field_from_multiple: TypeCheckError
 general/invalid_type: TypeCheckError
 general/invalid_operator: TypeCheckError
 general/invocations: RuntimeError
@@ -90,7 +90,6 @@
 general_nnbd_opt_out/error_locations/error_location_06: RuntimeError
 general_nnbd_opt_out/expressions: RuntimeError
 general_nnbd_opt_out/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
-general_nnbd_opt_out/ignore_function: TypeCheckError
 general_nnbd_opt_out/incomplete_field_formal_parameter: RuntimeError
 general_nnbd_opt_out/invalid_type: TypeCheckError
 general_nnbd_opt_out/invocations: RuntimeError
@@ -122,9 +121,6 @@
 general_nnbd_opt_out/void_methods: RuntimeError
 general_nnbd_opt_out/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
-inference/conflicting_fields: TypeCheckError
-inference/conflicts_can_happen2: TypeCheckError
-inference/conflicts_can_happen: TypeCheckError
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
 inference/constructors_too_many_positional_arguments: InstrumentationMismatch # Issue #30040
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
@@ -140,8 +136,6 @@
 inference/generic_methods_do_not_infer_invalid_override_of_generic_method: TypeCheckError
 inference/generic_methods_handle_override_of_non_generic_with_generic: TypeCheckError
 inference/generic_methods_infer_js_builtin: InstrumentationMismatch # Issue #30029
-inference/inconsistent_overrides: TypeCheckError
-inference/infer_field_override_multiple: TypeCheckError
 inference/infer_method_missing_params: ExpectationFileMismatch # Not supposed to be able to infer types if supertypes disagree on number of parameters. An error may be missing as C.f and B.f are not compatible at all.
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_type_regardless_of_declaration_order_or_cycles: RuntimeError
@@ -161,15 +155,13 @@
 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/infer_field_getter_setter_mismatch: TypeCheckError
-inference_new/infer_field_override_accessors: TypeCheckError
-inference_new/infer_field_override_getter_overrides_setter: 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/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
+nnbd/never_opt_out: TypeCheckError
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
 rasta/bad_continue: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index ef849a5..f0f4208 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -192,7 +192,7 @@
 general/if_null_in_cascade: TextSerializationFailure
 general/if_null_in_list_literal: TextSerializationFailure
 general/if_null_in_set_literal: TextSerializationFailure
-general/ignore_function: TypeCheckError
+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
@@ -204,6 +204,7 @@
 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/interface_contravariant_from_class: TextSerializationFailure
 general/interface_covariantImpl_from_class: TextSerializationFailure
 general/interface_covariantInterface_from_class: TextSerializationFailure
@@ -468,7 +469,7 @@
 general_nnbd_opt_out/if_null_in_cascade: TextSerializationFailure
 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: TypeCheckError
+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/implicit_const_with_static_fields: TextSerializationFailure # Was: Pass
@@ -663,10 +664,9 @@
 inference/complex_predecrement: TextSerializationFailure # Was: Pass
 inference/conditional_lub: TextSerializationFailure # Was: Pass
 inference/conditional_upwards_inference: TextSerializationFailure # Was: Pass
-inference/conflicting_fields: ExpectationFileMismatch
-inference/conflicting_fields: TypeCheckError
-inference/conflicts_can_happen2: TypeCheckError
-inference/conflicts_can_happen: TypeCheckError
+inference/conflicting_fields: TextSerializationFailure
+inference/conflicts_can_happen2: TextSerializationFailure
+inference/conflicts_can_happen: 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
@@ -779,7 +779,7 @@
 inference/generic_methods_nested_generic_instantiation: TextSerializationFailure # Was: Pass
 inference/generic_methods_uses_greatest_lower_bound: TextSerializationFailure # Was: Pass
 inference/greatest_closure_multiple_params: TextSerializationFailure # Was: Pass
-inference/inconsistent_overrides: TypeCheckError
+inference/inconsistent_overrides: TextSerializationFailure
 inference/index_assign_operator_return_type: TextSerializationFailure # Was: Pass
 inference/index_assign_operator_return_type_2: TextSerializationFailure # Was: Pass
 inference/infer_accessor_from_later_inferred_field: TextSerializationFailure # Was: Pass
@@ -813,7 +813,7 @@
 inference/infer_field_from_later_inferred_field: TextSerializationFailure # Was: Pass
 inference/infer_field_from_later_inferred_getter: TextSerializationFailure # Was: Pass
 inference/infer_field_from_later_inferred_setter: TextSerializationFailure # Was: Pass
-inference/infer_field_override_multiple: TypeCheckError
+inference/infer_field_override_multiple: TextSerializationFailure
 inference/infer_field_override_of_override: TextSerializationFailure # Was: Pass
 inference/infer_field_override_with_substitution: TextSerializationFailure # Was: Pass
 inference/infer_field_overrides_getter: TextSerializationFailure # Was: Pass
@@ -1091,9 +1091,9 @@
 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: TypeCheckError
-inference_new/infer_field_override_accessors: TypeCheckError
-inference_new/infer_field_override_getter_overrides_setter: TypeCheckError
+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
@@ -1190,6 +1190,8 @@
 late_lowering/instance_nullable_field_without_initializer: TextSerializationFailure
 late_lowering/instance_nullable_final_field_without_initializer: TextSerializationFailure
 late_lowering/issue40093: TextSerializationFailure
+late_lowering/issue40373: TextSerializationFailure
+late_lowering/issue40373b: TextSerializationFailure
 late_lowering/late_field_with_initializer: TextSerializationFailure
 late_lowering/late_field_without_initializer: TextSerializationFailure
 late_lowering/late_final_field_with_initializer: TextSerializationFailure
@@ -1241,6 +1243,9 @@
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/missing_required_named_parameter: TextSerializationFailure
+nnbd/mixin_from_opt_in: TextSerializationFailure
+nnbd/mixin_from_opt_out: 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
@@ -1248,6 +1253,7 @@
 nnbd/no_null_shorting_explicit_extension: TextSerializationFailure
 nnbd/no_null_shorting_extension: TextSerializationFailure
 nnbd/non_nullable_field_initialization: TextSerializationFailure
+nnbd/nsm_from_opt_in: TextSerializationFailure
 nnbd/null_access: TextSerializationFailure
 nnbd/null_aware_chain: TextSerializationFailure
 nnbd/null_check: TextSerializationFailure
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect
index 44fe61a..aca96a6 100644
--- a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → self::A*
     ;
 }
-abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A /*isMixinDeclaration*/  {
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect
index 0c6c3cdf..f0cf002 100644
--- a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect
@@ -7,6 +7,6 @@
     : super core::Object::•()
     ;
 }
-abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A /*isMixinDeclaration*/  {
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect
index 0c6c3cdf..f0cf002 100644
--- a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect
@@ -7,6 +7,6 @@
     : super core::Object::•()
     ;
 }
-abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A /*isMixinDeclaration*/  {
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index e0cb48b..2f7c797 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -32,7 +32,6 @@
 general_nnbd_opt_out/error_locations/error_location_06: RuntimeError
 general_nnbd_opt_out/expressions: RuntimeError
 general_nnbd_opt_out/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
-general_nnbd_opt_out/ignore_function: TypeCheckError
 general_nnbd_opt_out/incomplete_field_formal_parameter: RuntimeError
 general_nnbd_opt_out/invalid_type: TypeCheckError
 general_nnbd_opt_out/invocations: RuntimeError
@@ -65,4 +64,5 @@
 general_nnbd_opt_out/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
-nnbd/messages_with_types_opt_out: TypeCheckError
\ No newline at end of file
+nnbd/messages_with_types_opt_out: TypeCheckError
+nnbd/never_opt_out: TypeCheckError
\ No newline at end of file
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 04def33..f31999a 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -254,7 +254,8 @@
 
   @override
   void visitInterfaceType(InterfaceType node, StringBuffer sb) {
-    sb.write(computeName(node.classNode));
+    Class cls = node.classNode;
+    sb.write(computeName(cls));
     if (node.typeArguments.isNotEmpty) {
       sb.write("<");
       bool first = true;
@@ -265,7 +266,13 @@
       }
       sb.write(">");
     }
-    writeNullability(node.nullability, sb);
+    Uri clsImportUri = cls.enclosingLibrary.importUri;
+    bool isNull = cls.name == "Null" &&
+        clsImportUri.scheme == "dart" &&
+        clsImportUri.path == "core";
+    if (!isNull) {
+      writeNullability(node.nullability, sb);
+    }
   }
 
   @override
diff --git a/pkg/front_end/tool/_fasta/deps.dart b/pkg/front_end/tool/_fasta/deps.dart
new file mode 100644
index 0000000..3b83d0f
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/deps.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'entry_points.dart' show depsEntryPoint;
+
+main(List<String> arguments) => depsEntryPoint(arguments);
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 4bb712b..7676f1d 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -101,6 +101,17 @@
   }
 }
 
+depsEntryPoint(List<String> arguments) async {
+  installAdditionalTargets();
+
+  for (int i = 0; i < iterations; i++) {
+    if (i > 1) {
+      print("\n");
+    }
+    await deps(arguments);
+  }
+}
+
 compilePlatformEntryPoint(List<String> arguments) async {
   installAdditionalTargets();
   for (int i = 0; i < iterations; i++) {
@@ -228,6 +239,20 @@
   });
 }
 
+Future<Uri> deps(List<String> arguments) async {
+  return await runProtectedFromAbort<Uri>(() async {
+    return await withGlobalOptions("deps", arguments, true,
+        (CompilerContext c, _) async {
+      if (c.options.verbose) {
+        print("Computing deps: ${arguments.join(' ')}");
+      }
+      CompileTask task =
+          new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
+      return await task.buildDeps(c.options.output);
+    });
+  });
+}
+
 class CompileTask {
   final CompilerContext c;
   final Ticker ticker;
@@ -243,6 +268,30 @@
     return new KernelTarget(c.fileSystem, false, dillTarget, uriTranslator);
   }
 
+  Future<Uri> buildDeps([Uri output]) async {
+    UriTranslator uriTranslator = await c.options.getUriTranslator();
+    ticker.logMs("Read packages file");
+    DillTarget dillTarget = createDillTarget(uriTranslator);
+    KernelTarget kernelTarget = createKernelTarget(dillTarget, uriTranslator);
+    Uri platform = c.options.sdkSummary;
+    if (platform != null) {
+      // TODO(CFE-Team): Probably this should be read through the filesystem as
+      // well and the recording would be automatic.
+      _appendDillForUri(dillTarget, platform);
+      CompilerContext.recordDependency(platform);
+    }
+    kernelTarget.setEntryPoints(c.options.inputs);
+    await dillTarget.buildOutlines();
+    await kernelTarget.loader.buildOutlines();
+
+    Uri dFile;
+    if (output != null) {
+      dFile = new File(new File.fromUri(output).path + ".d").uri;
+      await writeDepsFile(output, dFile, c.dependencies);
+    }
+    return dFile;
+  }
+
   Future<KernelTarget> buildOutline([Uri output]) async {
     UriTranslator uriTranslator = await c.options.getUriTranslator();
     ticker.logMs("Read packages file");
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 6c70435..2762192 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 38;
+  UInt32 formatVersion = 39;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -317,7 +317,8 @@
   FileOffset fileOffset; // Offset of the name of the class.
   FileOffset fileEndOffset;
   Byte flags (levelBit0, levelBit1, isAbstract, isEnum, isAnonymousMixin,
-              isEliminatedMixin, isMixinDeclaration); // Where level is index into ClassLevel
+              isEliminatedMixin, isMixinDeclaration, 
+              hasConstConstructor); // Where level is index into ClassLevel
   StringReference name;
   List<Expression> annotations;
   List<TypeParameter> typeParameters;
@@ -367,7 +368,8 @@
   FileOffset fileOffset;
   FileOffset fileEndOffset;
   UInt flags (isFinal, isConst, isStatic, hasImplicitGetter, hasImplicitSetter,
-                isCovariant, isGenericCovariantImpl, isLate, isExtensionMember);
+                isCovariant, isGenericCovariantImpl, isLate, isExtensionMember,
+                isNonNullableByDefault);
   Name name;
   List<Expression> annotations;
   DartType type;
@@ -381,7 +383,7 @@
   FileOffset startFileOffset; // Offset of the start of the constructor including any annotations.
   FileOffset fileOffset; // Offset of the constructor name.
   FileOffset fileEndOffset;
-  Byte flags (isConst, isExternal, isSynthetic);
+  Byte flags (isConst, isExternal, isSynthetic, isNonNullableByDefault);
   Name name;
   List<Expression> annotations;
   FunctionNode function;
@@ -409,7 +411,8 @@
   Byte kind; // Index into the ProcedureKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst, isForwardingStub,
               isForwardingSemiStub, isRedirectingFactoryConstructor,
-              isNoSuchMethodForwarder, isExtensionMember, isMemberSignature);
+              isNoSuchMethodForwarder, isExtensionMember, isMemberSignature,
+              isNonNullableByDefault);
   Name name;
   List<Expression> annotations;
   // Only present if the 'isForwardingStub' flag is set.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 1b452d2..141595f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -913,6 +913,7 @@
   static const int FlagAnonymousMixin = 1 << 4;
   static const int FlagEliminatedMixin = 1 << 5;
   static const int FlagMixinDeclaration = 1 << 6;
+  static const int FlagHasConstConstructor = 1 << 7;
 
   int flags = 0;
 
@@ -971,6 +972,15 @@
         : (flags & ~FlagMixinDeclaration);
   }
 
+  /// True if this class declares one or more constant constructors.
+  bool get hasConstConstructor => flags & FlagHasConstConstructor != 0;
+
+  void set hasConstConstructor(bool value) {
+    flags = value
+        ? (flags | FlagHasConstConstructor)
+        : (flags & ~FlagHasConstConstructor);
+  }
+
   List<Supertype> superclassConstraints() {
     var constraints = <Supertype>[];
 
@@ -1532,6 +1542,11 @@
   ///
   bool get isExtensionMember;
 
+  /// If `true` this member is defined in a library for which non-nullable by
+  /// default is enabled.
+  bool get isNonNullableByDefault;
+  void set isNonNullableByDefault(bool value);
+
   /// The body of the procedure or constructor, or `null` if this is a field.
   FunctionNode get function => null;
 
@@ -1599,6 +1614,7 @@
   static const int FlagGenericCovariantImpl = 1 << 6;
   static const int FlagLate = 1 << 7;
   static const int FlagExtensionMember = 1 << 8;
+  static const int FlagNonNullableByDefault = 1 << 9;
 
   /// Whether the field is declared with the `covariant` keyword.
   bool get isCovariant => flags & FlagCovariant != 0;
@@ -1694,6 +1710,16 @@
     if (value) throw 'Fields cannot be external';
   }
 
+  @override
+  bool get isNonNullableByDefault => flags & FlagNonNullableByDefault != 0;
+
+  @override
+  void set isNonNullableByDefault(bool value) {
+    flags = value
+        ? (flags | FlagNonNullableByDefault)
+        : (flags & ~FlagNonNullableByDefault);
+  }
+
   R accept<R>(MemberVisitor<R> v) => v.visitField(this);
 
   acceptReference(MemberReferenceVisitor v) => v.visitFieldReference(this);
@@ -1766,6 +1792,7 @@
   static const int FlagConst = 1 << 0; // Must match serialized bit positions.
   static const int FlagExternal = 1 << 1;
   static const int FlagSynthetic = 1 << 2;
+  static const int FlagNonNullableByDefault = 1 << 3;
 
   bool get isConst => flags & FlagConst != 0;
   bool get isExternal => flags & FlagExternal != 0;
@@ -1793,6 +1820,16 @@
   @override
   bool get isExtensionMember => false;
 
+  @override
+  bool get isNonNullableByDefault => flags & FlagNonNullableByDefault != 0;
+
+  @override
+  void set isNonNullableByDefault(bool value) {
+    flags = value
+        ? (flags | FlagNonNullableByDefault)
+        : (flags & ~FlagNonNullableByDefault);
+  }
+
   R accept<R>(MemberVisitor<R> v) => v.visitConstructor(this);
 
   acceptReference(MemberReferenceVisitor v) =>
@@ -1901,6 +1938,7 @@
 
   static const int FlagConst = 1 << 0; // Must match serialized bit positions.
   static const int FlagExternal = 1 << 1;
+  static const int FlagNonNullableByDefault = 1 << 2;
 
   bool get isConst => flags & FlagConst != 0;
   bool get isExternal => flags & FlagExternal != 0;
@@ -1922,6 +1960,16 @@
 
   bool get isUnresolved => targetReference == null;
 
+  @override
+  bool get isNonNullableByDefault => flags & FlagNonNullableByDefault != 0;
+
+  @override
+  void set isNonNullableByDefault(bool value) {
+    flags = value
+        ? (flags | FlagNonNullableByDefault)
+        : (flags & ~FlagNonNullableByDefault);
+  }
+
   Member get target => targetReference?.asMember;
 
   void set target(Member member) {
@@ -2080,6 +2128,7 @@
   static const int FlagNoSuchMethodForwarder = 1 << 7;
   static const int FlagExtensionMember = 1 << 8;
   static const int FlagMemberSignature = 1 << 9;
+  static const int FlagNonNullableByDefault = 1 << 10;
 
   bool get isStatic => flags & FlagStatic != 0;
   bool get isAbstract => flags & FlagAbstract != 0;
@@ -2185,6 +2234,16 @@
   bool get hasSetter => kind == ProcedureKind.Setter;
   bool get isFactory => kind == ProcedureKind.Factory;
 
+  @override
+  bool get isNonNullableByDefault => flags & FlagNonNullableByDefault != 0;
+
+  @override
+  void set isNonNullableByDefault(bool value) {
+    flags = value
+        ? (flags | FlagNonNullableByDefault)
+        : (flags & ~FlagNonNullableByDefault);
+  }
+
   Member get forwardingStubSuperTarget =>
       forwardingStubSuperTargetReference?.asMember;
 
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index f45810b..dec7c71 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 = 38;
+  static const int BinaryFormatVersion = 39;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 717f0a5..da3e50b 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -15,6 +15,7 @@
 import 'src/future_or.dart';
 import 'src/heap.dart';
 import 'src/legacy_erasure.dart';
+import 'src/norm.dart';
 
 typedef HandleAmbiguousSupertypes = void Function(Class, Supertype, Supertype);
 
@@ -1581,7 +1582,10 @@
       genericSuperTypes[cls].add(type);
 
       if (classNode.enclosingLibrary.isNonNullableByDefault) {
-        Supertype result = nnbdTopMergeSupertype(coreTypes, type, canonical);
+        Supertype result = nnbdTopMergeSupertype(
+            coreTypes,
+            normSupertype(coreTypes, type),
+            normSupertype(coreTypes, canonical));
         if (result == null) {
           onAmbiguousSupertypes(classNode, canonical, type);
         } else {
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 6670ec6..bb3dd53 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -1262,4 +1262,109 @@
     }
     return result;
   }
+
+  /// Checks if [type] satisfies the TOP predicate.
+  ///
+  /// For the definition of TOP see the following:
+  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
+  bool isTop(DartType type) {
+    if (type is InvalidType) return false;
+
+    // TOP(dynamic) is true.
+    if (type is DynamicType) return true;
+
+    // TOP(void) is true.
+    if (type is VoidType) return true;
+
+    // TOP(T?) is true iff TOP(T) or OBJECT(T).
+    // TOP(T*) is true iff TOP(T) or OBJECT(T).
+    if (type.nullability == Nullability.nullable ||
+        type.nullability == Nullability.legacy) {
+      DartType nonNullableType = type.withNullability(Nullability.nonNullable);
+      assert(type != nonNullableType);
+      return isTop(nonNullableType) || isObject(nonNullableType);
+    }
+
+    // TOP(FutureOr<T>) is TOP(T).
+    if (type is InterfaceType && type.classNode == futureOrClass) {
+      return isTop(type.typeArguments.single);
+    }
+
+    return false;
+  }
+
+  /// Checks if [type] satisfies the OBJECT predicate.
+  ///
+  /// For the definition of OBJECT see the following:
+  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
+  bool isObject(DartType type) {
+    if (type is InvalidType) return false;
+
+    // OBJECT(Object) is true.
+    if (type is InterfaceType &&
+        type.classNode == objectClass &&
+        type.nullability == Nullability.nonNullable) {
+      return true;
+    }
+
+    // OBJECT(FutureOr<T>) is OBJECT(T).
+    if (type is InterfaceType &&
+        type.classNode == futureOrClass &&
+        type.nullability == Nullability.nonNullable) {
+      return isObject(type.typeArguments.single);
+    }
+
+    return false;
+  }
+
+  /// Checks if [type] satisfies the BOTTOM predicate.
+  ///
+  /// For the definition of BOTTOM see the following:
+  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
+  bool isBottom(DartType type) {
+    if (type is InvalidType) return false;
+
+    // BOTTOM(Never) is true.
+    if (type is NeverType && type.nullability == Nullability.nonNullable) {
+      return true;
+    }
+
+    // BOTTOM(X&T) is true iff BOTTOM(T).
+    if (type is TypeParameterType &&
+        type.promotedBound != null &&
+        type.isPotentiallyNonNullable) {
+      return isBottom(type.promotedBound);
+    }
+
+    // BOTTOM(X extends T) is true iff BOTTOM(T).
+    if (type is TypeParameterType && type.isPotentiallyNonNullable) {
+      assert(type.promotedBound == null);
+      return isBottom(type.parameter.bound);
+    }
+
+    if (type is BottomType) return true;
+
+    return false;
+  }
+
+  /// Checks if [type] satisfies the NULL predicate.
+  ///
+  /// For the definition of NULL see the following:
+  /// https://github.com/dart-lang/language/blob/master/resources/type-system/upper-lower-bounds.md#helper-predicates
+  bool isNull(DartType type) {
+    if (type is InvalidType) return false;
+
+    // NULL(Null) is true.
+    if (type == nullType) return true;
+
+    // NULL(T?) is true iff NULL(T) or BOTTOM(T).
+    // NULL(T*) is true iff NULL(T) or BOTTOM(T).
+    if (type.nullability == Nullability.nullable ||
+        type.nullability == Nullability.legacy) {
+      DartType nonNullableType = type.withNullability(Nullability.nonNullable);
+      return isBottom(nonNullableType);
+    }
+
+    return false;
+  }
 }
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index b2e6f6c..c7d012a 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -92,8 +92,7 @@
       } else {
         final DartType ownType = getterType(host, ownMember);
         final DartType superType = getterType(host, superMember);
-        if (!environment.isSubtypeOf(
-            ownType, superType, SubtypeCheckMode.ignoringNullabilities)) {
+        if (!_isSubtypeOf(ownType, superType)) {
           return failures.reportInvalidOverride(ownMember, superMember, '''
 ${ownType} is not a subtype of ${superType}
 ''');
@@ -109,8 +108,13 @@
 
   /// Check if [subtype] is subtype of [supertype] after applying
   /// type parameter [substitution].
-  bool _isSubtypeOf(DartType subtype, DartType supertype) => environment
-      .isSubtypeOf(subtype, supertype, SubtypeCheckMode.ignoringNullabilities);
+  bool _isSubtypeOf(DartType subtype, DartType supertype) {
+    if (subtype is InvalidType || supertype is InvalidType) {
+      return true;
+    }
+    return environment.isSubtypeOf(
+        subtype, supertype, SubtypeCheckMode.ignoringNullabilities);
+  }
 
   Substitution _makeSubstitutionForMember(Class host, Member member) {
     final hostType =
@@ -235,11 +239,7 @@
   @override
   void checkAssignable(TreeNode where, DartType from, DartType to) {
     // Note: we permit implicit downcasts.
-    if (from != to &&
-        !environment.isSubtypeOf(
-            from, to, SubtypeCheckMode.ignoringNullabilities) &&
-        !environment.isSubtypeOf(
-            to, from, SubtypeCheckMode.ignoringNullabilities)) {
+    if (from != to && !_isSubtypeOf(from, to) && !_isSubtypeOf(to, from)) {
       failures.reportNotAssignable(where, from, to);
     }
   }
diff --git a/pkg/kernel/lib/src/norm.dart b/pkg/kernel/lib/src/norm.dart
new file mode 100644
index 0000000..5c161a9
--- /dev/null
+++ b/pkg/kernel/lib/src/norm.dart
@@ -0,0 +1,161 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE.md file.
+
+import '../ast.dart' hide MapEntry;
+import '../core_types.dart';
+
+import 'future_or.dart';
+import 'replacement_visitor.dart';
+
+/// Returns normalization of [type].
+DartType norm(CoreTypes coreTypes, DartType type) {
+  return type.accept(new _Norm(coreTypes)) ?? type;
+}
+
+Supertype normSupertype(CoreTypes coreTypes, Supertype supertype) {
+  if (supertype.typeArguments.isEmpty) return supertype;
+  _Norm normVisitor = new _Norm(coreTypes);
+  List<DartType> typeArguments = null;
+  for (int i = 0; i < supertype.typeArguments.length; ++i) {
+    DartType typeArgument = supertype.typeArguments[i].accept(normVisitor);
+    if (typeArgument != null) {
+      typeArguments ??= supertype.typeArguments.toList();
+      typeArguments[i] = typeArgument;
+    }
+  }
+  if (typeArguments == null) return supertype;
+  return new Supertype(supertype.classNode, typeArguments);
+}
+
+/// Visitor implementing the NORM algorithm.
+///
+/// Visitor's methods return null if the type is unchanged by the NORM
+/// algorithm.  The algorithm is specified at
+/// https://github.com/dart-lang/language/blob/master/resources/type-system/normalization.md
+class _Norm extends ReplacementVisitor {
+  final CoreTypes coreTypes;
+
+  _Norm(this.coreTypes);
+
+  @override
+  DartType visitInterfaceType(InterfaceType node) {
+    if (node.classNode == coreTypes.futureOrClass) {
+      DartType typeArgument = node.typeArguments.single;
+      typeArgument = typeArgument.accept(this) ?? typeArgument;
+      if (coreTypes.isTop(typeArgument)) {
+        Nullability nullabilityAsProperty =
+            computeNullability(typeArgument, coreTypes.futureOrClass);
+        assert(nullabilityAsProperty == Nullability.nullable ||
+            nullabilityAsProperty == Nullability.legacy);
+        // [typeArgument] is nullable because it's a top type.  No need to unite
+        // the nullabilities of [node] and [typeArgument].
+        return typeArgument.withNullability(nullabilityAsProperty);
+      } else if (typeArgument is InterfaceType &&
+          typeArgument.classNode == coreTypes.objectClass &&
+          typeArgument.nullability == Nullability.nonNullable) {
+        assert(!coreTypes.isTop(typeArgument));
+        // [typeArgument] is non-nullable, so the union of that and the
+        // nullability of [node] is the nullability of [node].
+        return typeArgument
+            .withNullability(computeNullability(node, coreTypes.futureOrClass));
+      } else if (typeArgument is NeverType &&
+          typeArgument.nullability == Nullability.nonNullable) {
+        assert(!coreTypes.isTop(typeArgument));
+        assert(!coreTypes.isObject(typeArgument));
+        // [typeArgument] is non-nullable, so the union of that and the
+        // nullability of [node] is the nullability of [node].
+        return new InterfaceType(
+            coreTypes.futureClass,
+            computeNullability(node, coreTypes.futureOrClass),
+            <DartType>[typeArgument]);
+      } else if (coreTypes.isNull(typeArgument)) {
+        assert(!coreTypes.isTop(typeArgument));
+        assert(!coreTypes.isObject(typeArgument));
+        assert(!coreTypes.isBottom(typeArgument));
+        return new InterfaceType(
+            coreTypes.futureClass,
+            uniteNullabilities(typeArgument.nullability,
+                computeNullability(node, coreTypes.futureOrClass)),
+            <DartType>[typeArgument]);
+      }
+      assert(!coreTypes.isTop(typeArgument));
+      assert(!coreTypes.isObject(typeArgument));
+      assert(!coreTypes.isBottom(typeArgument));
+      assert(!coreTypes.isNull(typeArgument));
+      return new InterfaceType(
+          coreTypes.futureOrClass,
+          computeNullability(node, coreTypes.futureOrClass),
+          <DartType>[typeArgument]);
+    }
+    return super
+        .visitInterfaceType(node)
+        ?.withNullability(computeNullability(node, coreTypes.futureOrClass));
+  }
+
+  @override
+  DartType visitTypeParameterType(TypeParameterType node) {
+    if (node.promotedBound == null) {
+      DartType bound = node.parameter.bound;
+      if (normalizesToNever(bound)) {
+        DartType result = new NeverType(Nullability.nonNullable)
+            .withNullability(node.nullability);
+        return result.accept(this) ?? result;
+      }
+      assert(!coreTypes.isBottom(bound));
+      // If the bound isn't Never, the type is already normalized.
+      return null;
+    } else {
+      DartType bound = node.promotedBound;
+      bound = bound.accept(this) ?? bound;
+      if (bound is NeverType && bound.nullability == Nullability.nonNullable) {
+        return bound;
+      } else if (coreTypes.isTop(bound)) {
+        assert(!coreTypes.isBottom(bound));
+        assert(bound.nullability == Nullability.nullable);
+        return new TypeParameterType(
+            node.parameter, node.typeParameterTypeNullability);
+      } else if (bound is TypeParameterType &&
+          bound.parameter == node.parameter &&
+          bound.typeParameterTypeNullability ==
+              node.typeParameterTypeNullability &&
+          bound.promotedBound == null) {
+        assert(!coreTypes.isBottom(bound));
+        assert(!coreTypes.isTop(bound));
+        return new TypeParameterType(
+            node.parameter, node.typeParameterTypeNullability);
+      } else if (bound == coreTypes.objectNonNullableRawType &&
+          norm(coreTypes, node.parameter.bound) ==
+              coreTypes.objectNonNullableRawType) {
+        return new TypeParameterType(
+            node.parameter, node.typeParameterTypeNullability);
+      } else if (identical(bound, node.promotedBound)) {
+        // If [bound] is identical to [node.promotedBound], then the NORM
+        // algorithms didn't change the promoted bound, so the [node] is
+        // unchanged as well, and we return null to indicate that.
+        return null;
+      }
+      return new TypeParameterType(
+          node.parameter, node.typeParameterTypeNullability, bound);
+    }
+  }
+
+  @override
+  DartType visitNeverType(NeverType node) {
+    if (node.nullability == Nullability.nullable) return coreTypes.nullType;
+    return null;
+  }
+
+  bool normalizesToNever(DartType type) {
+    if (type is NeverType && type.nullability == Nullability.nonNullable) {
+      return true;
+    } else if (type is TypeParameterType) {
+      if (type.promotedBound == null) {
+        return normalizesToNever(type.parameter.bound);
+      } else {
+        return normalizesToNever(type.promotedBound);
+      }
+    }
+    return false;
+  }
+}
diff --git a/pkg/kernel/lib/testing/type_parser_environment.dart b/pkg/kernel/lib/testing/type_parser_environment.dart
index 4129fc5..0f066b2 100644
--- a/pkg/kernel/lib/testing/type_parser_environment.dart
+++ b/pkg/kernel/lib/testing/type_parser_environment.dart
@@ -115,6 +115,11 @@
   DartType parseType(String text) {
     return _libraryEnvironment.parseType(text);
   }
+
+  void extendWithTypeParameters(String typeParameters) {
+    _libraryEnvironment =
+        _libraryEnvironment.extendWithTypeParameters(typeParameters);
+  }
 }
 
 class TypeParserEnvironment {
@@ -229,11 +234,15 @@
           arguments[i].accept<Node, TypeParserEnvironment>(this, environment);
     }
     if (declaration is Class) {
+      Nullability nullability =
+          interpretParsedNullability(node.parsedNullability);
       if (declaration.name == 'Null' &&
           declaration.enclosingLibrary.importUri.scheme == 'dart' &&
-          declaration.enclosingLibrary.importUri.path == 'core' &&
-          node.parsedNullability != ParsedNullability.nullable) {
-        throw "Null type must be written as 'Null?'";
+          declaration.enclosingLibrary.importUri.path == 'core') {
+        if (node.parsedNullability != ParsedNullability.omitted) {
+          throw "Null type must be written without explicit nullability";
+        }
+        nullability = Nullability.nullable;
       }
       List<TypeParameter> typeVariables = declaration.typeParameters;
       if (kernelArguments.isEmpty && typeVariables.isNotEmpty) {
@@ -244,8 +253,7 @@
       } else if (kernelArguments.length != typeVariables.length) {
         throw "Expected ${typeVariables.length} type arguments: $node";
       }
-      return new InterfaceType(declaration,
-          interpretParsedNullability(node.parsedNullability), kernelArguments);
+      return new InterfaceType(declaration, nullability, kernelArguments);
     } else if (declaration is TypeParameter) {
       if (arguments.isNotEmpty) {
         throw "Type variable can't have arguments (${node.name})";
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 06bd220..72fb6e7 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -409,6 +409,9 @@
     if (library.name != null) {
       writeWord(library.name);
     }
+    if (library.isNonNullableByDefault) {
+      writeWord("/*isNonNullableByDefault*/");
+    }
     endLine(';');
 
     LibraryImportTable imports = new LibraryImportTable(library);
@@ -1071,11 +1074,23 @@
       writeSpaced('=');
       writeExpression(node.initializer);
     }
+    List<String> features = <String>[];
+    if (node.enclosingLibrary.isNonNullableByDefault !=
+        node.isNonNullableByDefault) {
+      if (node.isNonNullableByDefault) {
+        features.add("isNonNullableByDefault");
+      } else {
+        features.add("isNullableByDefault");
+      }
+    }
     if ((node.enclosingClass == null &&
             node.enclosingLibrary.fileUri != node.fileUri) ||
         (node.enclosingClass != null &&
             node.enclosingClass.fileUri != node.fileUri)) {
-      writeWord("/* from ${node.fileUri} */");
+      features.add(" from ${node.fileUri} ");
+    }
+    if (features.isNotEmpty) {
+      writeWord("/*${features.join(',')}*/");
     }
     endLine(';');
   }
@@ -1091,11 +1106,23 @@
     writeModifier(node.isMemberSignature, 'member-signature');
     writeModifier(node.isNoSuchMethodForwarder, 'no-such-method-forwarder');
     writeWord(procedureKindToString(node.kind));
+    List<String> features = <String>[];
+    if (node.enclosingLibrary.isNonNullableByDefault !=
+        node.isNonNullableByDefault) {
+      if (node.isNonNullableByDefault) {
+        features.add("isNonNullableByDefault");
+      } else {
+        features.add("isNullableByDefault");
+      }
+    }
     if ((node.enclosingClass == null &&
             node.enclosingLibrary.fileUri != node.fileUri) ||
         (node.enclosingClass != null &&
             node.enclosingClass.fileUri != node.fileUri)) {
-      writeWord("/* from ${node.fileUri} */");
+      features.add(" from ${node.fileUri} ");
+    }
+    if (features.isNotEmpty) {
+      writeWord("/*${features.join(',')}*/");
     }
     writeFunction(node.function, name: getMemberName(node));
   }
@@ -1107,6 +1134,18 @@
     writeModifier(node.isConst, 'const');
     writeModifier(node.isSynthetic, 'synthetic');
     writeWord('constructor');
+    List<String> features = <String>[];
+    if (node.enclosingLibrary.isNonNullableByDefault !=
+        node.isNonNullableByDefault) {
+      if (node.isNonNullableByDefault) {
+        features.add("isNonNullableByDefault");
+      } else {
+        features.add("isNullableByDefault");
+      }
+    }
+    if (features.isNotEmpty) {
+      writeWord("/*${features.join(',')}*/");
+    }
     writeFunction(node.function,
         name: node.name, initializers: node.initializers);
   }
@@ -1131,6 +1170,18 @@
       writeList(node.typeArguments, writeType);
       writeSymbol('>');
     }
+    List<String> features = <String>[];
+    if (node.enclosingLibrary.isNonNullableByDefault !=
+        node.isNonNullableByDefault) {
+      if (node.isNonNullableByDefault) {
+        features.add("isNonNullableByDefault");
+      } else {
+        features.add("isNullableByDefault");
+      }
+    }
+    if (features.isNotEmpty) {
+      writeWord("/*${features.join(',')}*/");
+    }
     endLine(';');
   }
 
@@ -1154,6 +1205,25 @@
       writeSpaced('implements');
       writeList(node.implementedTypes, visitSupertype);
     }
+    List<String> features = <String>[];
+    if (node.isEnum) {
+      features.add('isEnum');
+    }
+    if (node.isAnonymousMixin) {
+      features.add('isAnonymousMixin');
+    }
+    if (node.isEliminatedMixin) {
+      features.add('isEliminatedMixin');
+    }
+    if (node.isMixinDeclaration) {
+      features.add('isMixinDeclaration');
+    }
+    if (node.hasConstConstructor) {
+      features.add('hasConstConstructor');
+    }
+    if (features.isNotEmpty) {
+      writeSpaced('/*${features.join(',')}*/');
+    }
     var endLineString = ' {';
     if (node.enclosingLibrary.fileUri != node.fileUri) {
       endLineString += ' // from ${node.fileUri}';
@@ -2108,7 +2178,7 @@
   }
 
   visitNeverType(NeverType node) {
-    write('Never');
+    writeWord('Never');
     writeNullability(node.nullability);
   }
 
diff --git a/pkg/kernel/test/legacy_erasure_test.dart b/pkg/kernel/test/legacy_erasure_test.dart
index bf32877..4757d00 100644
--- a/pkg/kernel/test/legacy_erasure_test.dart
+++ b/pkg/kernel/test/legacy_erasure_test.dart
@@ -9,9 +9,9 @@
 import 'package:kernel/testing/type_parser_environment.dart';
 
 const Map<String, String> data = {
-  'Null?': 'Null?',
-  'Never': 'Null?',
-  'Never?': 'Null?',
+  'Null': 'Null',
+  'Never': 'Null',
+  'Never?': 'Null',
   'void': 'void',
   'dynamic': 'dynamic',
   'bool': 'bool*',
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index 91afe96..73240b0 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_test.dart
@@ -23,9 +23,9 @@
   'Object? vs dynamic': 'Object?',
   'Object* vs dynamic': null,
   'Object vs dynamic': null,
-  'Never? vs Null?': null,
-  'Never* vs Null?': 'Null?',
-  'Never vs Null?': null,
+  'Never? vs Null': null,
+  'Never* vs Null': 'Null',
+  'Never vs Null': null,
   'int? vs int?': 'int?',
   'int? vs int*': 'int?',
   'int* vs int*': 'int*',
diff --git a/pkg/kernel/test/norm_test.dart b/pkg/kernel/test/norm_test.dart
new file mode 100644
index 0000000..b8a5f3e
--- /dev/null
+++ b/pkg/kernel/test/norm_test.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All 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" show Expect;
+
+import 'package:kernel/ast.dart' hide MapEntry;
+import 'package:kernel/src/norm.dart';
+import 'package:kernel/testing/type_parser_environment.dart';
+
+run() {
+  checkNormToSame('Null');
+  checkNormToSame('Never');
+  check('Never?', 'Null');
+  checkNormToSame('Never*');
+  checkNormToSame('void');
+  checkNormToSame('dynamic');
+  checkNormToSame('Object?');
+  check('FutureOr<dynamic>', 'dynamic');
+  check('FutureOr<void>', 'void');
+  check('FutureOr<Object>', 'Object');
+  check('FutureOr<Object?>', 'Object?');
+  check('FutureOr<Object*>', 'Object*');
+  check('FutureOr<Never>', 'Future<Never>');
+  check('FutureOr<Never?>', 'Future<Null>?');
+
+  // TODO(dmitryas): Use the following test case instead when FutureOr can
+  // distinguish between the declared nullability and the nullability as a
+  // property.
+  //
+  //check('FutureOr<Never*>', 'Future<Never*>');
+  check('FutureOr<Never*>', 'Future<Never*>*');
+
+  check('FutureOr<Null>', 'Future<Null>?');
+  check('FutureOr<FutureOr<dynamic>>', 'dynamic');
+  check('FutureOr<FutureOr<void>>', 'void');
+  check('FutureOr<FutureOr<Object>>', 'Object');
+  check('FutureOr<FutureOr<Object?>>', 'Object?');
+  check('FutureOr<FutureOr<Object*>>', 'Object*');
+  check('FutureOr<FutureOr<Never>>', 'FutureOr<Future<Never>>');
+
+  // TODO(dmitryas): Use the following test case instead when FutureOr can
+  // distinguish between the declared nullability and the nullability as a
+  // property.
+  //
+  //check('FutureOr<FutureOr<Never?>>', 'FutureOr<Future<Null>?>');
+  check('FutureOr<FutureOr<Never?>>', 'FutureOr<Future<Null>?>?');
+
+  // TODO(dmitryas): Use the following test case instead when FutureOr can
+  // distinguish between the declared nullability and the nullability as a
+  // property.
+  //
+  //check('FutureOr<FutureOr<Never*>>', 'FutureOr<Future<Never*>>');
+  check('FutureOr<FutureOr<Never*>>', 'FutureOr<Future<Never*>*>*');
+
+  // TODO(dmitryas): Use the following test case instead when FutureOr can
+  // distinguish between the declared nullability and the nullability as a
+  // property.
+  //
+  //check('FutureOr<FutureOr<Null>>', 'FutureOr<Future<Null>?>');
+  check('FutureOr<FutureOr<Null>>', 'FutureOr<Future<Null>?>?');
+
+  checkNormToSame('bool');
+  checkNormToSame('bool?');
+  checkNormToSame('bool*');
+
+  checkNormToSame('List<bool>');
+  checkNormToSame('List<bool?>');
+  checkNormToSame('List<bool*>');
+  checkNormToSame('List<bool>?');
+  checkNormToSame('List<bool?>?');
+  checkNormToSame('List<bool*>?');
+  checkNormToSame('List<bool>*');
+  checkNormToSame('List<bool?>*');
+  checkNormToSame('List<bool*>*');
+  check('List<FutureOr<Object?>>', 'List<Object?>');
+  check('List<T>', 'List<Never>', 'T extends Never');
+  check('List<T?>', 'List<Null>', 'T extends Never');
+
+  checkNormToSame('() ->* bool*');
+  checkNormToSame('() ->? bool*');
+  checkNormToSame('() -> bool*');
+  checkNormToSame('() ->* bool?');
+  checkNormToSame('() ->? bool?');
+  checkNormToSame('() -> bool?');
+  checkNormToSame('() ->* bool');
+  checkNormToSame('() ->? bool');
+  checkNormToSame('() -> bool');
+  check('() ->? List<FutureOr<Object?>>', '() ->? List<Object?>');
+  check('() ->? List<T>', '() ->? List<Never>', 'T extends Never');
+  check('() ->? List<T?>', '() ->? List<Null>',
+      'T extends S, S extends U, U extends Never');
+
+  checkNormToSame('(int*) -> void');
+  checkNormToSame('(int?) -> void');
+  checkNormToSame('(int) -> void');
+  checkNormToSame('([int*]) -> void');
+  checkNormToSame('([int?]) -> void');
+  checkNormToSame('([int]) -> void');
+  checkNormToSame('({int* a}) -> void');
+  checkNormToSame('({int? a}) -> void');
+  checkNormToSame('({int a}) -> void');
+  checkNormToSame('({required int* a}) -> void');
+  checkNormToSame('({required int? a}) -> void');
+  checkNormToSame('({required int a}) -> void');
+  check('(List<FutureOr<Object?>>) -> void', '(List<Object?>) -> void');
+  check('([List<FutureOr<Object?>>]) -> void', '([List<Object?>]) -> void');
+  check('({List<FutureOr<Object?>> x}) -> void', '({List<Object?> x}) -> void');
+  check('({required List<FutureOr<Object?>> x}) -> void',
+      '({required List<Object?> x}) -> void');
+
+  checkNormToSame('<T>(T) -> void');
+  checkNormToSame('<T>(T?) -> void');
+  checkNormToSame('<T extends bool>(T) -> void');
+  checkNormToSame('<T extends List<T>>(T) -> void');
+  check('<T extends List<FutureOr<Object?>>>(T) -> void',
+      '<T extends List<Object?>>(T) -> void');
+
+  checkNormToSame('T', 'T extends Object?');
+  checkNormToSame('T?', 'T extends Object?');
+  checkNormToSame('T', 'T extends FutureOr<Never>');
+  check('T', 'Never', 'T extends Never');
+  check('T & Never', 'Never', 'T extends Object?');
+  check('T', 'Never', 'T extends S, S extends Never');
+  check('List<T?>', 'List<Null>', 'T extends S, S extends Never');
+  check('FutureOr<T?>', 'Future<Null>?', 'T extends S, S extends Never');
+
+  check('FutureOr<FutureOr<dynamic>>', 'dynamic');
+  check('FutureOr<FutureOr<void>>', 'void');
+  check('FutureOr<FutureOr<Object?>>', 'Object?');
+  check('FutureOr<FutureOr<dynamic>?>?', 'dynamic');
+  check('FutureOr<FutureOr<void>?>?', 'void');
+  check('FutureOr<FutureOr<Object?>?>?', 'Object?');
+
+  // TODO(dmitryas): The following test cases should be removed when FutureOr
+  // can distinguish between the declared nullability and the nullability as a
+  // property.
+  check('FutureOr<int?>', 'FutureOr<int?>?');
+  check('FutureOr<FutureOr<int?>>', 'FutureOr<FutureOr<int?>?>?');
+  check('FutureOr<FutureOr<int>?>', 'FutureOr<FutureOr<int>?>?');
+  check('FutureOr<FutureOr<FutureOr<int>>?>',
+      'FutureOr<FutureOr<FutureOr<int>>?>?');
+}
+
+check(String input, String output, [String typeParameters = '']) {
+  Env env = new Env('')..extendWithTypeParameters(typeParameters);
+  DartType inputType = env.parseType(input);
+  DartType expectedOutputType = env.parseType(output);
+  DartType actualOutputType = norm(env.coreTypes, inputType);
+  print('norm($inputType) = $actualOutputType, expected $expectedOutputType');
+  Expect.equals(
+      expectedOutputType,
+      actualOutputType,
+      "Unexpected norm of $inputType ('$input'):\n"
+      "Expected: ${expectedOutputType} ('$output')\n"
+      "Actual: ${actualOutputType}");
+}
+
+checkNormToSame(String type, [String typeParameters = '']) {
+  return check(type, type, typeParameters);
+}
+
+main() => run();
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index f379ffe..de635af 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,5 +1,14 @@
 # Changelog
 
+## 0.2.2
+
+- Finds instruction sections by the dynamic symbols the Dart VM creates instead
+  of assuming there are two text sections.
+
+## 0.2.1
+
+- Added static method Dwarf.fromBuffer.
+
 ## 0.2.0
 
 - API and documentation cleanups
diff --git a/pkg/native_stack_traces/lib/src/dwarf.dart b/pkg/native_stack_traces/lib/src/dwarf.dart
index 751301c..a10a9cd 100644
--- a/pkg/native_stack_traces/lib/src/dwarf.dart
+++ b/pkg/native_stack_traces/lib/src/dwarf.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:math';
+import 'dart:typed_data';
 
 import 'elf.dart';
 import 'reader.dart';
@@ -403,7 +404,8 @@
 /// A class representing a DWARF compilation unit.
 class CompilationUnit {
   final Reader reader;
-  final Dwarf dwarf;
+  final Map<int, _AbbreviationsTable> _abbreviationsTables;
+  final LineNumberInfo _lineNumberInfo;
 
   int size;
   int version;
@@ -412,7 +414,8 @@
   List<DebugInformationEntry> contents;
   Map<int, DebugInformationEntry> referenceTable;
 
-  CompilationUnit.fromReader(this.reader, this.dwarf) {
+  CompilationUnit.fromReader(
+      this.reader, this._abbreviationsTables, this._lineNumberInfo) {
     _read();
   }
 
@@ -428,7 +431,7 @@
       throw FormatException("Expected DWARF version 2, got $version");
     }
     abbreviationOffset = reader.readBytes(4);
-    if (!dwarf.abbreviationTables.containsKey(abbreviationOffset)) {
+    if (!_abbreviationsTables.containsKey(abbreviationOffset)) {
       throw FormatException("No abbreviation table found for offset "
           "0x${paddedHex(abbreviationOffset, 4)}");
     }
@@ -450,7 +453,7 @@
   Iterable<CallInfo> callInfo(int address) {
     for (final unit in contents) {
       final lineNumberProgram =
-          dwarf.lineNumberInfo[unit[_AttributeName.statementList]];
+          _lineNumberInfo[unit[_AttributeName.statementList]];
       final callInfo = unit.callInfo(address, lineNumberProgram);
       if (callInfo != null) {
         return callInfo;
@@ -460,7 +463,7 @@
   }
 
   _AbbreviationsTable get abbreviations =>
-      dwarf.abbreviationTables[abbreviationOffset];
+      _abbreviationsTables[abbreviationOffset];
 
   @override
   String toString() =>
@@ -474,11 +477,13 @@
 /// A class representing a DWARF `.debug_info` section.
 class DebugInfo {
   final Reader reader;
-  final Dwarf dwarf;
+  final Map<int, _AbbreviationsTable> _abbreviationsTables;
+  final LineNumberInfo _lineNumberInfo;
 
   List<CompilationUnit> units;
 
-  DebugInfo.fromReader(this.reader, this.dwarf) {
+  DebugInfo.fromReader(
+      this.reader, this._abbreviationsTables, this._lineNumberInfo) {
     _read();
   }
 
@@ -486,8 +491,8 @@
     reader.reset();
     units = <CompilationUnit>[];
     while (!reader.done) {
-      final unit =
-          CompilationUnit.fromReader(reader.shrink(reader.offset), dwarf);
+      final unit = CompilationUnit.fromReader(
+          reader.shrink(reader.offset), _abbreviationsTables, _lineNumberInfo);
       reader.seek(unit.reader.offset);
       if (unit.size == 0) {
         break;
@@ -1037,28 +1042,42 @@
 
 /// The DWARF debugging information for a Dart snapshot.
 class Dwarf {
-  final Elf elf;
-  Map<int, _AbbreviationsTable> abbreviationTables;
-  DebugInfo debugInfo;
-  LineNumberInfo lineNumberInfo;
-  int _vmStartAddress;
-  int _isolateStartAddress;
+  final Map<int, _AbbreviationsTable> _abbreviationTables;
+  final DebugInfo _debugInfo;
+  final LineNumberInfo _lineNumberInfo;
+  final int _vmStartAddress;
+  final int _isolateStartAddress;
 
-  Dwarf.fromElf(this.elf) {
-    _loadSections();
+  Dwarf._(this._abbreviationTables, this._debugInfo, this._lineNumberInfo,
+      this._vmStartAddress, this._isolateStartAddress);
+
+  /// Attempts to load the DWARF debugging information from the reader.
+  ///
+  /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
+  static Dwarf fromReader(Reader reader) {
+    // Currently, the only DWARF-containing format we recognize is ELF.
+    final elf = Elf.fromReader(reader);
+    if (elf == null) return null;
+    return Dwarf._loadSectionsFromElf(elf);
   }
 
+  /// Attempts to load the DWARF debugging information from the given bytes.
+  ///
+  /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
+  static Dwarf fromBytes(Uint8List bytes) =>
+      Dwarf.fromReader(Reader.fromTypedData(bytes));
+
   /// Attempts to load the DWARF debugging information from the file at [path].
+  ///
   /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
-  factory Dwarf.fromFile(String path) {
-    final elf = Elf.fromFile(path);
-    if (elf == null) return null;
-    return Dwarf.fromElf(elf);
-  }
+  static Dwarf fromFile(String path) => Dwarf.fromReader(Reader.fromFile(path));
 
-  void _loadSections() {
-    final abbrevSection = elf.namedSection(".debug_abbrev").first;
-    abbreviationTables = <int, _AbbreviationsTable>{};
+  static const String _vmSymbol = "_kDartVmSnapshotInstructions";
+  static const String _isolateSymbol = "_kDartIsolateSnapshotInstructions";
+
+  static Dwarf _loadSectionsFromElf(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(
@@ -1068,20 +1087,25 @@
     }
     assert(abbreviationOffset == abbrevSection.reader.length);
 
-    final lineNumberSection = elf.namedSection(".debug_line").first;
-    lineNumberInfo = LineNumberInfo.fromReader(lineNumberSection.reader);
+    final lineNumberSection = elf.namedSections(".debug_line").single;
+    final lineNumberInfo = LineNumberInfo.fromReader(lineNumberSection.reader);
 
-    final infoSection = elf.namedSection(".debug_info").first;
-    debugInfo = DebugInfo.fromReader(infoSection.reader, this);
+    final infoSection = elf.namedSections(".debug_info").single;
+    final debugInfo = DebugInfo.fromReader(
+        infoSection.reader, abbreviationTables, lineNumberInfo);
 
-    final textSegments = elf.namedSection(".text").toList();
-    if (textSegments.length != 2) {
+    final vmStartAddress = elf.namedAddress(_vmSymbol);
+    if (vmStartAddress == -1) {
+      throw FormatException("Expected a dynamic symbol with name ${_vmSymbol}");
+    }
+    final isolateStartAddress = elf.namedAddress(_isolateSymbol);
+    if (isolateStartAddress == -1) {
       throw FormatException(
-          "Expected two text segments for VM and isolate instructions");
+          "Expected a dynamic symbol with name ${_isolateSymbol}");
     }
 
-    _vmStartAddress = textSegments[0].virtualAddress;
-    _isolateStartAddress = textSegments[1].virtualAddress;
+    return Dwarf._(abbreviationTables, debugInfo, lineNumberInfo,
+        vmStartAddress, isolateStartAddress);
   }
 
   /// The call information for the given virtual address. There may be
@@ -1092,7 +1116,7 @@
   /// to user or library code is returned.
   Iterable<CallInfo> callInfoFor(int address,
       {bool includeInternalFrames = false}) {
-    final calls = debugInfo.callInfo(address);
+    final calls = _debugInfo.callInfo(address);
     if (calls != null && !includeInternalFrames) {
       return calls.where((CallInfo c) => c.line > 0);
     }
@@ -1114,10 +1138,10 @@
   @override
   String toString() =>
       "DWARF debugging information:\n\n" +
-      abbreviationTables
+      _abbreviationTables
           .map((int i, _AbbreviationsTable t) =>
               MapEntry(i, "(Offset ${paddedHex(i)}) $t"))
           .values
           .join() +
-      "\n$debugInfo\n$lineNumberInfo";
+      "\n$_debugInfo\n$_lineNumberInfo";
 }
diff --git a/pkg/native_stack_traces/lib/src/elf.dart b/pkg/native_stack_traces/lib/src/elf.dart
index 1fa0d3d..da4efae 100644
--- a/pkg/native_stack_traces/lib/src/elf.dart
+++ b/pkg/native_stack_traces/lib/src/elf.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:typed_data';
-import 'dart:io';
 
 import 'reader.dart';
 
@@ -48,6 +47,11 @@
   }
 }
 
+// Reads an Elf{32,64}_Section.
+int _readElfSection(Reader reader) {
+  return _readElfBytes(reader, 2, 2);
+}
+
 // Used in cases where the value read for a given field is Elf32_Word on 32-bit
 // and Elf64_Xword on 64-bit.
 int _readElfNative(Reader reader) {
@@ -452,6 +456,10 @@
     switch (entry.type) {
       case SectionHeaderEntry._SHT_STRTAB:
         return StringTable(entry, reader);
+      case SectionHeaderEntry._SHT_SYMTAB:
+        return SymbolTable(entry, reader);
+      case SectionHeaderEntry._SHT_DYNSYM:
+        return SymbolTable(entry, reader);
       default:
         return Section(entry, reader);
     }
@@ -473,6 +481,7 @@
   }
 
   String operator [](int index) => _entries[index];
+  bool containsKey(int index) => _entries.containsKey(index);
 
   @override
   String toString() {
@@ -488,94 +497,232 @@
   }
 }
 
+enum SymbolBinding {
+  STB_LOCAL,
+  STB_GLOBAL,
+}
+
+enum SymbolType {
+  STT_NOTYPE,
+  STT_OBJECT,
+  STT_FUNC,
+}
+
+enum SymbolVisibility {
+  STV_DEFAULT,
+  STV_INTERNAL,
+  STV_HIDDEN,
+  STV_PROTECTED,
+}
+
+class Symbol {
+  final int nameIndex;
+  final int info;
+  final int other;
+  final int sectionIndex;
+  final int value;
+  final int size;
+
+  final int _wordSize;
+
+  String name;
+
+  Symbol._(this.nameIndex, this.info, this.other, this.sectionIndex, this.value,
+      this.size, this._wordSize);
+
+  static Symbol fromReader(Reader reader) {
+    final nameIndex = _readElfWord(reader);
+    int info;
+    int other;
+    int sectionIndex;
+    if (reader.wordSize == 8) {
+      info = reader.readByte();
+      other = reader.readByte();
+      sectionIndex = _readElfSection(reader);
+    }
+    final value = _readElfAddress(reader);
+    final size = _readElfNative(reader);
+    if (reader.wordSize == 4) {
+      info = reader.readByte();
+      other = reader.readByte();
+      sectionIndex = _readElfSection(reader);
+    }
+    return Symbol._(
+        nameIndex, info, other, sectionIndex, value, size, reader.wordSize);
+  }
+
+  void _cacheNameFromStringTable(StringTable table) {
+    if (!table.containsKey(nameIndex)) {
+      throw FormatException("Index $nameIndex not found in string table");
+    }
+    name = table[nameIndex];
+  }
+
+  SymbolBinding get bind => SymbolBinding.values[info >> 4];
+  SymbolType get type => SymbolType.values[info & 0x0f];
+  SymbolVisibility get visibility => SymbolVisibility.values[other & 0x03];
+
+  @override
+  String toString() {
+    final buffer = StringBuffer("symbol ");
+    if (name != null) {
+      buffer..write('"')..write(name)..write('" ');
+    }
+    buffer
+      ..write("(")
+      ..write(nameIndex)
+      ..write("): ")
+      ..write(paddedHex(value, _wordSize))
+      ..write(" ")
+      ..write(size)
+      ..write(" sec ")
+      ..write(sectionIndex)
+      ..write(" ")
+      ..write(bind)
+      ..write(" ")
+      ..write(type)
+      ..write(" ")
+      ..write(visibility);
+    return buffer.toString();
+  }
+}
+
+class SymbolTable extends Section {
+  final Iterable<Symbol> _entries;
+  final _nameCache = Map<String, Symbol>();
+
+  SymbolTable(SectionHeaderEntry entry, Reader reader)
+      : _entries = reader.readRepeated(Symbol.fromReader),
+        super(entry, reader);
+
+  void _cacheNames(StringTable stringTable) {
+    _nameCache.clear();
+    for (final symbol in _entries) {
+      symbol._cacheNameFromStringTable(stringTable);
+      _nameCache[symbol.name] = symbol;
+    }
+  }
+
+  Symbol operator [](String name) => _nameCache[name];
+  bool containsKey(String name) => _nameCache.containsKey(name);
+
+  @override
+  String toString() {
+    var buffer = StringBuffer("a symbol table:\n");
+    for (var symbol in _entries) {
+      buffer
+        ..write(" ")
+        ..writeln(symbol);
+    }
+    return buffer.toString();
+  }
+}
+
 class Elf {
-  final Reader startingReader;
+  ElfHeader _header;
+  ProgramHeader _programHeader;
+  SectionHeader _sectionHeader;
+  Map<SectionHeaderEntry, Section> _sections;
 
-  ElfHeader header;
-  ProgramHeader programHeader;
-  SectionHeader sectionHeader;
+  Elf._(this._header, this._programHeader, this._sectionHeader, this._sections);
 
-  Map<SectionHeaderEntry, Section> sections;
-
-  Elf.fromReader(this.startingReader) {
-    _read();
+  /// 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);
   }
 
-  /// Returns either an [Elf] object representing the ELF information in the
-  /// file at [path] or null if the file does not start with the ELF magic
-  /// number.
-  factory Elf.fromFile(String path) {
-    if (!startsWithMagicNumber(path)) return null;
-    return Elf.fromReader(Reader.fromTypedData(File(path).readAsBytesSync(),
-        // We provide null for the wordSize and endianness to ensure
-        // we don't accidentally call any methods that use them until
-        // we have gotten that information from the ELF header.
-        wordSize: null,
-        endian: null));
-  }
+  /// Creates an [Elf] from [bytes].
+  ///
+  /// Returns null if the file does not start with the ELF magic number.
+  static Elf fromBuffer(Uint8List bytes) =>
+      Elf.fromReader(Reader.fromTypedData(bytes));
 
-  /// Checks that the file at [path] starts with the ELF magic number.
-  static bool startsWithMagicNumber(String path) {
-    final file = File(path).openSync();
-    var ret = true;
-    for (int code in ElfHeader._ELFMAG.codeUnits) {
-      if (file.readByteSync() != code) {
-        ret = false;
-        break;
+  /// Creates an [Elf] from the file at [path].
+  ///
+  /// Returns null if the file does not start with the ELF magic number.
+  static Elf fromFile(String path) => Elf.fromReader(Reader.fromFile(path));
+
+  /// The virtual address value of the dynamic symbol named [name].
+  ///
+  /// Returns -1 if there is no dynamic symbol with that name.
+  int namedAddress(String name) {
+    for (final SymbolTable dynsym in namedSections(".dynsym")) {
+      if (dynsym.containsKey(name)) {
+        return dynsym[name].value;
       }
     }
-    file.closeSync();
-    return ret;
+    return -1;
   }
 
-  /// Returns an iterable of [Section]s whose name matches [name].
-  Iterable<Section> namedSection(String name) {
-    final ret = <Section>[];
-    for (var entry in sections.keys) {
-      if (entry.name == name) {
-        ret.add(sections[entry]);
-      }
-    }
-    if (ret.isEmpty) {
-      throw FormatException("No section named $name found in ELF file");
-    }
-    return ret;
+  /// The [Section]s whose names match [name].
+  Iterable<Section> namedSections(String name) {
+    return _sections.keys
+        .where((entry) => entry.name == name)
+        .map((entry) => _sections[entry]);
   }
 
-  void _read() {
-    startingReader.reset();
-    header = ElfHeader.fromReader(startingReader.copy());
+  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);
-    programHeader = ProgramHeader.fromReader(
+    final programHeader = ProgramHeader.fromReader(
         reader.refocus(header.programHeaderOffset, header.programHeaderSize),
         entrySize: header.programHeaderEntrySize,
         entryCount: header.programHeaderCount);
-    sectionHeader = SectionHeader.fromReader(
+    final sectionHeader = SectionHeader.fromReader(
         reader.refocus(header.sectionHeaderOffset, header.sectionHeaderSize),
         entrySize: header.sectionHeaderEntrySize,
         entryCount: header.sectionHeaderCount,
         stringsIndex: header.sectionHeaderStringsIndex);
-    sections = <SectionHeaderEntry, Section>{};
+    final sections = <SectionHeaderEntry, Section>{};
+    final dynsyms = Map<SectionHeaderEntry, SymbolTable>();
+    final dynstrs = Map<SectionHeaderEntry, StringTable>();
     for (var i = 0; i < sectionHeader.length; i++) {
       final entry = sectionHeader[i];
       if (i == header.sectionHeaderStringsIndex) {
         sections[entry] = sectionHeader.nameTable;
-      } else {
-        sections[entry] = Section.fromEntryAndReader(
-            entry, reader.refocus(entry.offset, entry.size));
+        continue;
       }
+      final section = Section.fromEntryAndReader(
+          entry, reader.refocus(entry.offset, entry.size));
+      // Store the dynamic symbol tables and dynamic string tables so we can
+      // cache the symbol names afterwards.
+      switch (entry.name) {
+        case ".dynsym":
+          dynsyms[entry] = section;
+          break;
+        case ".dynstr":
+          dynstrs[entry] = section;
+          break;
+        default:
+          break;
+      }
+      sections[entry] = section;
     }
+    dynsyms.forEach((entry, dynsym) {
+      final linkEntry = sectionHeader[entry.link];
+      if (!dynstrs.containsKey(linkEntry)) {
+        throw FormatException(
+            "String table not found at section header entry ${entry.link}");
+      }
+      dynsym._cacheNames(dynstrs[linkEntry]);
+    });
+    return Elf._(header, programHeader, sectionHeader, sections);
   }
 
   @override
   String toString() {
     String accumulateSection(String acc, SectionHeaderEntry entry) =>
-        acc + "\nSection ${entry.name} is ${sections[entry]}";
-    return "Header information:\n\n${header}"
-        "\nProgram header information:\n\n${programHeader}"
-        "\nSection header information:\n\n${sectionHeader}"
-        "${sections.keys.fold("", accumulateSection)}";
+        acc + "\nSection ${entry.name} is ${_sections[entry]}";
+    return "Header information:\n\n${_header}"
+        "\nProgram header information:\n\n${_programHeader}"
+        "\nSection header information:\n\n${_sectionHeader}"
+        "${_sections.keys.fold("", accumulateSection)}";
   }
 }
diff --git a/pkg/native_stack_traces/lib/src/reader.dart b/pkg/native_stack_traces/lib/src/reader.dart
index e6d15d9..73a31e8 100644
--- a/pkg/native_stack_traces/lib/src/reader.dart
+++ b/pkg/native_stack_traces/lib/src/reader.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:io';
 import 'dart:typed_data';
 import 'dart:math';
 
@@ -16,10 +17,17 @@
 
   int _offset = 0;
 
-  Reader.fromTypedData(TypedData data, {this.wordSize, this.endian})
+  /// Unless provided, [wordSize] and [endian] are initialized to values that
+  /// ensure no reads are made that depend on their value (e.g., readBytes).
+  Reader.fromTypedData(TypedData data, {this.wordSize = -1, this.endian})
       : bdata =
             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);
+
   Reader copy() =>
       Reader.fromTypedData(bdata, wordSize: wordSize, endian: endian);
 
@@ -115,6 +123,12 @@
     return ret;
   }
 
+  Iterable<S> readRepeated<S>(S Function(Reader) callback) sync* {
+    while (!done) {
+      yield callback(this);
+    }
+  }
+
   String dumpCurrentReaderPosition({int maxSize = 0, int bytesPerLine = 16}) {
     var baseData = ByteData.view(bdata.buffer, 0, bdata.buffer.lengthInBytes);
     var startOffset = 0;
diff --git a/pkg/native_stack_traces/pubspec.yaml b/pkg/native_stack_traces/pubspec.yaml
index 118b873..aeccefc 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.2.0
+version: 0.2.2
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
diff --git a/pkg/nnbd_migration/bin/steamroll_ecosystem.dart b/pkg/nnbd_migration/bin/steamroll_ecosystem.dart
new file mode 100644
index 0000000..cc2124f
--- /dev/null
+++ b/pkg/nnbd_migration/bin/steamroll_ecosystem.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All 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';
+
+/// This binary can generate and update an integrated workspace for upgrading
+/// individual packages and their dependencies simultaneously.
+
+import 'package:nnbd_migration/src/fantasyland/fantasy_workspace.dart';
+import 'package:path/path.dart' as path;
+import 'package:args/args.dart';
+
+final parser = ArgParser()
+  ..addMultiOption('extra-packages', abbr: 'e', splitCommas: true)
+  ..addOption('package-name', abbr: 'p')
+  ..addFlag('analysis-options-hack', defaultsTo: true, negatable: true)
+  ..addFlag('strip-sdk-constraint-hack', defaultsTo: true, negatable: true)
+  ..addFlag('force-migrate-deps', defaultsTo: true, negatable: true)
+  ..addFlag('force-migrate-package', defaultsTo: false, negatable: true)
+  ..addFlag('force-migrate-extras', defaultsTo: true, negatable: true)
+  ..addFlag('help', abbr: 'h');
+
+Future<void> main(List<String> args) async {
+  ArgResults results = parser.parse(args);
+
+  if (results['help'] as bool) {
+    _showHelp(null, useStdError: false);
+    exit(0);
+  }
+
+  if (results.rest.length != 1) {
+    _showHelp('error: only one argument allowed for workspace directory');
+    exit(1);
+  }
+
+  List<String> extraPackages = results['extra-packages'] as List<String>;
+  String packageName = results['package-name'] as String;
+
+  if (packageName == null) {
+    _showHelp('error: --package_name required');
+    exit(1);
+  }
+  assert(packageName != null);
+  assert(extraPackages != null);
+
+  FantasyWorkspace workspace = await buildFantasyLand(
+      packageName, extraPackages, path.canonicalize(results.rest.first));
+  workspace.makeAllSymlinks();
+
+  if (results['analysis-options-hack'] as bool) {
+    stderr.writeln('warning: analysis options hack not implemented');
+  }
+
+  if (results['strip-sdk-constraint-hack'] as bool) {
+    stderr.writeln('warning: sdk constraint hack not implemented');
+  }
+
+  if (results['force-migrate-deps'] as bool ||
+      results['force-migrate-package'] as bool ||
+      results['force-migrate-extras'] as bool) {
+    stderr.writeln('warning: auto-migration not implemented');
+  }
+}
+
+// TODO(jcollins-g): add symbolic link support to analyzer filesystem.
+extension _Symlinks on FantasyWorkspace {
+  void makeAllSymlinks() {
+    for (var package in subPackages.values) {
+      Link l = Link(path.join(workspaceRootPath, package.name));
+      if (!l.existsSync()) {
+        l.createSync(
+            path.relative(package.packageRoot.path, from: workspaceRootPath));
+      }
+    }
+  }
+}
+
+void _showHelp(String message, {bool useStdError = true}) {
+  var writer = useStdError ? stderr : stdout;
+
+  writer.writeln(message ?? '');
+  writer.writeln(
+      'Usage: dart ${Platform.script.toFilePath()} [options] workspace_dir');
+  writer.writeln();
+  writer.writeln(parser.usage);
+}
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 133fa67..734e782 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -266,7 +266,8 @@
 
   @override
   DecoratedType visitAsExpression(AsExpression node) {
-    if (BestPracticesVerifier.isUnnecessaryCast(node, _typeSystem)) {
+    if (BestPracticesVerifier.isUnnecessaryCast(
+        node, _typeSystem as TypeSystemImpl)) {
       _variables.recordUnnecessaryCast(source, node);
     }
     node.type.accept(this);
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 7fb6997..2e0a9d5 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -1116,6 +1116,8 @@
     if (node is FunctionExpression && node.body is ExpressionFunctionBody) {
       // To avoid ambiguities when adding `as Type` after a function expression,
       // assume assignment precedence.
+      // TODO(paulberry): this is a hack - see
+      // https://github.com/dart-lang/sdk/issues/40536
       precedence = Precedence.assignment;
     } else if (node is Expression) {
       precedence = node.precedence;
@@ -1306,10 +1308,17 @@
 
   static bool _checkParenLogic(EditPlan innerPlan, bool parensNeeded) {
     if (innerPlan is _SimpleEditPlan && innerPlan._innerChanges == null) {
-      assert(
-          !parensNeeded,
-          "Code prior to fixes didn't need parens here, "
-          "shouldn't need parens now.");
+      if (innerPlan.sourceNode is FunctionExpression) {
+        // Skip parentheses check for function expressions; it produces false
+        // failures when examining an expression like `x ?? (y) => z`, due to
+        // https://github.com/dart-lang/sdk/issues/40536.
+        // TODO(paulberry): fix this.
+      } else {
+        assert(
+            !parensNeeded,
+            "Code prior to fixes didn't need parens here, "
+            "shouldn't need parens now.");
+      }
     }
     return true;
   }
diff --git a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo.dart b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo.dart
index 0126de7..4b6f5b0 100644
--- a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo.dart
+++ b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo.dart
@@ -16,8 +16,8 @@
       'build_version', '$githubHost:kevmoo/build_version.git'),
   'csv': FantasyRepoSettings('csv', '$githubHost:close2/csv.git'),
   'git': FantasyRepoSettings('git', '$githubHost:kevmoo/git.git'),
-  'node_interop': FantasyRepoSettings(
-      'node_interop', '$githubHost:pulyaevskiy/node-interop.git'),
+  'node-interop': FantasyRepoSettings(
+      'node-interop', '$githubHost:pulyaevskiy/node-interop.git'),
   'node_preamble': FantasyRepoSettings(
       'package_config', '$githubHost:mbullington/node_preamble.dart.git'),
   'package_config': FantasyRepoSettings('package_config',
diff --git a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo_impl.dart b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo_impl.dart
index 7f3b1c2..ab34724 100644
--- a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo_impl.dart
+++ b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_repo_impl.dart
@@ -73,9 +73,7 @@
   /// initializing.
   Future<void> _clone(SubprocessLauncher launcher) async {
     assert(_isInitialized == false);
-    if (!repoRoot.parent.exists) {
-      await repoRoot.parent.create();
-    }
+    repoRoot.parent.create();
     await launcher.runStreamed('git', ['init', repoRoot.path]);
     await launcher.runStreamed(
         'git',
@@ -111,34 +109,17 @@
       '!**/pubspec.lock\n',
       '!**/.dart_tool/package_config.json\n'
     ].join());
-    try {
-      await _update(launcher);
-    } catch (e) {
-      if (e is FantasyRepoUpdateException) {
-        throw FantasyRepoCloneException(
-            'Unable to initialize clone for: $repoSettings');
-      }
-      // Other kinds of exceptions are not expected, so rethrow.
-      rethrow;
-    }
+    await launcher.runStreamed(
+        'git', ['pull', '--depth=1', '--rebase', 'originHTTP'],
+        workingDirectory: repoRoot.path, retries: 5);
   }
 
   Future<void> _update(SubprocessLauncher launcher) async {
     assert(_isInitialized == false);
     try {
-      List<String> args;
-      if (repoSettings.branch == 'master') {
-        args = [
-          'pull',
-          '--depth=1',
-          '--rebase',
-          'originHTTP',
-          repoSettings.revision
-        ];
-      } else {
-        args = ['pull', '--rebase', 'originHTTP', repoSettings.revision];
-      }
-      await launcher.runStreamed('git', args, workingDirectory: repoRoot.path);
+      await launcher.runStreamed(
+          'git', ['pull', '--rebase', 'originHTTP', repoSettings.revision],
+          workingDirectory: repoRoot.path, retries: 5);
     } catch (e) {
       if (e is ProcessException) {
         throw FantasyRepoUpdateException(
diff --git a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_sub_package.dart b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_sub_package.dart
index 173d24f..e9afbfa 100644
--- a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_sub_package.dart
+++ b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_sub_package.dart
@@ -123,6 +123,9 @@
       subDir: path.join('pkg', 'vm_service')),
   'quiver': FantasySubPackageSettings(
       'quiver', FantasyRepoSettings.fromName('quiver-dart')),
+  'webkit_inspection_protocol': FantasySubPackageSettings(
+      'webkit_inspection_protocol',
+      FantasyRepoSettings.fromName('webkit_inspection_protocol.dart')),
 };
 
 /// Data class containing settings for a package within a [FantasyWorkspaceImpl].
diff --git a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace.dart b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace.dart
index cda38ec..4c83b15 100644
--- a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace.dart
+++ b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace.dart
@@ -2,9 +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.
 
-// TODO(jcollins-g): finish port away from io
-import 'dart:io' show Directory;
-
 import 'package:nnbd_migration/src/fantasyland/fantasy_sub_package.dart';
 import 'package:nnbd_migration/src/fantasyland/fantasy_workspace_impl.dart';
 
@@ -12,10 +9,16 @@
 
 /// Represent a single [FantasyWorkspace].
 abstract class FantasyWorkspace {
-  Directory get workspaceRoot;
+  String get workspaceRootPath;
 
   /// Fully initialized subpackages.
-  Map<String, FantasySubPackage> subPackages;
+  Map<FantasySubPackageSettings, FantasySubPackage> subPackages;
+
+  /// Add a package to the workspace, given [packageSettings].
+  ///
+  /// Completes when the repository and subPackage is added.
+  Future<FantasySubPackage> addPackageToWorkspace(
+      FantasySubPackageSettings packageSettings);
 }
 
 /// Build a "fantasyland"-style repository structure suitable for applying
diff --git a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace_impl.dart b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace_impl.dart
index 837eb07..d3a7cff 100644
--- a/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace_impl.dart
+++ b/pkg/nnbd_migration/lib/src/fantasyland/fantasy_workspace_impl.dart
@@ -2,28 +2,36 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// TODO(jcollins-g): finish port away from io
-import 'dart:io' show Directory;
-
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:nnbd_migration/src/fantasyland/fantasy_repo.dart';
+import 'package:nnbd_migration/src/fantasyland/fantasy_repo_impl.dart';
 import 'package:nnbd_migration/src/fantasyland/fantasy_sub_package.dart';
 import 'package:nnbd_migration/src/fantasyland/fantasy_workspace.dart';
+import 'package:nnbd_migration/src/utilities/multi_future_tracker.dart';
 import 'package:nnbd_migration/src/utilities/subprocess_launcher.dart';
-import 'package:path/path.dart' as path;
+import 'package:package_config/packages_file.dart' as packages_file;
+
+class FantasyWorkspaceError extends Error {
+  final String message;
+  FantasyWorkspaceError(this.message);
+
+  @override
+  String toString() => message;
+}
 
 // TODO(jcollins-g): consider refactor that makes resourceProvider required.
 class FantasyWorkspaceDependencies {
-  final Future<FantasyRepo> Function(FantasyRepoSettings, String)
-      buildGitRepoFrom;
+  final Future<FantasyRepo> Function(FantasyRepoSettings, String,
+      {FantasyRepoDependencies fantasyRepoDependencies}) buildGitRepoFrom;
   final ResourceProvider resourceProvider;
   final SubprocessLauncher launcher;
 
   FantasyWorkspaceDependencies(
       {ResourceProvider resourceProvider,
       SubprocessLauncher launcher,
-      Future<FantasyRepo> Function(FantasyRepoSettings, String)
+      Future<FantasyRepo> Function(FantasyRepoSettings, String,
+              {FantasyRepoDependencies fantasyRepoDependencies})
           buildGitRepoFrom})
       : resourceProvider =
             resourceProvider ?? PhysicalResourceProvider.INSTANCE,
@@ -31,27 +39,39 @@
         buildGitRepoFrom = buildGitRepoFrom ?? FantasyRepo.buildGitRepoFrom;
 }
 
-abstract class FantasyWorkspaceImpl extends FantasyWorkspace {
-  @override
-  final Directory workspaceRoot;
+abstract class FantasyWorkspaceBase extends FantasyWorkspace {
+  final String workspaceRootPath;
 
-  // TODO(jcollins-g): inject FantasyWorkspaceDependencies here.
-  FantasyWorkspaceImpl._(this.workspaceRoot);
+  final FantasyWorkspaceDependencies _external;
+
+  FantasyWorkspaceBase._(this.workspaceRootPath,
+      {FantasyWorkspaceDependencies workspaceDependencies})
+      : _external = workspaceDependencies ?? FantasyWorkspaceDependencies() {
+    if (!_external.resourceProvider.pathContext.isAbsolute(workspaceRootPath)) {
+      throw FantasyWorkspaceError('workspaceRootPath must be absolute');
+    }
+  }
+
+  MultiFutureTracker _packageConfigLock = MultiFutureTracker(1);
 
   /// Repositories on which [addRepoToWorkspace] has been called.
   Map<String, Future<FantasyRepo>> _repos = {};
 
-  /// Sub-packages on which [addPackageNameToWorkspace] has been called.
-  Map<String, Future<List<String>>> _packageDependencies = {};
-
   /// Fully initialized subpackages.
   ///
   /// This is complete once all [addPackageNameToWorkspace] futures are complete.
-  /// futures are complete.
-  Map<String, FantasySubPackage> subPackages = {};
+  /// futures are complete.  Packages may appear here early.
+  Map<FantasySubPackageSettings, FantasySubPackage> subPackages = {};
 
-  /// Implementation-dependent part of addPackageToWorkspace.
-  ///
+  File _packagesFile;
+  File get packagesFile => _packagesFile ??= _external.resourceProvider.getFile(
+      _external.resourceProvider.pathContext
+          .join(workspaceRootPath, '.packages'));
+
+  // TODO(jcollins-g): use package_config when pub package is updated, or
+  // implement writing for the analyzer version ourselves.
+  File get packageConfigJson => throw UnimplementedError();
+
   /// The returned future should complete only when this package's repository
   /// is:
   ///
@@ -61,54 +81,83 @@
   ///  symlinked into the workspace
   ///  has a [FantasySubPackage] assigned to its key in [subPackages].
   ///
-  /// Returns a list of packageNames that needed to be added as dependencies.
+  /// Returns a list of [FantasySubPackageSettings] that needed to be added as
+  /// dependencies.
   ///
   /// Which dependencies are automatically added is implementation dependent.
-  Future<List<String>> addPackageNameToWorkspaceInternal(String packageName);
+  Future<void> addPackageNameToWorkspace(String packageName);
 
-  Future<void> addPackageNameToWorkspace(String packageName) async {
-    if (_packageDependencies.containsKey(packageName)) return;
-    _packageDependencies[packageName] =
-        addPackageNameToWorkspaceInternal(packageName);
-    return Future.wait([
-      for (var n in await _packageDependencies[packageName])
-        addPackageNameToWorkspace(n)
-    ]);
+  Future<FantasySubPackage> addPackageToWorkspace(
+      FantasySubPackageSettings packageSettings) async {
+    FantasyRepo containingRepo =
+        await addRepoToWorkspace(packageSettings.repoSettings);
+    FantasySubPackage fantasySubPackage =
+        FantasySubPackage(packageSettings, containingRepo);
+    // TODO(jcollins-g): throw if double add
+    subPackages[packageSettings] = fantasySubPackage;
+    return fantasySubPackage;
   }
 
   static const _repoSubDir = '_repo';
 
-  /// Asynchronously add one repository to the workspace.
+  /// Add one repository to the workspace.
   ///
-  /// Completes when the repository is synced and cloned.
-  /// Completes immediately if the [name] is already added.
+  /// The returned [Future] completes when the repository is synced and cloned.
   Future<FantasyRepo> addRepoToWorkspace(FantasyRepoSettings repoSettings) {
     if (_repos.containsKey(repoSettings.name)) return _repos[repoSettings.name];
-    Directory repoRoot = Directory(path.canonicalize(
-        path.join(workspaceRoot.path, _repoSubDir, repoSettings.name)));
-    _repos[repoSettings.name] =
-        FantasyRepo.buildGitRepoFrom(repoSettings, repoRoot.path);
+    Folder repoRoot = _external.resourceProvider.getFolder(_external
+        .resourceProvider.pathContext
+        .canonicalize(_external.resourceProvider.pathContext
+            .join(workspaceRootPath, _repoSubDir, repoSettings.name)));
+    _repos[repoSettings.name] = _external.buildGitRepoFrom(
+        repoSettings, repoRoot.path,
+        fantasyRepoDependencies:
+            FantasyRepoDependencies.fromWorkspaceDependencies(_external));
     return _repos[repoSettings.name];
   }
+
+  Future<void> rewritePackageConfigWith(FantasySubPackage subPackage) async {
+    return _packageConfigLock.runFutureFromClosure(
+        () async => _rewritePackageConfigWith(subPackage));
+  }
+
+  // Only one [_rewritePackageConfigWith] should be running at a time
+  // per workspace.
+  Future<void> _rewritePackageConfigWith(FantasySubPackage subPackage) async {
+    Map<String, Uri> uriMap = {};
+    if (packagesFile.exists) {
+      var uri = packagesFile.toUri();
+      var content = packagesFile.readAsBytesSync();
+      uriMap = packages_file.parse(content, uri);
+    }
+    uriMap[subPackage.name] =
+        subPackage.packageRoot.getChildAssumingFolder('lib').toUri();
+    StringBuffer buffer = StringBuffer();
+    packages_file.write(buffer, uriMap);
+    // TODO(jcollins-g): Consider accumulating rewrites rather than doing
+    // this once per package.
+    // TODO(jcollins-g): support package_config.json.
+    return packagesFile.writeAsStringSync(buffer.toString());
+  }
 }
 
-/// Represents a [FantasyWorkspaceImpl] that only fetches dev_dependencies
+/// Represents a [FantasyWorkspaceBase] that only fetches dev_dependencies
 /// for the top level package.
-class FantasyWorkspaceTopLevelDevDepsImpl extends FantasyWorkspaceImpl {
+class FantasyWorkspaceTopLevelDevDepsImpl extends FantasyWorkspaceBase {
   final String topLevelPackage;
 
   FantasyWorkspaceTopLevelDevDepsImpl._(
-      this.topLevelPackage, Directory workspaceRoot)
-      : super._(workspaceRoot);
+      this.topLevelPackage, String workspaceRootPath,
+      {FantasyWorkspaceDependencies workspaceDependencies})
+      : super._(workspaceRootPath,
+            workspaceDependencies: workspaceDependencies);
 
   static Future<FantasyWorkspace> buildFor(String topLevelPackage,
-      List<String> extraPackageNames, String workspaceRoot) async {
-    // TODO(jcollins-g): finish port
-    Directory workspaceRootDir = Directory(workspaceRoot);
-    await workspaceRootDir.create(recursive: true);
-
+      List<String> extraPackageNames, String workspaceRootPath,
+      {FantasyWorkspaceDependencies workspaceDependencies}) async {
     var workspace = FantasyWorkspaceTopLevelDevDepsImpl._(
-        topLevelPackage, workspaceRootDir);
+        topLevelPackage, workspaceRootPath,
+        workspaceDependencies: workspaceDependencies);
     await Future.wait([
       for (var n in [topLevelPackage, ...extraPackageNames])
         workspace.addPackageNameToWorkspace(n)
@@ -116,21 +165,43 @@
     return workspace;
   }
 
-  Future<List<String>> addPackageNameToWorkspaceInternal(
+  Future<FantasySubPackage> addPackageNameToWorkspace(
       String packageName) async {
     FantasySubPackageSettings packageSettings =
         FantasySubPackageSettings.fromName(packageName);
-    FantasyRepo containingRepo =
-        await addRepoToWorkspace(packageSettings.repoSettings);
-    FantasySubPackage fantasySubPackage =
-        FantasySubPackage(packageSettings, containingRepo);
-    subPackages[fantasySubPackage.name] = fantasySubPackage;
+    return await addPackageToWorkspace(packageSettings);
+  }
 
-    // TODO(jcollins-g): Add to .packages / package_config.json
+  @override
+  Future<FantasySubPackage> addPackageToWorkspace(
+      FantasySubPackageSettings packageSettings,
+      {Set<FantasySubPackageSettings> seenPackages}) async {
+    seenPackages ??= {};
+    if (seenPackages.contains(packageSettings)) return null;
+    seenPackages.add(packageSettings);
+    await _addPackageToWorkspace(packageSettings, seenPackages);
+  }
+
+  Future<FantasySubPackage> _addPackageToWorkspace(
+      FantasySubPackageSettings packageSettings,
+      Set<FantasySubPackageSettings> seenPackages) async {
+    FantasySubPackage fantasySubPackage =
+        await super.addPackageToWorkspace(packageSettings);
+    String packageName = packageSettings.name;
+
+    await rewritePackageConfigWith(fantasySubPackage);
+    List<FantasySubPackageSettings> dependencies = [];
+
     if (packageName == topLevelPackage) {
-      throw UnimplementedError();
-      // TODO(jcollins-g): implement some dependency calculations inside FantasySubPackage.
+      dependencies = await fantasySubPackage.getPackageAllDependencies();
+    } else {
+      dependencies = await fantasySubPackage.getPackageDependencies();
     }
-    return [];
+
+    await Future.wait([
+      for (var subPackageSettings in dependencies)
+        addPackageToWorkspace(subPackageSettings, seenPackages: seenPackages)
+    ]);
+    return fantasySubPackage;
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 857264a..64e465f 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -263,23 +263,37 @@
 /// Implementation of [NodeChange] specialized for operating on [Expression]
 /// nodes.
 class NodeChangeForExpression<N extends Expression> extends NodeChange<N> {
-  /// Indicates whether the expression should be null checked.
-  bool addNullCheck = false;
+  bool _addsNullCheck = false;
 
-  /// If [addNullCheck] is `true`, the information that should be contained in
-  /// the edit that adds the null check.
-  AtomicEditInfo addNullCheckInfo;
+  AtomicEditInfo _addNullCheckInfo;
 
-  /// Indicates whether the expression should be cast to a different type using
-  /// `as`.
-  String introduceAsType;
+  String _introducesAsType;
 
-  /// If [introduceAsType] is not `null`, the information that should be
-  /// contained in the edit that introduces the cast.
-  AtomicEditInfo introduceAsInfo;
+  AtomicEditInfo _introduceAsInfo;
 
   NodeChangeForExpression() : super._();
 
+  /// Indicates whether [addNullCheck] has been called.
+  bool get addsNullCheck => _addsNullCheck;
+
+  /// Causes a null check to be added to this expression, with the given [info].
+  void addNullCheck(AtomicEditInfo info) {
+    assert(!_addsNullCheck);
+    assert(_introducesAsType == null);
+    _addsNullCheck = true;
+    _addNullCheckInfo = info;
+  }
+
+  /// Causes a cast to the given [type] to be added to this expression, with
+  /// the given [info].
+  void introduceAs(String type, AtomicEditInfo info) {
+    assert(!_addsNullCheck);
+    assert(_introducesAsType == null);
+    assert(type != null);
+    _introducesAsType = type;
+    _introduceAsInfo = info;
+  }
+
   @override
   EditPlan _apply(N node, FixAggregator aggregator) {
     var innerPlan = aggregator.innerPlanForNode(node);
@@ -291,14 +305,13 @@
   /// Otherwise returns [innerPlan] unchanged.
   NodeProducingEditPlan _applyExpression(
       FixAggregator aggregator, NodeProducingEditPlan innerPlan) {
-    assert((introduceAsType == null) == (introduceAsInfo == null));
-    if (addNullCheck) {
-      assert(introduceAsInfo == null);
+    if (_addsNullCheck) {
       return aggregator.planner
-          .addUnaryPostfix(innerPlan, TokenType.BANG, info: addNullCheckInfo);
-    } else if (introduceAsInfo != null) {
-      return aggregator.planner
-          .addBinaryPostfix(innerPlan, TokenType.AS, introduceAsType);
+          .addUnaryPostfix(innerPlan, TokenType.BANG, info: _addNullCheckInfo);
+    } else if (_introducesAsType != null) {
+      return aggregator.planner.addBinaryPostfix(
+          innerPlan, TokenType.AS, _introducesAsType,
+          info: _introduceAsInfo);
     } else {
       return innerPlan;
     }
@@ -397,6 +410,28 @@
   }
 }
 
+/// Implementation of [NodeChange] specialized for operating on
+/// [SimpleFormalParameter] nodes.
+class NodeChangeForSimpleFormalParameter
+    extends NodeChange<SimpleFormalParameter> {
+  /// If not `null`, an explicit type annotation that should be added to the
+  /// parameter.
+  DartType addExplicitType;
+
+  NodeChangeForSimpleFormalParameter() : super._();
+
+  @override
+  EditPlan _apply(SimpleFormalParameter node, FixAggregator aggregator) {
+    var innerPlan = aggregator.innerPlanForNode(node);
+    if (addExplicitType == null) return innerPlan;
+    return aggregator.planner.surround(innerPlan, prefix: [
+      AtomicEdit.insert(
+          addExplicitType.getDisplayString(withNullability: true)),
+      AtomicEdit.insert(' ')
+    ]);
+  }
+}
+
 /// Implementation of [NodeChange] specialized for operating on [TypeAnnotation]
 /// nodes.
 class NodeChangeForTypeAnnotation extends NodeChange<TypeAnnotation> {
@@ -492,6 +527,10 @@
       NodeChangeForPropertyAccess();
 
   @override
+  NodeChange visitSimpleFormalParameter(SimpleFormalParameter node) =>
+      NodeChangeForSimpleFormalParameter();
+
+  @override
   NodeChange visitTypeName(TypeName node) => NodeChangeForTypeAnnotation();
 
   @override
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 8c603ae..2df41bc 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
@@ -92,6 +93,10 @@
 
   final MigrationResolutionHooksImpl migrationResolutionHooks;
 
+  /// Parameter elements for which an explicit type should be added, and what
+  /// that type should be.
+  final Map<ParameterElement, DartType> _addedParameterTypes = {};
+
   factory FixBuilder(
       Source source,
       DecoratedClassHierarchy decoratedClassHierarchy,
@@ -153,10 +158,12 @@
   /// makes note of changes that need to be made.
   void visitAll() {
     try {
-      ElementTypeProvider.current = migrationResolutionHooks;
-      unit.accept(_FixBuilderPreVisitor(this));
-      unit.accept(_resolver);
-      unit.accept(_FixBuilderPostVisitor(this));
+      NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+        ElementTypeProvider.current = migrationResolutionHooks;
+        unit.accept(_FixBuilderPreVisitor(this));
+        unit.accept(_resolver);
+        unit.accept(_FixBuilderPostVisitor(this));
+      });
     } catch (exception, stackTrace) {
       if (listener != null) {
         listener.reportException(source, unit, exception, stackTrace);
@@ -399,6 +406,18 @@
       });
 
   @override
+  DartType modifyInferredParameterType(
+      ParameterElement parameter, DartType type) {
+    var postMigrationType = parameter.type;
+    if (postMigrationType != type) {
+      // TODO(paulberry): make sure we test all kinds of parameters
+      _fixBuilder._addedParameterTypes[parameter] = postMigrationType;
+      return postMigrationType;
+    }
+    return type;
+  }
+
+  @override
   void setFlowAnalysis(
       FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>
           flowAnalysis) {
@@ -413,8 +432,7 @@
             NullabilityFixDescription.checkExpression, checks.edges)
         : null;
     (_fixBuilder._getChange(node) as NodeChangeForExpression)
-      ..introduceAsType = contextType.getDisplayString(withNullability: true)
-      ..introduceAsInfo = info;
+        .introduceAs(contextType.getDisplayString(withNullability: true), info);
     _flowAnalysis.asExpression_end(node, contextType);
     return contextType;
   }
@@ -427,8 +445,7 @@
             NullabilityFixDescription.checkExpression, checks.edges)
         : null;
     (_fixBuilder._getChange(node) as NodeChangeForExpression)
-      ..addNullCheck = true
-      ..addNullCheckInfo = info;
+        .addNullCheck(info);
     _flowAnalysis.nonNullAssert_end(node);
     return _fixBuilder._typeSystem.promoteToNonNull(type as TypeImpl);
   }
@@ -562,6 +579,17 @@
   }
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    if (node.type == null) {
+      var typeToAdd = _fixBuilder._addedParameterTypes[node.declaredElement];
+      if (typeToAdd != null) {
+        (_fixBuilder._getChange(node) as NodeChangeForSimpleFormalParameter)
+            .addExplicitType = typeToAdd;
+      }
+    }
+  }
+
+  @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     if (node.type == null) {
       // TODO(paulberry): for fields, handle inference via override as well.
diff --git a/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart b/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
index 950b63b..9f3a13d 100644
--- a/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
@@ -7,6 +7,26 @@
 /// This library helps run parallel thread-like closures asynchronously.
 /// Borrowed from dartdoc:src/io_utils.dart.
 
+Future<T> retryClosure<T>(Future<T> Function() closure,
+    {Duration baseInterval = const Duration(milliseconds: 200),
+    double factor = 2,
+    int retries = 5}) async {
+  Future<T> handleError(Object _) async {
+    return await Future.delayed(
+        baseInterval,
+        () => retryClosure(closure,
+            baseInterval: baseInterval * factor,
+            factor: factor,
+            retries: retries - 1));
+  }
+
+  if (retries > 0) {
+    return await Future.sync(closure).catchError(handleError);
+  } else {
+    return await Future.sync(closure);
+  }
+}
+
 // TODO(jcollins-g): like SubprocessLauncher, merge with io_utils in dartdoc
 // before cut-and-paste gets out of hand.
 class MultiFutureTracker {
diff --git a/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart b/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
index 151b1d4..8bd599a 100644
--- a/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
@@ -66,13 +66,16 @@
       {String workingDirectory,
       Map<String, String> environment,
       bool includeParentEnvironment = true,
-      void Function(String) perLine}) async {
+      void Function(String) perLine,
+      int retries = 0}) async {
     return maxParallel.runFutureFromClosure(() async {
-      return runStreamedImmediate(executable, arguments,
-          workingDirectory: workingDirectory,
-          environment: environment,
-          includeParentEnvironment: includeParentEnvironment,
-          perLine: perLine);
+      return retryClosure(
+          () async => await runStreamedImmediate(executable, arguments,
+              workingDirectory: workingDirectory,
+              environment: environment,
+              includeParentEnvironment: includeParentEnvironment,
+              perLine: perLine),
+          retries: retries);
     });
   }
 
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index c2386bb..8e857de 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -94,6 +94,101 @@
 
 /// Mixin containing test cases for the provisional API.
 mixin _ProvisionalApiTestCases on _ProvisionalApiTestBase {
+  Future<void> test_add_explicit_parameter_type() async {
+    var content = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => value + 1);
+}
+''';
+    // Under the new NNBD rules, `value` gets an inferred type of `Object?`.  We
+    // need to change this to `dynamic` to avoid an "undefined operator +"
+    // error.
+    var expected = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((dynamic value) => value + 1);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40476')
+  Future<void> test_add_explicit_parameter_type_interpolation() async {
+    var content = r'''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => '$value';
+}
+''';
+    // Under the new NNBD rules, `value` gets an inferred type of `Object?`,
+    // whereas it previously had a type of `dynamic`.  But we don't need to fix
+    // it because `Object?` supports `toString`.
+    var expected = r'''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => '$value';
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40476')
+  Future<void> test_add_explicit_parameter_type_object_method() async {
+    var content = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => value.toString());
+}
+''';
+    // Under the new NNBD rules, `value` gets an inferred type of `Object?`,
+    // whereas it previously had a type of `dynamic`.  But we don't need to fix
+    // it because `Object?` supports `toString`.
+    var expected = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => value.toString());
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40476')
+  Future<void> test_add_explicit_parameter_type_unused() async {
+    var content = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => 0);
+}
+''';
+    // Under the new NNBD rules, `value` gets an inferred type of `Object?`,
+    // whereas it previously had a type of `dynamic`.  But we don't need to fix
+    // it because it's unused.
+    var expected = '''
+abstract class C {
+  void m<T>(T Function(T) callback);
+}
+void test(C c) {
+  c.m((value) => 0);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_add_required() async {
     var content = '''
 int f({String s}) => s.length;
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index d88c4f6..3d78101 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -1361,6 +1361,10 @@
 ''');
   }
 
+  Future<void> test_precedence_functionExpression_ifNotNull() async {
+    await checkPrecedence('f(b, c) => ((a) => b) ?? c;');
+  }
+
   Future<void> test_precedence_functionExpressionInvocation() async {
     await checkPrecedence('''
 f(g) => g[0](1);
@@ -1368,6 +1372,11 @@
 ''');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40536')
+  Future<void> test_precedence_ifNotNull_functionExpression() async {
+    await checkPrecedence('f(a, c) => a ?? (b) => c;');
+  }
+
   Future<void> test_precedence_is() async {
     await checkPrecedence('''
 f(a) => (a as num) is int;
diff --git a/pkg/nnbd_migration/test/fantasyland/fantasy_workspace_test.dart b/pkg/nnbd_migration/test/fantasyland/fantasy_workspace_test.dart
index f0d3701..9765b03 100644
--- a/pkg/nnbd_migration/test/fantasyland/fantasy_workspace_test.dart
+++ b/pkg/nnbd_migration/test/fantasyland/fantasy_workspace_test.dart
@@ -2,6 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
+import 'package:mockito/mockito.dart';
+import 'package:nnbd_migration/src/fantasyland/fantasy_workspace.dart';
+import 'package:nnbd_migration/src/fantasyland/fantasy_workspace_impl.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'src/filesystem_test_base.dart';
@@ -9,8 +15,46 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FantasyWorkspaceTest);
+    defineReflectiveTests(FantasyWorkspaceIntegrationTest);
   });
 }
 
 @reflectiveTest
-class FantasyWorkspaceTest extends FilesystemTestBase {}
+class FantasyWorkspaceTest extends FilesystemTestBase {
+  setUp() async {
+    super.setUp();
+  }
+}
+
+@reflectiveTest
+class FantasyWorkspaceIntegrationTest extends FilesystemTestBase {
+  FantasyWorkspace workspace;
+
+  setUp() {
+    super.setUp();
+  }
+
+  /// Verify connection between workspace and buildGitRepoFrom.
+  test_fantasyWorkspaceDevDepsImplIntegration() async {
+    workspace = await FantasyWorkspaceTopLevelDevDepsImpl.buildFor(
+        'test_package',
+        ['extra_package_1', 'extra_package_2'],
+        convertPath('/fantasyland'),
+        workspaceDependencies: workspaceDependencies);
+    expect(getFolder('/fantasyland').exists, isTrue);
+    for (var n in ['test_package', 'extra_package_1', 'extra_package_2']) {
+      String repoPath = convertPath('/fantasyland/_repo/$n');
+      verify(mockLauncher.runStreamed(
+          'git',
+          [
+            'remote',
+            'add',
+            'origin',
+            '-t',
+            'master',
+            'git@github.com:dart-lang/$n.git'
+          ],
+          workingDirectory: repoPath));
+    }
+  }
+}
diff --git a/pkg/nnbd_migration/test/fix_aggregator_test.dart b/pkg/nnbd_migration/test/fix_aggregator_test.dart
index 19e5403..e516346 100644
--- a/pkg/nnbd_migration/test/fix_aggregator_test.dart
+++ b/pkg/nnbd_migration/test/fix_aggregator_test.dart
@@ -36,9 +36,10 @@
     var aRef = findNode.simple('a +');
     var bRef = findNode.simple('b;');
     var previewInfo = run({
-      aRef: NodeChangeForExpression()..addNullCheck = true,
-      bRef: NodeChangeForExpression()..addNullCheck = true,
-      findNode.binary('a + b'): NodeChangeForExpression()..addNullCheck = true
+      aRef: NodeChangeForExpression()..addNullCheck(_MockInfo()),
+      bRef: NodeChangeForExpression()..addNullCheck(_MockInfo()),
+      findNode.binary('a + b'): NodeChangeForExpression()
+        ..addNullCheck(_MockInfo())
     });
     expect(previewInfo.applyTo(code), 'f(a, b) => (a! + b!)!;');
   }
@@ -53,7 +54,7 @@
       findNode.statement('if'): NodeChangeForIfStatement()
         ..conditionValue = true,
       findNode.simple('j.isEven'): NodeChangeForExpression()
-        ..addNullCheck = true
+        ..addNullCheck(_MockInfo())
     });
     expect(previewInfo.applyTo(code), '''
 f(int i, int/*?*/ j) {
@@ -74,7 +75,7 @@
       findNode.statement('if'): NodeChangeForIfStatement()
         ..conditionValue = true,
       findNode.simple('j.isEven'): NodeChangeForExpression()
-        ..addNullCheck = true
+        ..addNullCheck(_MockInfo())
     });
     expect(previewInfo.applyTo(code), '''
 f(int i, int/*?*/ j) {
@@ -327,11 +328,8 @@
     // leave them.
     await analyze('f(a, c) => a..b = (throw c..d);');
     var cd = findNode.cascade('c..d');
-    var previewInfo = run({
-      cd: NodeChangeForExpression()
-        ..introduceAsType = 'int'
-        ..introduceAsInfo = _MockInfo()
-    });
+    var previewInfo =
+        run({cd: NodeChangeForExpression()..introduceAs('int', _MockInfo())});
     expect(
         previewInfo.applyTo(code), 'f(a, c) => a..b = (throw (c..d) as int);');
   }
@@ -339,22 +337,16 @@
   Future<void> test_introduceAs_no_parens() async {
     await analyze('f(a, b) => a | b;');
     var expr = findNode.binary('a | b');
-    var previewInfo = run({
-      expr: NodeChangeForExpression()
-        ..introduceAsType = 'int'
-        ..introduceAsInfo = _MockInfo()
-    });
+    var previewInfo =
+        run({expr: NodeChangeForExpression()..introduceAs('int', _MockInfo())});
     expect(previewInfo.applyTo(code), 'f(a, b) => a | b as int;');
   }
 
   Future<void> test_introduceAs_parens() async {
     await analyze('f(a, b) => a < b;');
     var expr = findNode.binary('a < b');
-    var previewInfo = run({
-      expr: NodeChangeForExpression()
-        ..introduceAsType = 'bool'
-        ..introduceAsInfo = _MockInfo()
-    });
+    var previewInfo = run(
+        {expr: NodeChangeForExpression()..introduceAs('bool', _MockInfo())});
     expect(previewInfo.applyTo(code), 'f(a, b) => (a < b) as bool;');
   }
 
@@ -380,7 +372,7 @@
     await analyze('f(a) => a++;');
     var expr = findNode.postfix('a++');
     var previewInfo =
-        run({expr: NodeChangeForExpression()..addNullCheck = true});
+        run({expr: NodeChangeForExpression()..addNullCheck(_MockInfo())});
     expect(previewInfo.applyTo(code), 'f(a) => a++!;');
   }
 
@@ -388,7 +380,7 @@
     await analyze('f(a) => -a;');
     var expr = findNode.prefix('-a');
     var previewInfo =
-        run({expr: NodeChangeForExpression()..addNullCheck = true});
+        run({expr: NodeChangeForExpression()..addNullCheck(_MockInfo())});
     expect(previewInfo.applyTo(code), 'f(a) => (-a)!;');
   }
 
@@ -524,7 +516,7 @@
     var previewInfo = run({
       methodInvocation: NodeChangeForMethodInvocation()
         ..removeNullAwareness = true,
-      argument: NodeChangeForExpression()..addNullCheck = true
+      argument: NodeChangeForExpression()..addNullCheck(_MockInfo())
     });
     expect(previewInfo.applyTo(code), 'f(x) => x.m(x!);');
   }
@@ -658,7 +650,7 @@
             ..addExplicitType =
                 MockDartType(toStringValueWithNullability: 'int'),
       findNode.integerLiteral('0'): NodeChangeForExpression()
-        ..addNullCheck = true
+        ..addNullCheck(_MockInfo())
     });
     expect(previewInfo.applyTo(code), 'int x = 0!;');
   }
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 3fd3eb7..54d8468 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -47,7 +47,7 @@
       .having((c) => c.makeNullable, 'makeNullable', isNotNull);
 
   static final isNullCheck = TypeMatcher<NodeChangeForExpression>()
-      .having((c) => c.addNullCheck, 'addNullCheck', true);
+      .having((c) => c.addsNullCheck, 'addsNullCheck', true);
 
   static final isRemoveNullAwareness =
       TypeMatcher<NodeChangeForPropertyAccess>()
@@ -2292,7 +2292,7 @@
     var propertyAccess = findNode.propertyAccess('?.');
     visitSubexpression(propertyAccess, 'int', changes: {
       propertyAccess: TypeMatcher<NodeChangeForPropertyAccess>()
-          .having((c) => c.addNullCheck, 'addNullCheck', true)
+          .having((c) => c.addsNullCheck, 'addsNullCheck', true)
           .having((c) => c.removeNullAwareness, 'removeNullAwareness', true)
     });
   }
diff --git a/pkg/test_runner/lib/src/multitest.dart b/pkg/test_runner/lib/src/multitest.dart
index 7cd62eb..2f5ec07 100644
--- a/pkg/test_runner/lib/src/multitest.dart
+++ b/pkg/test_runner/lib/src/multitest.dart
@@ -72,6 +72,7 @@
 import "dart:io";
 
 import "path.dart";
+import "repository.dart";
 import "test_file.dart";
 import "utils.dart";
 
@@ -342,5 +343,47 @@
       .append(_suiteNameFromPath(suiteDir))
       .join(relative);
   TestUtils.mkdirRecursive(Path.workingDirectory, path);
+
+  _createPackageConfig(outputDir);
+
   return Path(File(path.toNativePath()).absolute.path);
 }
+
+/// Copies "tests/.dart_tool/package_config.json" to the multitest directory so
+/// that multitests have the right language version.
+///
+/// Also fixes relative paths in that file.
+void _createPackageConfig(String outputDir) {
+  var configDir =
+      Path(outputDir).append('generated_tests').append('.dart_tool');
+  TestUtils.mkdirRecursive(Path.workingDirectory, configDir);
+
+  var configFileSource = Repository.dir
+      .append('tests')
+      .append('.dart_tool')
+      .append('package_config.json');
+  var configFileDest = configDir.append('package_config.json');
+
+  var config = File(configFileSource.toNativePath()).readAsStringSync();
+
+  // The relative paths to the test "packages" ("language", "lib", etc.) are
+  // correct because they are also in the "generated_tests" directory. But the
+  // relative paths to the packages used by the tests ("expect",
+  // "async_helper") are now wrong because we need to walk farther out to get
+  // back to the repo's root directory.
+  //
+  // Was:
+  //
+  // <sdk>/tests/.dart_tool/package_config.json
+  // (2 levels from <sdk>)
+  //
+  // Now:
+  //
+  // <sdk>/build/ReleaseX64/generated_tests/.dart_tool/package_config.json
+  // (4 levels from <sdk>)
+  //
+  // TODO(rnystrom): This is a very hacky way to edit this file.
+  config = config.replaceAll('"../../', '"../../../../');
+
+  _writeFile(configFileDest.toNativePath(), config);
+}
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 97aa087..75ff955 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -244,7 +244,8 @@
         ],
         fileUri: node.fileUri,
         reference: referenceFrom?.reference)
-      ..fileOffset = node.fileOffset;
+      ..fileOffset = node.fileOffset
+      ..isNonNullableByDefault = node.enclosingLibrary.isNonNullableByDefault;
     _makeEntryPoint(ctor);
     node.addMember(ctor);
   }
@@ -348,7 +349,8 @@
         fileUri: field.fileUri,
         reference:
             indexedClass?.lookupProcedureNotSetter(pointerName.name)?.reference)
-      ..fileOffset = field.fileOffset;
+      ..fileOffset = field.fileOffset
+      ..isNonNullableByDefault = field.isNonNullableByDefault;
 
     // Sample output:
     // double get x => _xPtr.value;
@@ -369,7 +371,8 @@
         fileUri: field.fileUri,
         reference:
             indexedClass?.lookupProcedureNotSetter(field.name.name)?.reference)
-      ..fileOffset = field.fileOffset;
+      ..fileOffset = field.fileOffset
+      ..isNonNullableByDefault = field.isNonNullableByDefault;
 
     // Sample output:
     // set x(double v) { _xPtr.value = v; };
@@ -395,7 +398,8 @@
           fileUri: field.fileUri,
           reference:
               indexedClass?.lookupProcedureSetter(field.name.name)?.reference)
-        ..fileOffset = field.fileOffset;
+        ..fileOffset = field.fileOffset
+        ..isNonNullableByDefault = field.isNonNullableByDefault;
     }
 
     replacedGetters[field] = getter;
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index b41711e..ec56e61 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -185,12 +185,17 @@
       case CallKind.PropertyGet:
         assertx(args.values.length == firstParamIndex);
         assertx(args.names.isEmpty);
+        fieldValue.isGetterUsed = true;
         return fieldValue.getValue(
             typeFlowAnalysis, field.isStatic ? null : args.values[0]);
 
       case CallKind.PropertySet:
+      case CallKind.SetFieldInConstructor:
         assertx(args.values.length == firstParamIndex + 1);
         assertx(args.names.isEmpty);
+        if (selector.callKind == CallKind.PropertySet) {
+          fieldValue.isSetterUsed = true;
+        }
         final Type setterArg = args.values[firstParamIndex];
         fieldValue.setValue(
             setterArg, typeFlowAnalysis, field.isStatic ? null : args.receiver);
@@ -200,6 +205,7 @@
         // Call via field.
         // TODO(alexmarkov): support function types and use inferred type
         // to get more precise return type.
+        fieldValue.isGetterUsed = true;
         final receiver = fieldValue.getValue(
             typeFlowAnalysis, field.isStatic ? null : args.values[0]);
         if (receiver != const EmptyType()) {
@@ -766,6 +772,12 @@
   /// Flag indicating if field initializer was executed.
   bool isInitialized = false;
 
+  /// Flag indicating if field getter was executed.
+  bool isGetterUsed = false;
+
+  /// Flag indicating if field setter was executed.
+  bool isSetterUsed = false;
+
   _FieldValue(this.field, this.typeGuardSummary, TypesBuilder typesBuilder)
       : staticType = typesBuilder.fromStaticType(field.type, true) {
     if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
@@ -1385,6 +1397,26 @@
     return false;
   }
 
+  /// Returns true if analysis found that getter corresponding to the given
+  /// [field] could be executed.
+  bool isFieldGetterUsed(Field field) {
+    final fieldValue = _fieldValues[field];
+    if (fieldValue != null) {
+      return fieldValue.isGetterUsed;
+    }
+    return false;
+  }
+
+  /// Returns true if analysis found that setter corresponding to the given
+  /// [field] could be executed.
+  bool isFieldSetterUsed(Field field) {
+    final fieldValue = _fieldValues[field];
+    if (fieldValue != null) {
+      return fieldValue.isSetterUsed;
+    }
+    return false;
+  }
+
   bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c);
 
   Call callSite(TreeNode node) => summaryCollector.callSites[node];
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index d0c284e..715b5c9 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -16,7 +16,8 @@
   Method, // x.foo(..) or foo()
   PropertyGet, // ... x.foo ...
   PropertySet, // x.foo = ...
-  FieldInitializer,
+  FieldInitializer, // run initializer of a field
+  SetFieldInConstructor, // foo = ... in initializer list in a constructor
 }
 
 /// [Selector] encapsulates the way of calling (at the call site).
@@ -55,6 +56,7 @@
         return member.getterType;
       case CallKind.PropertySet:
       case CallKind.FieldInitializer:
+      case CallKind.SetFieldInConstructor:
         return const BottomType();
     }
     return null;
@@ -72,7 +74,8 @@
       case CallKind.PropertySet:
         return (member is Field) || ((member is Procedure) && member.isSetter);
       case CallKind.FieldInitializer:
-        return (member is Field);
+      case CallKind.SetFieldInConstructor:
+        return member is Field;
     }
     return false;
   }
@@ -84,6 +87,7 @@
       case CallKind.PropertyGet:
         return 'get ';
       case CallKind.PropertySet:
+      case CallKind.SetFieldInConstructor:
         return 'set ';
       case CallKind.FieldInitializer:
         return 'init ';
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index f0021f0..9575612 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -800,6 +800,7 @@
         break;
 
       case CallKind.PropertySet:
+      case CallKind.SetFieldInConstructor:
         args.add(new Type.nullableAny());
         break;
 
@@ -2071,8 +2072,11 @@
   TypeExpr visitFieldInitializer(FieldInitializer node) {
     final value = _visit(node.value);
     final args = new Args<TypeExpr>([_receiver, value]);
-    _makeCall(node,
-        new DirectSelector(node.field, callKind: CallKind.PropertySet), args);
+    _makeCall(
+        node,
+        new DirectSelector(node.field,
+            callKind: CallKind.SetFieldInConstructor),
+        args);
     return null;
   }
 
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index c29fb3c..5f20ca6 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -67,12 +67,15 @@
 
   final transformsStopWatch = new Stopwatch()..start();
 
-  new TreeShaker(component, typeFlowAnalysis).transformComponent(component);
+  final treeShaker = new TreeShaker(component, typeFlowAnalysis);
+  treeShaker.transformComponent(component);
 
-  new TFADevirtualization(component, typeFlowAnalysis, hierarchy)
+  new TFADevirtualization(
+          component, typeFlowAnalysis, hierarchy, treeShaker.fieldMorpher)
       .visitComponent(component);
 
-  new AnnotateKernel(component, typeFlowAnalysis).visitComponent(component);
+  new AnnotateKernel(component, typeFlowAnalysis, treeShaker.fieldMorpher)
+      .visitComponent(component);
 
   transformsStopWatch.stop();
 
@@ -87,9 +90,10 @@
 /// Devirtualization based on results of type flow analysis.
 class TFADevirtualization extends Devirtualization {
   final TypeFlowAnalysis _typeFlowAnalysis;
+  final FieldMorpher fieldMorpher;
 
-  TFADevirtualization(
-      Component component, this._typeFlowAnalysis, ClassHierarchy hierarchy)
+  TFADevirtualization(Component component, this._typeFlowAnalysis,
+      ClassHierarchy hierarchy, this.fieldMorpher)
       : super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy);
 
   @override
@@ -97,7 +101,8 @@
       {bool setter = false}) {
     final callSite = _typeFlowAnalysis.callSite(node);
     if (callSite != null) {
-      final Member singleTarget = callSite.monomorphicTarget;
+      final Member singleTarget = fieldMorpher
+          .getMorphedMember(callSite.monomorphicTarget, isSetter: setter);
       if (singleTarget != null) {
         return new DirectCallMetadata(
             singleTarget, callSite.isNullableReceiver);
@@ -110,6 +115,7 @@
 /// Annotates kernel AST with metadata using results of type flow analysis.
 class AnnotateKernel extends RecursiveVisitor<Null> {
   final TypeFlowAnalysis _typeFlowAnalysis;
+  final FieldMorpher fieldMorpher;
   final InferredTypeMetadataRepository _inferredTypeMetadata;
   final UnreachableNodeMetadataRepository _unreachableNodeMetadata;
   final ProcedureAttributesMetadataRepository _procedureAttributesMetadata;
@@ -117,7 +123,7 @@
   final Class _intClass;
   Constant _nullConstant;
 
-  AnnotateKernel(Component component, this._typeFlowAnalysis)
+  AnnotateKernel(Component component, this._typeFlowAnalysis, this.fieldMorpher)
       : _inferredTypeMetadata = new InferredTypeMetadataRepository(),
         _unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
         _procedureAttributesMetadata =
@@ -278,7 +284,8 @@
 
         // TODO(alexmarkov): figure out how to pass receiver type.
       }
-    } else if (!member.isAbstract) {
+    } else if (!member.isAbstract &&
+        !fieldMorpher.isExtraMemberWithReachableBody(member)) {
       _setUnreachable(member);
     }
 
@@ -287,14 +294,15 @@
     // interface target, and table dispatch calls need selector IDs for all
     // interface targets.
     if (member.isInstanceMember) {
+      final original = fieldMorpher.getOriginalMember(member);
       final attrs = new ProcedureAttributesMetadata(
           methodOrSetterCalledDynamically:
-              _typeFlowAnalysis.isCalledDynamically(member),
+              _typeFlowAnalysis.isCalledDynamically(original),
           getterCalledDynamically:
-              _typeFlowAnalysis.isGetterCalledDynamically(member),
-          hasThisUses: _typeFlowAnalysis.isCalledViaThis(member),
-          hasNonThisUses: _typeFlowAnalysis.isCalledNotViaThis(member),
-          hasTearOffUses: _typeFlowAnalysis.isTearOffTaken(member),
+              _typeFlowAnalysis.isGetterCalledDynamically(original),
+          hasThisUses: _typeFlowAnalysis.isCalledViaThis(original),
+          hasNonThisUses: _typeFlowAnalysis.isCalledNotViaThis(original),
+          hasTearOffUses: _typeFlowAnalysis.isTearOffTaken(original),
           methodOrSetterSelectorId:
               _tableSelectorAssigner.methodOrSetterSelectorId(member),
           getterSelectorId: _tableSelectorAssigner.getterSelectorId(member));
@@ -393,12 +401,14 @@
   final Set<Member> _usedMembers = new Set<Member>();
   final Set<Extension> _usedExtensions = new Set<Extension>();
   final Set<Typedef> _usedTypedefs = new Set<Typedef>();
+  FieldMorpher fieldMorpher;
   _TreeShakerTypeVisitor typeVisitor;
   _TreeShakerConstantVisitor constantVisitor;
   _TreeShakerPass1 _pass1;
   _TreeShakerPass2 _pass2;
 
   TreeShaker(Component component, this.typeFlowAnalysis) {
+    fieldMorpher = new FieldMorpher(this);
     typeVisitor = new _TreeShakerTypeVisitor(this);
     constantVisitor = new _TreeShakerConstantVisitor(this, typeVisitor);
     _pass1 = new _TreeShakerPass1(this);
@@ -417,13 +427,25 @@
   bool isClassAllocated(Class c) => typeFlowAnalysis.isClassAllocated(c);
   bool isMemberUsed(Member m) => _usedMembers.contains(m);
   bool isExtensionUsed(Extension e) => _usedExtensions.contains(e);
-  bool isMemberBodyReachable(Member m) => typeFlowAnalysis.isMemberUsed(m);
+  bool isMemberBodyReachable(Member m) =>
+      typeFlowAnalysis.isMemberUsed(m) ||
+      fieldMorpher.isExtraMemberWithReachableBody(m);
   bool isFieldInitializerReachable(Field f) =>
       typeFlowAnalysis.isFieldInitializerUsed(f);
+  bool isFieldGetterReachable(Field f) => typeFlowAnalysis.isFieldGetterUsed(f);
+  bool isFieldSetterReachable(Field f) => typeFlowAnalysis.isFieldSetterUsed(f);
   bool isMemberReferencedFromNativeCode(Member m) =>
       typeFlowAnalysis.nativeCodeOracle.isMemberReferencedFromNativeCode(m);
   bool isTypedefUsed(Typedef t) => _usedTypedefs.contains(t);
 
+  bool retainField(Field f) =>
+      isFieldGetterReachable(f) ||
+      (f.initializer != null &&
+          isFieldInitializerReachable(f) &&
+          mayHaveSideEffects(f.initializer)) ||
+      (f.isLate && f.isFinal) ||
+      isMemberReferencedFromNativeCode(f);
+
   void addClassUsedInType(Class c) {
     if (_classesUsedInType.add(c)) {
       if (kPrintDebug) {
@@ -459,9 +481,15 @@
       } else if (m is Procedure) {
         func = m.function;
         if (m.forwardingStubSuperTarget != null) {
+          m.forwardingStubSuperTarget = fieldMorpher.adjustInstanceCallTarget(
+              m.forwardingStubSuperTarget,
+              isSetter: m.isSetter);
           addUsedMember(m.forwardingStubSuperTarget);
         }
         if (m.forwardingStubInterfaceTarget != null) {
+          m.forwardingStubInterfaceTarget = fieldMorpher
+              .adjustInstanceCallTarget(m.forwardingStubInterfaceTarget,
+                  isSetter: m.isSetter);
           addUsedMember(m.forwardingStubInterfaceTarget);
         }
       } else if (m is Constructor) {
@@ -514,6 +542,86 @@
   }
 }
 
+class FieldMorpher {
+  final TreeShaker shaker;
+  final Set<Member> _extraMembersWithReachableBody = <Member>{};
+  final Map<Field, Member> _gettersForRemovedFields = <Field, Member>{};
+  final Map<Field, Member> _settersForRemovedFields = <Field, Member>{};
+  final Map<Member, Field> _removedFields = <Member, Field>{};
+
+  FieldMorpher(this.shaker);
+
+  Member _createAccessorForRemovedField(Field field, bool isSetter) {
+    assertx(!field.isStatic);
+    assertx(!shaker.retainField(field));
+    Procedure accessor;
+    if (isSetter) {
+      final isAbstract = !shaker.isFieldSetterReachable(field);
+      final parameter = new VariableDeclaration('value', type: field.type)
+        ..isCovariant = field.isCovariant
+        ..isGenericCovariantImpl = field.isGenericCovariantImpl
+        ..fileOffset = field.fileOffset;
+      accessor = new Procedure(
+          field.name,
+          ProcedureKind.Setter,
+          new FunctionNode(null,
+              positionalParameters: [parameter], returnType: const VoidType())
+            ..fileOffset = field.fileOffset,
+          isAbstract: isAbstract,
+          fileUri: field.fileUri);
+      if (!isAbstract) {
+        _extraMembersWithReachableBody.add(accessor);
+      }
+    } else {
+      accessor = new Procedure(field.name, ProcedureKind.Getter,
+          new FunctionNode(null, returnType: field.type),
+          isAbstract: true, fileUri: field.fileUri);
+    }
+    accessor.fileOffset = field.fileOffset;
+    field.enclosingClass.addMember(accessor);
+    _removedFields[accessor] = field;
+    shaker.addUsedMember(accessor);
+    return accessor;
+  }
+
+  /// Return a replacement for an instance call target.
+  /// If necessary, creates a getter or setter as a replacement if target is a
+  /// field which is going to be removed by the tree shaker.
+  /// This method is used during tree shaker pass 1.
+  Member adjustInstanceCallTarget(Member target, {bool isSetter = false}) {
+    if (target is Field && !shaker.retainField(target)) {
+      final targets =
+          isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
+      return targets[target] ??=
+          _createAccessorForRemovedField(target, isSetter);
+    }
+    return target;
+  }
+
+  bool isExtraMemberWithReachableBody(Member member) =>
+      _extraMembersWithReachableBody.contains(member);
+
+  /// Return a member which replaced [target] in instance calls.
+  /// This method can be used after tree shaking to discover replacement.
+  Member getMorphedMember(Member target, {bool isSetter = false}) {
+    if (target == null) {
+      return null;
+    }
+    final targets =
+        isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
+    return targets[target] ?? target;
+  }
+
+  /// Return original member which was replaced by [target] in instance calls.
+  /// This method can be used after tree shaking.
+  Member getOriginalMember(Member target) {
+    if (target == null) {
+      return null;
+    }
+    return _removedFields[target] ?? target;
+  }
+}
+
 /// Visits Dart types and collects all classes and typedefs used in types.
 /// This visitor is used during pass 1 of tree shaking. It is a separate
 /// visitor because [Transformer] does not provide a way to traverse types.
@@ -564,9 +672,10 @@
 /// transforms unreachable calls into 'throw' expressions.
 class _TreeShakerPass1 extends Transformer {
   final TreeShaker shaker;
+  final FieldMorpher fieldMorpher;
   Procedure _unsafeCast;
 
-  _TreeShakerPass1(this.shaker);
+  _TreeShakerPass1(this.shaker) : fieldMorpher = shaker.fieldMorpher;
 
   void transform(Component component) {
     component.transformChildren(this);
@@ -609,7 +718,9 @@
           'Attempt to execute code removed by Dart AOT compiler (TFA)'));
     }
     for (var arg in args.reversed) {
-      node = new Let(new VariableDeclaration(null, initializer: arg), node);
+      if (mayHaveSideEffects(arg)) {
+        node = new Let(new VariableDeclaration(null, initializer: arg), node);
+      }
     }
     Statistics.callsDropped++;
     return node;
@@ -686,7 +797,7 @@
 
   @override
   TreeNode visitField(Field node) {
-    if (shaker.isMemberBodyReachable(node)) {
+    if (shaker.retainField(node)) {
       if (kPrintTrace) {
         tracePrint("Visiting $node");
       }
@@ -698,12 +809,10 @@
           node.initializer = _makeUnreachableCall([])..parent = node;
         }
       }
-    } else if (shaker.isMemberReferencedFromNativeCode(node)) {
-      // Preserve members referenced from native code to satisfy lookups, even
-      // if they are not reachable. An instance member could be added via
-      // native code entry point but still unreachable if no instances of
-      // its enclosing class are allocated.
-      shaker.addUsedMember(node);
+    } else if (shaker.isFieldSetterReachable(node) && !node.isStatic) {
+      // Make sure setter is created to replace the field even if field is not
+      // used as an instance call target.
+      fieldMorpher.adjustInstanceCallTarget(node, isSetter: true);
     }
     return node;
   }
@@ -715,6 +824,8 @@
       return _makeUnreachableCall(
           _flattenArguments(node.arguments, receiver: node.receiver));
     } else {
+      node.interfaceTarget =
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -728,6 +839,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
+      node.interfaceTarget =
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -741,6 +854,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
     } else {
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -754,6 +869,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
     } else {
+      node.interfaceTarget =
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -767,6 +884,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([]);
     } else {
+      node.interfaceTarget =
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -780,6 +899,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
     } else {
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
       if (node.interfaceTarget != null) {
         shaker.addUsedMember(node.interfaceTarget);
       }
@@ -825,7 +946,11 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
     } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      final target = node.target;
+      assertx(shaker.isMemberBodyReachable(target), details: node);
+      if (target is Field && !shaker.retainField(target)) {
+        return node.value;
+      }
       return node;
     }
   }
@@ -837,7 +962,7 @@
       return _makeUnreachableCall(
           _flattenArguments(node.arguments, receiver: node.receiver));
     } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      assertx(shaker.isMemberBodyReachable(node.target), details: node);
       return node;
     }
   }
@@ -848,7 +973,10 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      final target = node.target;
+      assertx(shaker.isMemberBodyReachable(target), details: node);
+      assertx(target is! Field || shaker.isFieldGetterReachable(target),
+          details: node);
       return node;
     }
   }
@@ -859,7 +987,9 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
     } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      assertx(shaker.isMemberBodyReachable(node.target), details: node);
+      node.target =
+          fieldMorpher.adjustInstanceCallTarget(node.target, isSetter: true);
       return node;
     }
   }
@@ -902,12 +1032,20 @@
   }
 
   @override
-  visitFieldInitializer(FieldInitializer node) {
+  TreeNode visitFieldInitializer(FieldInitializer node) {
     node.transformChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer([node.value]);
     } else {
       assertx(shaker.isMemberBodyReachable(node.field), details: node.field);
+      if (!shaker.retainField(node.field)) {
+        if (mayHaveSideEffects(node.value)) {
+          return LocalInitializer(
+              VariableDeclaration(null, initializer: node.value));
+        } else {
+          return null;
+        }
+      }
       return node;
     }
   }
@@ -1180,3 +1318,26 @@
     constant.type.accept(typeVisitor);
   }
 }
+
+bool mayHaveSideEffects(Expression node) {
+  if (node is BasicLiteral ||
+      node is ConstantExpression ||
+      node is ThisExpression) {
+    return false;
+  }
+  if (node is VariableGet && !node.variable.isLate) {
+    return false;
+  }
+  if (node is StaticGet) {
+    final target = node.target;
+    if (target is Field && !target.isLate) {
+      final initializer = target.initializer;
+      if (initializer == null ||
+          initializer is BasicLiteral ||
+          initializer is ConstantExpression) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index afa5e6b..e95b52b 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -10,7 +10,9 @@
         CompilerOptions,
         DiagnosticMessage,
         computePlatformBinariesLocation,
-        kernelForProgram;
+        kernelForProgram,
+        parseExperimentalArguments,
+        parseExperimentalFlags;
 import 'package:kernel/ast.dart';
 import 'package:kernel/text/ast_to_text.dart' show Printer;
 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
@@ -35,6 +37,7 @@
 Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
     {Target target,
     bool enableSuperMixins = false,
+    List<String> experimentalFlags,
     Map<String, String> environmentDefines}) async {
   final platformKernel =
       computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
@@ -45,6 +48,11 @@
     ..target = target
     ..linkedDependencies = <Uri>[platformKernel]
     ..environmentDefines = environmentDefines
+    ..experimentalFlags =
+        parseExperimentalFlags(parseExperimentalArguments(experimentalFlags),
+            onError: (String message) {
+      throw message;
+    })
     ..onDiagnostic = (DiagnosticMessage message) {
       fail("Compilation error: ${message.plainTextFormatted.join('\n')}");
     };
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index b51cbd3..d26a8ec 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -18,10 +18,10 @@
 
 final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
 
-runTestCase(Uri source) async {
+runTestCase(Uri source, List<String> experimentalFlags) async {
   final target = new TestingVmTarget(new TargetFlags());
-  Component component =
-      await compileTestCaseToKernelProgram(source, target: target);
+  Component component = await compileTestCaseToKernelProgram(source,
+      target: target, experimentalFlags: experimentalFlags);
 
   final coreTypes = new CoreTypes(component);
 
@@ -44,7 +44,10 @@
         .listSync(recursive: true, followLinks: false)
         .reversed) {
       if (entry.path.endsWith(".dart")) {
-        test(entry.path, () => runTestCase(entry.uri));
+        final List<String> experimentalFlags = [
+          if (entry.path.endsWith("_nnbd.dart")) 'non-nullable',
+        ];
+        test(entry.path, () => runTestCase(entry.uri, experimentalFlags));
       }
     }
   });
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index e90a55c..316e2e4 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -684,7 +684,7 @@
 ]library #lib from "#lib" as #lib {
 
   typedef GenericFunctionType = <X extends dart.core::Object* = dynamic>(X*) →* X*;
-  class A extends dart.core::Object {
+  class A extends dart.core::Object /*isEnum*/  {
     final field dart.core::int* index;
     final field dart.core::String* _name;
     static const field dart.core::List<#lib::A*>* values = #C13;
@@ -698,31 +698,31 @@
     method toString() → dart.core::String*
       return this.{=#lib::A::_name};
   }
-  class B extends dart.core::Object {
+  class B extends dart.core::Object /*hasConstConstructor*/  {
     final field dart.core::int* i;
     const constructor •(dart.core::int* i) → #lib::B*
       : #lib::B::i = i, super dart.core::Object::•()
       ;
   }
-  class C extends #lib::B {
+  class C extends #lib::B /*hasConstConstructor*/  {
     final field dart.core::int* j;
     const constructor •(dart.core::int* a, dart.core::int* b, dart.core::int* c) → #lib::C*
       : #lib::C::j = a.{dart.core::num::+}(b), super #lib::B::•(c.{dart.core::num::*}(5))
       ;
   }
-  class D extends dart.core::Object {
+  class D extends dart.core::Object /*hasConstConstructor*/  {
     final field dynamic x;
     final field dynamic y;
     const constructor •(dynamic x, [dynamic y = #C14]) → #lib::D*
       : #lib::D::x = x, #lib::D::y = y, super dart.core::Object::•()
       ;
   }
-  class E<T extends dart.core::Object* = dynamic> extends dart.core::Object {
+  class E<T extends dart.core::Object* = dynamic> extends dart.core::Object /*hasConstConstructor*/  {
     const constructor •() → #lib::E<#lib::E::T*>*
       : super dart.core::Object::•()
       ;
   }
-  class F<P extends dart.core::Object* = dynamic, Q extends dart.core::Object* = dynamic> extends #lib::E<dart.core::Map<#lib::F::P*, #lib::F::Q*>*> {
+  class F<P extends dart.core::Object* = dynamic, Q extends dart.core::Object* = dynamic> extends #lib::E<dart.core::Map<#lib::F::P*, #lib::F::Q*>*> /*hasConstConstructor*/  {
     const constructor •() → #lib::F<#lib::F::P*, #lib::F::Q*>*
       : super #lib::E::•()
       ;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index ec084d3..a866265 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -4,17 +4,17 @@
 
 @#C5
 typedef SomeType<contravariant T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
-abstract class ClassAnnotation2 extends core::Object {
+abstract class ClassAnnotation2 extends core::Object /*hasConstConstructor*/  {
 }
-abstract class MethodAnnotation extends core::Object {
+abstract class MethodAnnotation extends core::Object /*hasConstConstructor*/  {
 [@vm.unreachable.metadata=] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  final field core::int* x;
 }
-abstract class TypedefAnnotation extends core::Object {
+abstract class TypedefAnnotation extends core::Object /*hasConstConstructor*/  {
 [@vm.unreachable.metadata=] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  final field core::List<core::int*>* list;
 }
-abstract class VarAnnotation extends core::Object {
+abstract class VarAnnotation extends core::Object /*hasConstConstructor*/  {
 }
-abstract class ParametrizedAnnotation<T extends core::Object* = dynamic> extends core::Object {
+abstract class ParametrizedAnnotation<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
 [@vm.unreachable.metadata=] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  final field self::ParametrizedAnnotation::T* foo;
 }
 abstract class A extends core::Object {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 09996bb..db3abec 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -15,7 +15,7 @@
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  operator []([@vm.inferred-type.metadata=!] core::int* i) → core::double*
     return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}));
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2]  operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int* i, core::double* value) → void {
-    let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements} in let dynamic #t2 = i in let dynamic #t3 = [@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+    let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements} in let dynamic #t2 = [@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector* a) → core::double* {
     core::double* result = 0.0;
@@ -27,7 +27,7 @@
 [@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector* v = new self::_Vector::•(10);
 [@vm.inferred-type.metadata=dart.core::_Double?]static field core::double* x = 0.0;
 static method main(core::List<core::String*>* args) → dynamic {
-  core::Stopwatch* timer = let final core::Stopwatch* #t4 = new core::Stopwatch::•() in let final void #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t4.{core::Stopwatch::start}() in #t4;
+  core::Stopwatch* timer = let final core::Stopwatch* #t3 = new core::Stopwatch::•() in let final void #t4 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t3.{core::Stopwatch::start}() in #t3;
   for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
     self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 78eb735..4c84b68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -11,7 +11,7 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method getBar() → core::String*
     return "bar";
 }
-class B extends core::Object {
+class B extends core::Object /*isEnum*/  {
 [@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  final field core::int* index;
 [@vm.inferred-type.metadata=dart.core::_OneByteString (value: B.b2)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  final field core::String* _name;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method toString() → core::String*
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 15f83fe..6149267 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -32,7 +32,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _E&D&C extends self::D implements self::C {
+abstract class _E&D&C extends self::D implements self::C /*isAnonymousMixin,isEliminatedMixin*/  {
   synthetic constructor •() → self::_E&D&C*
     : super self::D::•()
     ;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
index 8da19ec..3390a91 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
@@ -17,7 +17,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {}
 }
-class Point extends core::Object {
+class Point extends core::Object /*hasConstConstructor*/  {
 [@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  final field self::I* x;
   const constructor •([@vm.inferred-type.metadata=!] self::I* x) → self::Point*
     : self::Point::x = x, super core::Object::•()
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
index 47a15c4..0ed46d3 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
@@ -14,7 +14,7 @@
 [@vm.inferred-type.metadata=#lib::B?]static field self::I* ii = new self::B::•();
 static method bar([@vm.inferred-type.metadata=#lib::B?] self::I* i) → void {
   if(i is self::A*) {
-    let dynamic #t1 = i{self::A*} in let dynamic #t2 = 42 in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+    throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
 }
 static method main(core::List<core::String*>* args) → dynamic {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
index 0e5a825..7acac49 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
@@ -2,8 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
-}
 class B extends core::Object {
   constructor •() → self::B*
     : super core::Object::•() {
@@ -16,8 +14,7 @@
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field self::A* field = throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
 static method main() → void {
-  self::field = null;
+  null;
   [@vm.direct-call.metadata=#lib::C::instanceField] new self::C::•().{self::C::instanceField} = null;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
new file mode 100644
index 0000000..af6a9b8
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for tree shaking of write-only fields.
+
+import "package:expect/expect.dart";
+
+foo() {}
+
+class A {
+  // Should be removed.
+  var unused1;
+
+  // Should be removed.
+  var unused2 = 42;
+
+  // Not removed due to a non-trivial initializer.
+  var unused3 = foo();
+}
+
+class B {
+  // Should be removed.
+  var unused4;
+
+  // Should be removed.
+  var unused5;
+
+  B(this.unused4) : unused5 = foo();
+}
+
+class C<T> {
+  // Should be replaced with setter.
+  T bar;
+}
+
+class D implements C<int> {
+  // Should be replaced with setter.
+  int bar;
+}
+
+class E {
+  // Should be replaced with getter.
+  final int bar;
+
+  E(this.bar);
+}
+
+class F implements E {
+  int get bar => 42;
+}
+
+class G {
+  // Not removed because used in a constant.
+  final int bazz;
+
+  const G(this.bazz);
+}
+
+class H {
+  // Should be replaced with setter.
+  int unused6;
+}
+
+class I extends H {
+  foo() {
+    super.unused6 = 3;
+  }
+}
+
+// Should be removed.
+int unusedStatic7 = foo();
+
+void main() {
+  new A();
+  new B('hi');
+
+  C<num> c = new D();
+  Expect.throws(() {
+    c.bar = 3.14;
+  });
+
+  E e = new F();
+  Expect.equals(42, e.bar);
+
+  Expect.isTrue(!identical(const G(1), const G(2)));
+
+  new I().foo();
+
+  unusedStatic7 = 5;
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
new file mode 100644
index 0000000..9d81be0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -0,0 +1,68 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+class A 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]  field dynamic unused3 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo();
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString (value: hi)] dynamic unused4) → self::B*
+    : dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
+    ;
+}
+abstract class C<T extends core::Object* = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  abstract set bar(generic-covariant-impl self::C::T* value) → void;
+}
+class D extends core::Object implements self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  set bar(generic-covariant-impl core::int* value) → void;
+}
+abstract class E extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  abstract get bar() → core::int*;
+}
+class F extends core::Object implements self::E {
+  synthetic constructor •() → self::F*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  get bar() → core::int*
+    return 42;
+}
+class G extends core::Object /*hasConstConstructor*/  {
+[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  final field core::int* bazz;
+}
+abstract class H extends core::Object {
+  synthetic constructor •() → self::H*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7]  set unused6(core::int* value) → void;
+}
+class I extends self::H {
+  synthetic constructor •() → self::I*
+    : super self::H::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  method foo() → dynamic {
+    super.{self::H::unused6} = 3;
+  }
+}
+static method foo() → dynamic {}
+static method main() → void {
+  new self::A::•();
+  new self::B::•("hi");
+  self::C<core::num*>* c = new self::D::•();
+  exp::Expect::throws<dynamic>(() → core::Null? {
+    [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num*>*] [@vm.direct-call.metadata=#lib::D::bar] c.{self::C::bar} = 3.14;
+  });
+  self::E* e = new self::F::•();
+  exp::Expect::equals(42, [@vm.direct-call.metadata=#lib::F::bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar});
+  exp::Expect::isTrue(![@vm.inferred-type.metadata=dart.core::bool] core::identical(#C2, #C4));
+  [@vm.direct-call.metadata=#lib::I::foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}();
+  5;
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
new file mode 100644
index 0000000..b368917
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.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.
+
+// Test for tree shaking of write-only late fields.
+// This test requires non-nullable experiment.
+
+import "package:expect/expect.dart";
+
+foo() {}
+
+class A {
+  // Should be replaced with setter.
+  late int x;
+
+  use() {
+    x = 3;
+  }
+}
+
+class B {
+  // Should be retained.
+  late final int x;
+
+  use() {
+    x = 3;
+  }
+}
+
+// Should be removed.
+late int staticLateA;
+
+// Should be retained.
+late final int staticLateB;
+
+void main() {
+  new A().use();
+  new B().use();
+
+  staticLateA = 4;
+  staticLateB = 4;
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect
new file mode 100644
index 0000000..b2e47a8
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect
@@ -0,0 +1,31 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method use() → dynamic {
+    [@vm.direct-call.metadata=#lib::A::x] this.{self::A::x} = 3;
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  set /*isNullableByDefault*/ x(core::int value) → void;
+}
+class B extends core::Object {
+[@vm.unreachable.metadata=] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  late final field core::int x;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method use() → dynamic {
+    this.{self::B::x} = 3;
+  }
+}
+[@vm.inferred-type.metadata=dart.core::_Smi?]late static final field core::int staticLateB;
+static method main() → void {
+  [@vm.direct-call.metadata=#lib::A::use] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::use}();
+  [@vm.direct-call.metadata=#lib::B::use] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::use}();
+  4;
+  self::staticLateB = 4;
+}
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index 5303e47..363613f 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -226,7 +226,7 @@
   }
 }
 
-static bool DeleteFile(wchar_t* file_name, PathBuffer* path) {
+static bool DeleteFile(const wchar_t* file_name, PathBuffer* path) {
   if (!path->AddW(file_name)) {
     return false;
   }
@@ -258,7 +258,7 @@
   return false;
 }
 
-static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) {
+static bool DeleteDir(const wchar_t* dir_name, PathBuffer* path) {
   if ((wcscmp(dir_name, L".") == 0) || (wcscmp(dir_name, L"..") == 0)) {
     return true;
   }
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index cc39f08..435c240 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -186,6 +186,21 @@
   return retval;
 }
 
+DART_EXPORT intptr_t Regress40537(uint8_t x) {
+  std::cout << "Regress40537(" << static_cast<int>(x) << ")\n";
+  return x == 249 ? 1 : 0;
+}
+
+DART_EXPORT intptr_t Regress40537Variant2(uint8_t x) {
+  std::cout << "Regress40537Variant2(" << static_cast<int>(x) << ")\n";
+  return x;
+}
+
+DART_EXPORT uint8_t Regress40537Variant3(intptr_t x) {
+  std::cout << "Regress40537Variant3(" << static_cast<int>(x) << ")\n";
+  return x;
+}
+
 // Performs some computation on various sized unsigned ints.
 // Used for testing value ranges for unsigned ints.
 DART_EXPORT int64_t UintComputation(uint8_t a,
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index dd618a5..0fde6ae 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -262,6 +262,10 @@
   return File::Open(namespc, path.get(), mode);
 }
 
+File* File::OpenStdio(int fd) {
+  return new File(new FileHandle(fd));
+}
+
 bool File::Exists(Namespace* namespc, const char* name) {
   NamespaceScope ns(namespc, name);
   struct stat st;
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 48c384a..cfcae15 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -170,7 +170,7 @@
                         written);
     int buffer_len =
         WideCharToMultiByte(cp, 0, wide, written, NULL, 0, NULL, NULL);
-    delete wide;
+    delete[] wide;
     bytes_written = buffer_len;
   }
   return bytes_written;
@@ -401,8 +401,8 @@
   };
 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
 
-static const int kReparseDataHeaderSize = sizeof ULONG + 2 * sizeof USHORT;
-static const int kMountPointHeaderSize = 4 * sizeof USHORT;
+static const int kReparseDataHeaderSize = sizeof(ULONG) + 2 * sizeof(USHORT);
+static const int kMountPointHeaderSize = 4 * sizeof(USHORT);
 
 // Note: CreateLink used to create junctions on Windows instead of true
 // symbolic links. All File::*Link methods now support handling links created
@@ -541,7 +541,7 @@
   }
 
   int buffer_size =
-      sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR;
+      sizeof(REPARSE_DATA_BUFFER) + 2 * (MAX_PATH + 1) * sizeof(WCHAR);
   REPARSE_DATA_BUFFER* buffer =
       reinterpret_cast<REPARSE_DATA_BUFFER*>(Dart_ScopeAllocate(buffer_size));
   DWORD received_bytes;  // Value is not used.
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 296bc69..bd539e8 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -805,11 +805,11 @@
   return starter.Start();
 }
 
-static bool CloseProcessBuffers(struct pollfd fds[3]) {
+static bool CloseProcessBuffers(struct pollfd* fds, int alive) {
   int e = errno;
-  close(fds[0].fd);
-  close(fds[1].fd);
-  close(fds[2].fd);
+  for (int i = 0; i < alive; i++) {
+    close(fds[i].fd);
+  }
   errno = e;
   return false;
 }
@@ -846,28 +846,30 @@
   while (alive > 0) {
     // Blocking call waiting for events from the child process.
     if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) {
-      return CloseProcessBuffers(fds);
+      return CloseProcessBuffers(fds, alive);
     }
 
     // Process incoming data.
-    int current_alive = alive;
-    for (int i = 0; i < current_alive; i++) {
+    for (int i = 0; i < alive; i++) {
+      if ((fds[i].revents & (POLLNVAL | POLLERR)) != 0) {
+        return CloseProcessBuffers(fds, alive);
+      }
       if ((fds[i].revents & POLLIN) != 0) {
         intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
         if (fds[i].fd == out) {
           if (!out_data.Read(out, avail)) {
-            return CloseProcessBuffers(fds);
+            return CloseProcessBuffers(fds, alive);
           }
         } else if (fds[i].fd == err) {
           if (!err_data.Read(err, avail)) {
-            return CloseProcessBuffers(fds);
+            return CloseProcessBuffers(fds, alive);
           }
         } else if (fds[i].fd == exit_event) {
           if (avail == 8) {
             intptr_t b =
                 TEMP_FAILURE_RETRY(read(exit_event, exit_code_data.bytes, 8));
             if (b != 8) {
-              return CloseProcessBuffers(fds);
+              return CloseProcessBuffers(fds, alive);
             }
           }
         } else {
@@ -875,11 +877,15 @@
         }
       }
       if ((fds[i].revents & POLLHUP) != 0) {
+        // Remove the pollfd from the list of pollfds.
         close(fds[i].fd);
         alive--;
         if (i < alive) {
           fds[i] = fds[alive];
         }
+        // Process the same index again.
+        i--;
+        continue;
       }
     }
   }
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 9301b43..f6ec06d 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -804,11 +804,11 @@
   return starter.Start();
 }
 
-static bool CloseProcessBuffers(struct pollfd fds[3]) {
+static bool CloseProcessBuffers(struct pollfd* fds, int alive) {
   int e = errno;
-  close(fds[0].fd);
-  close(fds[1].fd);
-  close(fds[2].fd);
+  for (int i = 0; i < alive; i++) {
+    close(fds[i].fd);
+  }
   errno = e;
   return false;
 }
@@ -845,28 +845,30 @@
   while (alive > 0) {
     // Blocking call waiting for events from the child process.
     if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) {
-      return CloseProcessBuffers(fds);
+      return CloseProcessBuffers(fds, alive);
     }
 
     // Process incoming data.
-    int current_alive = alive;
-    for (int i = 0; i < current_alive; i++) {
+    for (int i = 0; i < alive; i++) {
+      if ((fds[i].revents & (POLLNVAL | POLLERR)) != 0) {
+        return CloseProcessBuffers(fds, alive);
+      }
       if ((fds[i].revents & POLLIN) != 0) {
         intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
         if (fds[i].fd == out) {
           if (!out_data.Read(out, avail)) {
-            return CloseProcessBuffers(fds);
+            return CloseProcessBuffers(fds, alive);
           }
         } else if (fds[i].fd == err) {
           if (!err_data.Read(err, avail)) {
-            return CloseProcessBuffers(fds);
+            return CloseProcessBuffers(fds, alive);
           }
         } else if (fds[i].fd == exit_event) {
           if (avail == 8) {
             intptr_t b =
                 TEMP_FAILURE_RETRY(read(exit_event, exit_code_data.bytes, 8));
             if (b != 8) {
-              return CloseProcessBuffers(fds);
+              return CloseProcessBuffers(fds, alive);
             }
           }
         } else {
@@ -874,11 +876,15 @@
         }
       }
       if ((fds[i].revents & POLLHUP) != 0) {
+        // Remove the pollfd from the list of pollfds.
         close(fds[i].fd);
         alive--;
         if (i < alive) {
           fds[i] = fds[alive];
         }
+        // Process the same index again.
+        i--;
+        continue;
       }
     }
   }
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index d9a087a..0f9287b 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -770,11 +770,11 @@
   return starter.Start();
 }
 
-static bool CloseProcessBuffers(struct pollfd fds[3]) {
+static bool CloseProcessBuffers(struct pollfd* fds, int alive) {
   int e = errno;
-  close(fds[0].fd);
-  close(fds[1].fd);
-  close(fds[2].fd);
+  for (int i = 0; i < alive; i++) {
+    close(fds[i].fd);
+  }
   errno = e;
   return false;
 }
@@ -811,13 +811,15 @@
   while (alive > 0) {
     // Blocking call waiting for events from the child process.
     if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) {
-      return CloseProcessBuffers(fds);
+      return CloseProcessBuffers(fds, alive);
     }
 
     // Process incoming data.
-    int current_alive = alive;
-    for (int i = 0; i < current_alive; i++) {
+    for (int i = 0; i < alive; i++) {
       intptr_t avail;
+      if ((fds[i].revents & (POLLNVAL | POLLERR)) != 0) {
+        return CloseProcessBuffers(fds, alive);
+      }
       if ((fds[i].revents & POLLIN) != 0) {
         avail = FDUtils::AvailableBytes(fds[i].fd);
         // On Mac OS POLLIN can be set with zero available
@@ -825,18 +827,18 @@
         if (avail > 0) {
           if (fds[i].fd == out) {
             if (!out_data.Read(out, avail)) {
-              return CloseProcessBuffers(fds);
+              return CloseProcessBuffers(fds, alive);
             }
           } else if (fds[i].fd == err) {
             if (!err_data.Read(err, avail)) {
-              return CloseProcessBuffers(fds);
+              return CloseProcessBuffers(fds, alive);
             }
           } else if (fds[i].fd == exit_event) {
             if (avail == 8) {
               intptr_t b =
-                  TEMP_FAILURE_RETRY(read(fds[i].fd, exit_code_data.bytes, 8));
+                  TEMP_FAILURE_RETRY(read(exit_event, exit_code_data.bytes, 8));
               if (b != 8) {
-                return CloseProcessBuffers(fds);
+                return CloseProcessBuffers(fds, alive);
               }
             }
           } else {
@@ -846,11 +848,15 @@
       }
       if (((fds[i].revents & POLLHUP) != 0) ||
           (((fds[i].revents & POLLIN) != 0) && (avail == 0))) {
+        // Remove the pollfd from the list of pollfds.
         close(fds[i].fd);
         alive--;
         if (i < alive) {
           fds[i] = fds[alive];
         }
+        // Process the same index again.
+        i--;
+        continue;
       }
     }
   }
diff --git a/runtime/bin/socket_base_win.cc b/runtime/bin/socket_base_win.cc
index 6aaef24..b24dc05 100644
--- a/runtime/bin/socket_base_win.cc
+++ b/runtime/bin/socket_base_win.cc
@@ -153,7 +153,7 @@
     case FILE_TYPE_DISK:
       return File::kFile;
     default:
-      return GetLastError == NO_ERROR ? File::kOther : -1;
+      return GetLastError() == NO_ERROR ? File::kOther : -1;
   }
 }
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index c736f39..c68de7b 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1488,6 +1488,11 @@
 DART_EXPORT Dart_Handle Dart_Null();
 
 /**
+ * Is this object null?
+ */
+DART_EXPORT bool Dart_IsNull(Dart_Handle object);
+
+/**
  * Returns the empty string object.
  *
  * \return A handle to the empty string object.
@@ -1495,9 +1500,14 @@
 DART_EXPORT Dart_Handle Dart_EmptyString();
 
 /**
- * Is this object null?
+ * Returns types that are not classes, and which therefore cannot be looked up
+ * as library members by Dart_GetType.
+ *
+ * \return A handle to the dynamic, void or Never type.
  */
-DART_EXPORT bool Dart_IsNull(Dart_Handle object);
+DART_EXPORT Dart_Handle Dart_TypeDynamic();
+DART_EXPORT Dart_Handle Dart_TypeVoid();
+DART_EXPORT Dart_Handle Dart_TypeNever();
 
 /**
  * Checks if the two objects are equal.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 4792f62..d2b1672 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -272,7 +272,7 @@
                  << Mirrors::kFactoryCtor);
   kind_flags |=
       (static_cast<intptr_t>(func.is_external()) << Mirrors::kExternal);
-  bool is_synthetic = func.is_no_such_method_forwarder();
+  bool is_synthetic = func.is_synthetic();
   kind_flags |= (static_cast<intptr_t>(is_synthetic) << Mirrors::kSynthetic);
   kind_flags |= (static_cast<intptr_t>(func.is_extension_member())
                  << Mirrors::kExtensionMember);
@@ -311,7 +311,9 @@
     ASSERT(ref_type.IsCanonical());
     return CreateClassMirror(cls, ref_type, is_declaration, owner_mirror);
   }
-  ASSERT(!cls.IsDynamicClass() && !cls.IsVoidClass());
+  ASSERT(!cls.IsDynamicClass());
+  ASSERT(!cls.IsVoidClass());
+  ASSERT(!cls.IsNeverClass());
   ASSERT(!type.IsNull());
   ASSERT(type.IsFinalized());
 
@@ -625,6 +627,10 @@
       Array& args = Array::Handle(Array::New(1));
       args.SetAt(0, Symbols::Dynamic());
       return CreateMirror(Symbols::_SpecialTypeMirror(), args);
+    } else if (cls.IsNeverClass()) {
+      Array& args = Array::Handle(Array::New(1));
+      args.SetAt(0, Symbols::Never());
+      return CreateMirror(Symbols::_SpecialTypeMirror(), args);
     }
     // TODO(regis): Until mirrors reflect nullability, force kLegacy, except for
     // Null type, which should remain nullable.
@@ -830,7 +836,8 @@
   ASSERT(type.HasTypeClass());
   const Class& cls = Class::Handle(type.type_class());
   ASSERT(!cls.IsNull());
-  if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsTypedefClass()) {
+  if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsNeverClass() ||
+      cls.IsTypedefClass()) {
     Exceptions::ThrowArgumentError(type);
     UNREACHABLE();
   }
@@ -1172,19 +1179,18 @@
     entry = entries.GetNext();
     if (entry.IsClass()) {
       const Class& klass = Class::Cast(entry);
-      // We filter out dynamic.
-      // TODO(12478): Should not need to filter out dynamic.
-      if (!klass.IsDynamicClass()) {
-        error = klass.EnsureIsFinalized(thread);
-        if (!error.IsNull()) {
-          Exceptions::PropagateError(error);
-        }
-        type = klass.DeclarationType();
-        member_mirror = CreateClassMirror(klass, type,
-                                          Bool::True(),  // is_declaration
-                                          owner_mirror);
-        member_mirrors.Add(member_mirror);
+      ASSERT(!klass.IsDynamicClass());
+      ASSERT(!klass.IsVoidClass());
+      ASSERT(!klass.IsNeverClass());
+      error = klass.EnsureIsFinalized(thread);
+      if (!error.IsNull()) {
+        Exceptions::PropagateError(error);
       }
+      type = klass.DeclarationType();
+      member_mirror = CreateClassMirror(klass, type,
+                                        Bool::True(),  // is_declaration
+                                        owner_mirror);
+      member_mirrors.Add(member_mirror);
     } else if (entry.IsField()) {
       const Field& field = Field::Cast(entry);
       if (field.is_reflectable()) {
@@ -1700,6 +1706,8 @@
     ASSERT(!script.IsNull());
     const String& uri = String::Handle(zone, script.url());
     return CreateSourceLocation(uri, 1, 1);
+  } else {
+    FATAL1("Unexpected declaration type: %s", decl.ToCString());
   }
 
   ASSERT(!script.IsNull());
diff --git a/runtime/observatory/tests/service/allocations_test.dart b/runtime/observatory/tests/service/allocations_test.dart
index 4b0f23b..b3a5c04 100644
--- a/runtime/observatory/tests/service/allocations_test.dart
+++ b/runtime/observatory/tests/service/allocations_test.dart
@@ -10,6 +10,9 @@
 
 class Foo {}
 
+// Prevent TFA from removing this static field to ensure the objects are kept
+// alive, so the allocation stats will report them via the service api.
+@pragma('vm:entry-point')
 List<Foo> foos;
 
 void script() {
diff --git a/runtime/observatory/tests/service/contexts_test.dart b/runtime/observatory/tests/service/contexts_test.dart
index ecc9b44..a857b5a 100644
--- a/runtime/observatory/tests/service/contexts_test.dart
+++ b/runtime/observatory/tests/service/contexts_test.dart
@@ -8,7 +8,15 @@
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
 
-var cleanBlock, copyingBlock, fullBlock, fullBlockWithChain;
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
+var cleanBlock;
+@pragma("vm:entry-point")
+var copyingBlock;
+@pragma("vm:entry-point")
+var fullBlock;
+@pragma("vm:entry-point")
+var fullBlockWithChain;
 
 Function genCleanBlock() {
   block(x) => x;
diff --git a/runtime/observatory/tests/service/dominator_tree_vm_test.dart b/runtime/observatory/tests/service/dominator_tree_vm_test.dart
index be63548..c136a91 100644
--- a/runtime/observatory/tests/service/dominator_tree_vm_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_vm_test.dart
@@ -12,62 +12,86 @@
 
 // small example from [Lenguaer & Tarjan 1979]
 class R {
+  // All fields are marked with @pragma("vm:entry-point")
+  // in order to make sure they are not removed by the tree shaker
+  // even though they are never read.
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
+  @pragma("vm:entry-point")
   var z;
 }
 
 class A {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class B {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
+  @pragma("vm:entry-point")
   var z;
 }
 
 class C {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class D {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class E {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class F {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class G {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class H {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class I {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class J {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class K {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class L {
+  @pragma("vm:entry-point")
   var x;
 }
 
diff --git a/runtime/observatory/tests/service/dominator_tree_vm_with_double_field_test.dart b/runtime/observatory/tests/service/dominator_tree_vm_with_double_field_test.dart
index 9edaf23..83bed89 100644
--- a/runtime/observatory/tests/service/dominator_tree_vm_with_double_field_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_vm_with_double_field_test.dart
@@ -21,62 +21,86 @@
 // small example from [Lenguaer & Tarjan 1979]
 class R {
   final double fld = getDoubleWithHeapObjectTag();
+  // Fields are marked with @pragma("vm:entry-point")
+  // in order to make sure they are not removed by the tree shaker
+  // even though they are never read.
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
+  @pragma("vm:entry-point")
   var z;
 }
 
 class A {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class B {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
+  @pragma("vm:entry-point")
   var z;
 }
 
 class C {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class D {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class E {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class F {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class G {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class H {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class I {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class J {
+  @pragma("vm:entry-point")
   var x;
 }
 
 class K {
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
 class L {
+  @pragma("vm:entry-point")
   var x;
 }
 
diff --git a/runtime/observatory/tests/service/get_instances_rpc_test.dart b/runtime/observatory/tests/service/get_instances_rpc_test.dart
index 8479483..e1ddebc 100644
--- a/runtime/observatory/tests/service/get_instances_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_instances_rpc_test.dart
@@ -9,7 +9,10 @@
 
 class _TestClass {
   _TestClass(this.x, this.y);
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
diff --git a/runtime/observatory/tests/service/get_retained_size_rpc_test.dart b/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
index 318c511..4db0fddc 100644
--- a/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
@@ -9,10 +9,14 @@
 
 class _TestClass {
   _TestClass(this.x, this.y);
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
+@pragma("vm:entry-point")
 var myVar;
 
 @pragma("vm:entry-point")
diff --git a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
index e9f6e55..50e720a 100644
--- a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
@@ -9,7 +9,10 @@
 
 class _TestClass {
   _TestClass();
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
   var x;
+  @pragma("vm:entry-point")
   var y;
 }
 
diff --git a/runtime/observatory/tests/service/inbound_references_test.dart b/runtime/observatory/tests/service/inbound_references_test.dart
index fddc8ba..995935e 100644
--- a/runtime/observatory/tests/service/inbound_references_test.dart
+++ b/runtime/observatory/tests/service/inbound_references_test.dart
@@ -9,6 +9,8 @@
 import 'test_helper.dart';
 
 class Node {
+  // Make sure this field is not removed by the tree shaker.
+  @pragma("vm:entry-point")
   var edge;
 }
 
diff --git a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
index c531ad6..978f0dc 100644
--- a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
+++ b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
@@ -9,12 +9,17 @@
 import 'test_helper.dart';
 
 class Super {
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
   var z = 1;
+  @pragma("vm:entry-point")
   var y = 2;
 }
 
 class Sub extends Super {
+  @pragma("vm:entry-point")
   var y = 3;
+  @pragma("vm:entry-point")
   var x = 4;
 }
 
diff --git a/runtime/observatory/tests/service/object_graph_vm_test.dart b/runtime/observatory/tests/service/object_graph_vm_test.dart
index 669d096..b29ada5 100644
--- a/runtime/observatory/tests/service/object_graph_vm_test.dart
+++ b/runtime/observatory/tests/service/object_graph_vm_test.dart
@@ -9,7 +9,10 @@
 import 'test_helper.dart';
 
 class Foo {
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
   dynamic left;
+  @pragma("vm:entry-point")
   dynamic right;
 }
 
diff --git a/runtime/observatory/tests/service/reachable_size_test.dart b/runtime/observatory/tests/service/reachable_size_test.dart
index 800ebb2..c22b35f 100644
--- a/runtime/observatory/tests/service/reachable_size_test.dart
+++ b/runtime/observatory/tests/service/reachable_size_test.dart
@@ -9,7 +9,11 @@
 import 'service_test_common.dart';
 
 class Pair {
-  var x, y;
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
 }
 
 var p1;
diff --git a/runtime/observatory/tests/service/regexp_function_test.dart b/runtime/observatory/tests/service/regexp_function_test.dart
index 6fb09bc..c16ee1b 100644
--- a/runtime/observatory/tests/service/regexp_function_test.dart
+++ b/runtime/observatory/tests/service/regexp_function_test.dart
@@ -8,7 +8,10 @@
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
 
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
 var regex0;
+@pragma("vm:entry-point")
 var regex;
 
 void script() {
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index 9d23a87..0f1ff19 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -11,7 +11,12 @@
 
 import 'use_flag_test_helper.dart';
 
-test({String dillPath, bool useAsm, bool stripFlag, bool stripUtil}) async {
+test(
+    {String dillPath,
+    bool useAsm,
+    bool useBare,
+    bool stripFlag,
+    bool stripUtil}) async {
   // The assembler may add extra unnecessary information to the compiled
   // snapshot whether or not we generate DWARF information in the assembly, so
   // we force the use of a utility when generating assembly.
@@ -23,6 +28,7 @@
 
   final tempDirPrefix = 'v8-snapshot-profile' +
       (useAsm ? '-assembly' : '-elf') +
+      (useBare ? '-bare' : '-nonbare') +
       (stripFlag ? '-intstrip' : '') +
       (stripUtil ? '-extstrip' : '');
 
@@ -32,6 +38,7 @@
     final snapshotPath = path.join(tempDir, 'test.snap');
     final commonSnapshotArgs = [
       if (stripFlag) '--strip',
+      useBare ? '--use-bare-instructions' : '--no-use-bare-instructions',
       "--write-v8-snapshot-profile-to=$profilePath",
       dillPath,
     ];
@@ -71,7 +78,7 @@
     // graph (in some cases the shallow size can legitimately be 0, e.g. for
     // "base objects").
     for (final int node in profile.nodes) {
-      Expect.notEquals(profile[node].type, "Unknown",
+      Expect.notEquals("Unknown", profile[node].type,
           "unknown node at ID ${profile[node].id}");
     }
 
@@ -89,6 +96,7 @@
     final actual = await File(strippedPath).length();
     final expected = profile.accountedBytes;
 
+    final bareUsed = useBare ? "bare" : "non-bare";
     final fileType = useAsm ? "assembly" : "ELF";
     String stripPrefix = "";
     if (stripFlag && stripUtil) {
@@ -100,7 +108,7 @@
     }
 
     Expect.approxEquals(expected, actual, 0.03 * actual,
-        "failed on $stripPrefix$fileType snapshot type.");
+        "failed on $bareUsed $stripPrefix$fileType snapshot type.");
   });
 }
 
@@ -214,7 +222,17 @@
 
     // Test stripped ELF generation directly.
     await test(
-        dillPath: dillPath, stripFlag: true, stripUtil: false, useAsm: false);
+        dillPath: dillPath,
+        stripFlag: true,
+        stripUtil: false,
+        useAsm: false,
+        useBare: false);
+    await test(
+        dillPath: dillPath,
+        stripFlag: true,
+        stripUtil: false,
+        useAsm: false,
+        useBare: true);
 
     // We neither generate assembly nor have a stripping utility on Windows.
     if (Platform.isWindows) {
@@ -228,7 +246,17 @@
     } else {
       // Test unstripped ELF generation that is then stripped externally.
       await test(
-          dillPath: dillPath, stripFlag: false, stripUtil: true, useAsm: false);
+          dillPath: dillPath,
+          stripFlag: false,
+          stripUtil: true,
+          useAsm: false,
+          useBare: false);
+      await test(
+          dillPath: dillPath,
+          stripFlag: false,
+          stripUtil: true,
+          useAsm: false,
+          useBare: true);
     }
 
     // TODO(sstrickl): Currently we can't assemble for SIMARM64 on MacOSX.
@@ -241,9 +269,29 @@
 
     // Test stripped assembly generation that is then compiled and stripped.
     await test(
-        dillPath: dillPath, stripFlag: true, stripUtil: true, useAsm: true);
+        dillPath: dillPath,
+        stripFlag: true,
+        stripUtil: true,
+        useAsm: true,
+        useBare: false);
+    await test(
+        dillPath: dillPath,
+        stripFlag: true,
+        stripUtil: true,
+        useAsm: true,
+        useBare: true);
     // Test unstripped assembly generation that is then compiled and stripped.
     await test(
-        dillPath: dillPath, stripFlag: false, stripUtil: true, useAsm: true);
+        dillPath: dillPath,
+        stripFlag: false,
+        stripUtil: true,
+        useAsm: true,
+        useBare: false);
+    await test(
+        dillPath: dillPath,
+        stripFlag: false,
+        stripUtil: true,
+        useAsm: true,
+        useBare: true);
   });
 }
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index 6770834..6a4fcdb 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,7 +14,7 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.86';
+const String version = '1.87';
 
 // Restriction on statements and expressions.
 const int stmtDepth = 1;
diff --git a/runtime/tools/dartfuzz/dartfuzz_api_table.dart b/runtime/tools/dartfuzz/dartfuzz_api_table.dart
index c73535a..b002073 100644
--- a/runtime/tools/dartfuzz/dartfuzz_api_table.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_api_table.dart
@@ -1067,7 +1067,6 @@
     DartLib('toString', [DartType.MAPENTRY_INT_STRING, DartType.VOID], true),
     DartLib('toString', [DartType.NULL, DartType.VOID], true),
     DartLib('toString', [DartType.NULLTHROWNERROR, DartType.VOID], true),
-    DartLib('toString', [DartType.OUTOFMEMORYERROR, DartType.VOID], true),
     DartLib('toString', [DartType.STACKOVERFLOWERROR, DartType.VOID], true),
     DartLib('toString', [DartType.STATEERROR, DartType.VOID], true),
     DartLib('toString', [DartType.STRINGBUFFER, DartType.VOID], true),
diff --git a/runtime/tools/dartfuzz/dartfuzz_type_table.dart b/runtime/tools/dartfuzz/dartfuzz_type_table.dart
index 6e15099..f644f94 100644
--- a/runtime/tools/dartfuzz/dartfuzz_type_table.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_type_table.dart
@@ -190,7 +190,6 @@
   static const STATEERROR = const DartType._withName("StateError");
   static const CONCURRENTMODIFICATIONERROR =
       const DartType._withName("ConcurrentModificationError");
-  static const OUTOFMEMORYERROR = const DartType._withName("OutOfMemoryError");
   static const STACKOVERFLOWERROR =
       const DartType._withName("StackOverflowError");
   static const CYCLICINITIALIZATIONERROR =
@@ -11341,7 +11340,6 @@
     UNIMPLEMENTEDERROR,
     STATEERROR,
     CONCURRENTMODIFICATIONERROR,
-    OUTOFMEMORYERROR,
     STACKOVERFLOWERROR,
     CYCLICINITIALIZATIONERROR,
     EXCEPTION,
@@ -43735,7 +43733,6 @@
       FALLTHROUGHERROR,
       INDEXERROR,
       NULLTHROWNERROR,
-      OUTOFMEMORYERROR,
       RANGEERROR,
       STACKOVERFLOWERROR,
       STATEERROR,
@@ -48644,7 +48641,6 @@
       NULL,
       NULLTHROWNERROR,
       NUM,
-      OUTOFMEMORYERROR,
       PROVISIONAL,
       RANGEERROR,
       REGEXP,
@@ -63023,9 +63019,6 @@
     NULLTHROWNERROR: {
       '': [],
     },
-    OUTOFMEMORYERROR: {
-      '': [],
-    },
     PROVISIONAL: {
       '': [],
     },
@@ -102567,14 +102560,6 @@
         NUM,
       },
     },
-    OUTOFMEMORYERROR: {
-      '=': {
-        OUTOFMEMORYERROR,
-      },
-      '??=': {
-        OUTOFMEMORYERROR,
-      },
-    },
     PROVISIONAL: {
       '=': {
         PROVISIONAL,
@@ -103277,7 +103262,6 @@
     DartType.UNIMPLEMENTEDERROR,
     DartType.STATEERROR,
     DartType.CONCURRENTMODIFICATIONERROR,
-    DartType.OUTOFMEMORYERROR,
     DartType.STACKOVERFLOWERROR,
     DartType.CYCLICINITIALIZATIONERROR,
     DartType.EXCEPTION,
@@ -113732,7 +113716,6 @@
       DartType.FALLTHROUGHERROR,
       DartType.INDEXERROR,
       DartType.NULLTHROWNERROR,
-      DartType.OUTOFMEMORYERROR,
       DartType.RANGEERROR,
       DartType.STACKOVERFLOWERROR,
       DartType.STATEERROR,
@@ -115732,7 +115715,6 @@
       DartType.NULL,
       DartType.NULLTHROWNERROR,
       DartType.NUM,
-      DartType.OUTOFMEMORYERROR,
       DartType.PROVISIONAL,
       DartType.RANGEERROR,
       DartType.REGEXP,
@@ -121514,9 +121496,6 @@
     DartType.NULLTHROWNERROR: {
       '': [],
     },
-    DartType.OUTOFMEMORYERROR: {
-      '': [],
-    },
     DartType.PROVISIONAL: {
       '': [],
     },
@@ -137734,14 +137713,6 @@
         DartType.NUM,
       },
     },
-    DartType.OUTOFMEMORYERROR: {
-      '=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-      '??=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-    },
     DartType.PROVISIONAL: {
       '=': {
         DartType.PROVISIONAL,
@@ -138307,7 +138278,6 @@
     DartType.UNIMPLEMENTEDERROR,
     DartType.STATEERROR,
     DartType.CONCURRENTMODIFICATIONERROR,
-    DartType.OUTOFMEMORYERROR,
     DartType.STACKOVERFLOWERROR,
     DartType.CYCLICINITIALIZATIONERROR,
     DartType.EXCEPTION,
@@ -138871,7 +138841,6 @@
       DartType.FALLTHROUGHERROR,
       DartType.INDEXERROR,
       DartType.NULLTHROWNERROR,
-      DartType.OUTOFMEMORYERROR,
       DartType.RANGEERROR,
       DartType.STACKOVERFLOWERROR,
       DartType.STATEERROR,
@@ -139028,7 +138997,6 @@
       DartType.NULL,
       DartType.NULLTHROWNERROR,
       DartType.NUM,
-      DartType.OUTOFMEMORYERROR,
       DartType.PROVISIONAL,
       DartType.RANGEERROR,
       DartType.REGEXP,
@@ -139415,9 +139383,6 @@
     DartType.NULLTHROWNERROR: {
       '': [],
     },
-    DartType.OUTOFMEMORYERROR: {
-      '': [],
-    },
     DartType.PROVISIONAL: {
       '': [],
     },
@@ -140723,14 +140688,6 @@
         DartType.NUM,
       },
     },
-    DartType.OUTOFMEMORYERROR: {
-      '=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-      '??=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-    },
     DartType.PROVISIONAL: {
       '=': {
         DartType.PROVISIONAL,
@@ -141081,7 +141038,6 @@
     DartType.UNIMPLEMENTEDERROR,
     DartType.STATEERROR,
     DartType.CONCURRENTMODIFICATIONERROR,
-    DartType.OUTOFMEMORYERROR,
     DartType.STACKOVERFLOWERROR,
     DartType.CYCLICINITIALIZATIONERROR,
     DartType.EXCEPTION,
@@ -141491,7 +141447,6 @@
       DartType.FALLTHROUGHERROR,
       DartType.INDEXERROR,
       DartType.NULLTHROWNERROR,
-      DartType.OUTOFMEMORYERROR,
       DartType.RANGEERROR,
       DartType.STACKOVERFLOWERROR,
       DartType.STATEERROR,
@@ -141601,7 +141556,6 @@
       DartType.NULL,
       DartType.NULLTHROWNERROR,
       DartType.NUM,
-      DartType.OUTOFMEMORYERROR,
       DartType.PROVISIONAL,
       DartType.RANGEERROR,
       DartType.REGEXP,
@@ -141875,9 +141829,6 @@
     DartType.NULLTHROWNERROR: {
       '': [],
     },
-    DartType.OUTOFMEMORYERROR: {
-      '': [],
-    },
     DartType.PROVISIONAL: {
       '': [],
     },
@@ -142840,14 +142791,6 @@
         DartType.NUM,
       },
     },
-    DartType.OUTOFMEMORYERROR: {
-      '=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-      '??=': {
-        DartType.OUTOFMEMORYERROR,
-      },
-    },
     DartType.PROVISIONAL: {
       '=': {
         DartType.PROVISIONAL,
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 581dd8a..9969291 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -84,7 +84,6 @@
 const nullEncoding = 'DartType.NULL';
 const nullThrownErrorEncoding = 'DartType.NULLTHROWNERROR';
 const numEncoding = 'DartType.NUM';
-const outOfMemoryErrorEncoding = 'DartType.OUTOFMEMORYERROR';
 const provisionalEncoding = 'DartType.PROVISIONAL';
 const rangeErrorEncoding = 'DartType.RANGEERROR';
 const regExpEncoding = 'DartType.REGEXP';
@@ -146,7 +145,6 @@
 final nullLibs = 'nullLibs';
 final nullThrownErrorLibs = 'nullThrownErrorLibs';
 final numLibs = 'numLibs';
-final outOfMemoryErrorLibs = 'outOfMemoryErrorLibs';
 final provisionalLibs = 'provisionalLibs';
 final rangeErrorLibs = 'rangeErrorLibs';
 final regExpLibs = 'regExpLibs';
@@ -208,7 +206,6 @@
   nullEncoding: nullLibs,
   nullThrownErrorEncoding: nullThrownErrorLibs,
   numEncoding: numLibs,
-  outOfMemoryErrorEncoding: outOfMemoryErrorLibs,
   provisionalEncoding: provisionalLibs,
   rangeErrorEncoding: rangeErrorLibs,
   regExpEncoding: regExpLibs,
@@ -273,7 +270,6 @@
   nullEncoding: <DartLib>[],
   nullThrownErrorEncoding: <DartLib>[],
   numEncoding: <DartLib>[],
-  outOfMemoryErrorEncoding: <DartLib>[],
   provisionalEncoding: <DartLib>[],
   rangeErrorEncoding: <DartLib>[],
   regExpEncoding: <DartLib>[],
@@ -538,8 +534,6 @@
       return nullEncoding;
     case 'NullThrownError':
       return nullThrownErrorEncoding;
-    case 'OutOfMemoryError':
-      return outOfMemoryErrorEncoding;
     case 'Provisional':
       return provisionalEncoding;
     case 'RangeError':
diff --git a/runtime/tools/dartfuzz/gen_type_table.dart b/runtime/tools/dartfuzz/gen_type_table.dart
index 0dfae17..f6d0249 100644
--- a/runtime/tools/dartfuzz/gen_type_table.dart
+++ b/runtime/tools/dartfuzz/gen_type_table.dart
@@ -1323,7 +1323,8 @@
           (classElement.name == 'Comparable') ||
           (classElement.name == 'BidirectionalIterator') ||
           (classElement.name == 'Iterator') ||
-          (classElement.name == 'Stopwatch')) {
+          (classElement.name == 'Stopwatch') ||
+          (classElement.name == 'OutOfMemoryError')) {
         continue;
       }
       allTypes.add(classElement.thisType);
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 281c35d..52f8ef7 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -28,6 +28,7 @@
   V(Code)                                                                      \
   V(Bytecode)                                                                  \
   V(Instructions)                                                              \
+  V(InstructionsSection)                                                       \
   V(ObjectPool)                                                                \
   V(PcDescriptors)                                                             \
   V(CodeSourceMap)                                                             \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 4cb654f..aad57c1 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1509,15 +1509,16 @@
         s->UnexpectedObject(code, "Disabled code");
       }
 
-      s->WriteInstructions(code->ptr()->instructions_, code);
-      s->WriteUnsigned(code->ptr()->unchecked_offset_);
+      s->WriteInstructions(code->ptr()->instructions_,
+                           code->ptr()->unchecked_offset_, code, i);
       if (kind == Snapshot::kFullJIT) {
         // TODO(rmacnak): Fix references to disabled code before serializing.
         // For now, we may write the FixCallersTarget or equivalent stub. This
         // will cause a fixup if this code is called.
-        s->WriteInstructions(code->ptr()->active_instructions_, code);
-        s->WriteUnsigned(code->ptr()->unchecked_entry_point_ -
-                         code->ptr()->entry_point_);
+        const uint32_t active_unchecked_offset =
+            code->ptr()->unchecked_entry_point_ - code->ptr()->entry_point_;
+        s->WriteInstructions(code->ptr()->active_instructions_,
+                             active_unchecked_offset, code, i);
       }
 
       WriteField(code, object_pool_);
@@ -1598,24 +1599,10 @@
 
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
-      RawCode* code = reinterpret_cast<RawCode*>(d->Ref(id));
+      auto const code = reinterpret_cast<RawCode*>(d->Ref(id));
       Deserializer::InitializeHeader(code, kCodeCid, Code::InstanceSize(0));
 
-      RawInstructions* instr = d->ReadInstructions();
-      uint32_t unchecked_offset = d->ReadUnsigned();
-
-      code->ptr()->instructions_ = instr;
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-      code->ptr()->unchecked_offset_ = unchecked_offset;
-      if (d->kind() == Snapshot::kFullJIT) {
-        instr = d->ReadInstructions();
-        unchecked_offset = d->ReadUnsigned();
-      }
-      code->ptr()->active_instructions_ = instr;
-#endif  // !DART_PRECOMPILED_RUNTIME
-
-      Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
+      d->ReadInstructions(code, id, start_index_);
 
       code->ptr()->object_pool_ =
           reinterpret_cast<RawObjectPool*>(d->ReadRef());
@@ -4485,6 +4472,10 @@
       current_parent_(Object::null()),
       parent_pairs_()
 #endif
+#if defined(DART_PRECOMPILER)
+      ,
+      deduped_instructions_sources_(zone_)
+#endif
 {
   num_cids_ = thread->isolate()->class_table()->NumCids();
   clusters_by_cid_ = new SerializationCluster*[num_cids_];
@@ -4675,7 +4666,10 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-void Serializer::WriteInstructions(RawInstructions* instr, RawCode* code) {
+void Serializer::WriteInstructions(RawInstructions* instr,
+                                   uint32_t unchecked_offset,
+                                   RawCode* code,
+                                   intptr_t index) {
   ASSERT(code != Code::null());
 
   const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
@@ -4683,7 +4677,6 @@
     // Code should have been removed by DropCodeWithoutReusableInstructions.
     UnexpectedObject(code, "Expected instructions to reuse");
   }
-  Write<uint32_t>(offset);
 
   // If offset < 0, it's pointing to a shared instruction. We don't profile
   // references to shared text/data (since they don't consume any space). Of
@@ -4701,6 +4694,41 @@
         from_object, {to_object, V8SnapshotProfileWriter::Reference::kProperty,
                       profile_writer_->EnsureString("<instructions>")});
   }
+
+#if defined(DART_PRECOMPILER)
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    static_assert(
+        ImageWriter::kBareInstructionsAlignment > 1,
+        "Bare instruction payloads are not aligned on even byte boundaries");
+    ASSERT((offset & 0x1) == 0);
+    // Since instructions are aligned on even byte boundaries, we can use the
+    // low bit as a flag for whether the first uint32_t read is an offset
+    // followed by the unchecked_offset + mono entry bit (when 0) or a reference
+    // to another code object (when 1).
+    if (deduped_instructions_sources_.HasKey(offset)) {
+      ASSERT(FLAG_dedup_instructions);
+      Write<uint32_t>(deduped_instructions_sources_.LookupValue(offset));
+      return;
+    }
+    Write<uint32_t>(offset);
+    // When writing only instruction payloads, we also need to serialize
+    // whether there was a single entry. We append this as the low order bit
+    // in the unchecked_offset.
+    ASSERT(Utils::IsUint(31, unchecked_offset));
+    const uint32_t payload_info =
+        (unchecked_offset << 1) | (Code::HasMonomorphicEntry(code) ? 0x1 : 0x0);
+    WriteUnsigned(payload_info);
+    // Store the index with an added set low bit (e.g., the form it should take
+    // if used in serializing later Code objects). This also avoids storing a 0
+    // in the IntMap when sharing instructions with the first code object (as
+    // that is IntMap's current kNoValue).
+    ASSERT(Utils::IsUint(31, index));
+    deduped_instructions_sources_.Insert(offset, (index << 1) | 0x1);
+    return;
+  }
+#endif
+  Write<uint32_t>(offset);
+  WriteUnsigned(unchecked_offset);
 }
 
 void Serializer::TraceDataOffset(uint32_t offset) {
@@ -5007,6 +5035,7 @@
   AddBaseObject(Object::zero_array().raw(), "Array", "<zero_array>");
   AddBaseObject(Object::dynamic_type().raw(), "Type", "<dynamic type>");
   AddBaseObject(Object::void_type().raw(), "Type", "<void type>");
+  AddBaseObject(Object::never_type().raw(), "Type", "<never type>");
   AddBaseObject(Object::empty_type_arguments().raw(), "TypeArguments", "[]");
   AddBaseObject(Bool::True().raw(), "bool", "true");
   AddBaseObject(Bool::False().raw(), "bool", "false");
@@ -5423,9 +5452,96 @@
   return ApiError::New(msg, Heap::kOld);
 }
 
-RawInstructions* Deserializer::ReadInstructions() {
-  uint32_t offset = Read<uint32_t>();
-  return image_reader_->GetInstructionsAt(offset);
+void Deserializer::ReadInstructions(RawCode* code,
+                                    intptr_t index,
+                                    intptr_t start_index) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (FLAG_use_bare_instructions) {
+    // There are no serialized RawInstructions objects in this mode.
+    code->ptr()->instructions_ = Instructions::null();
+
+    const uint32_t bare_offset = Read<uint32_t>();
+    if ((bare_offset & 0x1) == 0x1) {
+      // The low bit being set marks this as a reference to an earlier Code
+      // object in the cluster that shared the same deduplicated Instructions
+      // object. Thus, retrieve the instructions-related information from there.
+      ASSERT((index - start_index) >= code_order_length());
+      const uint32_t source_id = (bare_offset >> 1) + start_index;
+      auto const source = reinterpret_cast<RawCode*>(Ref(source_id));
+      code->ptr()->entry_point_ = source->ptr()->entry_point_;
+      code->ptr()->unchecked_entry_point_ =
+          source->ptr()->unchecked_entry_point_;
+      code->ptr()->monomorphic_entry_point_ =
+          source->ptr()->monomorphic_entry_point_;
+      code->ptr()->monomorphic_unchecked_entry_point_ =
+          source->ptr()->monomorphic_unchecked_entry_point_;
+      code->ptr()->instructions_length_ = source->ptr()->instructions_length_;
+      return;
+    }
+    const uword payload_start =
+        image_reader_->GetBareInstructionsAt(bare_offset);
+    const uint32_t payload_info = ReadUnsigned();
+    const uint32_t unchecked_offset = payload_info >> 1;
+    const bool has_monomorphic_entrypoint = (payload_info & 0x1) == 0x1;
+
+    const uword entry_offset = has_monomorphic_entrypoint
+                                   ? Instructions::kPolymorphicEntryOffsetAOT
+                                   : 0;
+    const uword monomorphic_entry_offset =
+        has_monomorphic_entrypoint ? Instructions::kMonomorphicEntryOffsetAOT
+                                   : 0;
+
+    const uword entry_point = payload_start + entry_offset;
+    const uword monomorphic_entry_point =
+        payload_start + monomorphic_entry_offset;
+
+    code->ptr()->entry_point_ = entry_point;
+    code->ptr()->unchecked_entry_point_ = entry_point + unchecked_offset;
+    code->ptr()->monomorphic_entry_point_ = monomorphic_entry_point;
+    code->ptr()->monomorphic_unchecked_entry_point_ =
+        monomorphic_entry_point + unchecked_offset;
+
+    // We don't serialize the length of the instructions payload. Instead, we
+    // calculate an approximate length (may include padding) by subtracting the
+    // payload start of the next Code object (if any) from the start for this
+    // one. Thus, here we patch the instructions length for the previous Code
+    // object, if any.
+    ASSERT((index - start_index) < code_order_length());
+    const uword curr_payload_start = Code::PayloadStartOf(code);
+    if (index > start_index) {
+      auto const prev = reinterpret_cast<RawCode*>(Ref(index - 1));
+      const uword prev_payload_start = Code::PayloadStartOf(prev);
+      prev->ptr()->instructions_length_ =
+          curr_payload_start - prev_payload_start;
+    }
+    // For the last Code object whose Instructions were written to the
+    // instructions image, assume its payload extends to the image's end.
+    if ((index - start_index) == code_order_length() - 1) {
+      code->ptr()->instructions_length_ =
+          image_reader_->GetBareInstructionsEnd() - curr_payload_start;
+    }
+
+    return;
+  }
+#endif
+
+  const uint32_t offset = Read<uint32_t>();
+  RawInstructions* instr = image_reader_->GetInstructionsAt(offset);
+  uint32_t unchecked_offset = ReadUnsigned();
+
+  code->ptr()->instructions_ = instr;
+#if defined(DART_PRECOMPILED_RUNTIME)
+  code->ptr()->instructions_length_ = Instructions::Size(instr);
+#else
+  code->ptr()->unchecked_offset_ = unchecked_offset;
+  if (kind() == Snapshot::kFullJIT) {
+    const uint32_t active_offset = Read<uint32_t>();
+    instr = image_reader_->GetInstructionsAt(active_offset);
+    unchecked_offset = ReadUnsigned();
+  }
+  code->ptr()->active_instructions_ = instr;
+#endif
+  Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
 }
 
 RawObject* Deserializer::GetObjectAt(uint32_t offset) const {
@@ -5498,6 +5614,7 @@
   AddBaseObject(Object::zero_array().raw());
   AddBaseObject(Object::dynamic_type().raw());
   AddBaseObject(Object::void_type().raw());
+  AddBaseObject(Object::never_type().raw());
   AddBaseObject(Object::empty_type_arguments().raw());
   AddBaseObject(Bool::True().raw());
   AddBaseObject(Bool::False().raw());
@@ -5842,19 +5959,72 @@
     if (end == nullptr) {
       end = features + features_length;
     }
-#define CHECK_FLAG(name, flag)                                                 \
+
+#define SET_FLAG(name)                                                         \
   if (strncmp(cursor, #name, end - cursor) == 0) {                             \
-    flag = true;                                                               \
+    FLAG_##name = true;                                                        \
     cursor = end;                                                              \
     continue;                                                                  \
   }                                                                            \
   if (strncmp(cursor, "no-" #name, end - cursor) == 0) {                       \
-    flag = false;                                                              \
+    FLAG_##name = false;                                                       \
     cursor = end;                                                              \
     continue;                                                                  \
   }
-    VM_GLOBAL_FLAG_LIST(CHECK_FLAG)
+
+#define CHECK_FLAG(name, mode)                                                 \
+  if (strncmp(cursor, #name, end - cursor) == 0) {                             \
+    if (!FLAG_##name) {                                                        \
+      return header_reader.BuildError("Flag " #name                            \
+                                      " is true in snapshot, "                 \
+                                      "but " #name                             \
+                                      " is always false in " mode);            \
+    }                                                                          \
+    cursor = end;                                                              \
+    continue;                                                                  \
+  }                                                                            \
+  if (strncmp(cursor, "no-" #name, end - cursor) == 0) {                       \
+    if (FLAG_##name) {                                                         \
+      return header_reader.BuildError("Flag " #name                            \
+                                      " is false in snapshot, "                \
+                                      "but " #name                             \
+                                      " is always true in " mode);             \
+    }                                                                          \
+    cursor = end;                                                              \
+    continue;                                                                  \
+  }
+
+#define SET_P(name, T, DV, C) SET_FLAG(name)
+
+#if defined(PRODUCT)
+#define SET_OR_CHECK_R(name, PV, T, DV, C) CHECK_FLAG(name, "product mode")
+#else
+#define SET_OR_CHECK_R(name, PV, T, DV, C) SET_FLAG(name)
+#endif
+
+#if defined(PRODUCT)
+#define SET_OR_CHECK_C(name, PCV, PV, T, DV, C) CHECK_FLAG(name, "product mode")
+#elif defined(DART_PRECOMPILED_RUNTIME)
+#define SET_OR_CHECK_C(name, PCV, PV, T, DV, C)                                \
+  CHECK_FLAG(name, "the precompiled runtime")
+#else
+#define SET_OR_CHECK_C(name, PV, T, DV, C) SET_FLAG(name)
+#endif
+
+#if !defined(DEBUG)
+#define SET_OR_CHECK_D(name, T, DV, C) CHECK_FLAG(name, "non-debug mode")
+#else
+#define SET_OR_CHECK_D(name, T, DV, C) SET_FLAG(name)
+#endif
+
+    VM_GLOBAL_FLAG_LIST(SET_P, SET_OR_CHECK_R, SET_OR_CHECK_C, SET_OR_CHECK_D)
+
+#undef SET_OR_CHECK_D
+#undef SET_OR_CHECK_C
+#undef SET_OR_CHECK_R
+#undef SET_P
 #undef CHECK_FLAG
+#undef SET_FLAG
 
     cursor = end;
   }
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 15d53f7..919ee4b 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -358,7 +358,10 @@
     Write<int32_t>(cid);
   }
 
-  void WriteInstructions(RawInstructions* instr, RawCode* code);
+  void WriteInstructions(RawInstructions* instr,
+                         uint32_t unchecked_offset,
+                         RawCode* code,
+                         intptr_t index);
   uint32_t GetDataOffset(RawObject* object) const;
   void TraceDataOffset(uint32_t offset);
   intptr_t GetDataSize() const;
@@ -403,6 +406,10 @@
   GrowableArray<Object*> parent_pairs_;
 #endif
 
+#if defined(DART_PRECOMPILER)
+  IntMap<intptr_t> deduped_instructions_sources_;
+#endif
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer);
 };
 
@@ -559,7 +566,7 @@
     return Read<int32_t>();
   }
 
-  RawInstructions* ReadInstructions();
+  void ReadInstructions(RawCode* code, intptr_t index, intptr_t start_index);
   RawObject* GetObjectAt(uint32_t offset) const;
 
   void SkipHeader() { stream_.SetPosition(Snapshot::kHeaderSize); }
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index a2718c2..7dffac5 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1378,9 +1378,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
       functions = cls.functions();
       for (intptr_t j = 0; j < functions.Length(); j++) {
         function ^= functions.At(j);
@@ -1458,10 +1455,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-
       functions = cls.functions();
       for (intptr_t j = 0; j < functions.Length(); j++) {
         function ^= functions.At(j);
@@ -1517,10 +1510,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-
       functions = cls.functions();
       retained_functions = GrowableObjectArray::New();
       for (intptr_t j = 0; j < functions.Length(); j++) {
@@ -1581,10 +1570,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-
       fields = cls.fields();
       retained_fields = GrowableObjectArray::New();
       for (intptr_t j = 0; j < fields.Length(); j++) {
@@ -1780,9 +1765,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
 
       // The subclasses/implementors array is only needed for CHA.
       cls.ClearDirectSubclasses();
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 96ed82e..07252ce 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -303,7 +303,7 @@
   explicit AssemblerBase(ObjectPoolBuilder* object_pool_builder)
       : StackResource(ThreadState::Current()),
         prologue_offset_(-1),
-        has_single_entry_point_(true),
+        has_monomorphic_entry_(false),
         object_pool_builder_(object_pool_builder) {}
   virtual ~AssemblerBase();
 
@@ -315,7 +315,7 @@
   ObjectPoolBuilder& object_pool_builder() { return *object_pool_builder_; }
 
   intptr_t prologue_offset() const { return prologue_offset_; }
-  bool has_single_entry_point() const { return has_single_entry_point_; }
+  bool has_monomorphic_entry() const { return has_monomorphic_entry_; }
 
   void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
   static bool EmittingComments();
@@ -370,7 +370,7 @@
  protected:
   AssemblerBuffer buffer_;  // Contains position independent code.
   int32_t prologue_offset_;
-  bool has_single_entry_point_;
+  bool has_monomorphic_entry_;
 
   intptr_t unchecked_entry_offset_ = 0;
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index b14b8d9..961706a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3164,6 +3164,7 @@
                              Register rn,
                              int32_t value,
                              Condition cond) {
+  ASSERT(value != kMinInt32);  // Cannot be negated.
   AddImmediate(rd, rn, -value, cond);
 }
 
@@ -3171,27 +3172,8 @@
                                      Register rn,
                                      int32_t value,
                                      Condition cond) {
-  Operand o;
-  if (Operand::CanHold(value, &o)) {
-    // Handles value == kMinInt32.
-    subs(rd, rn, o, cond);
-  } else if (Operand::CanHold(-value, &o)) {
-    ASSERT(value != kMinInt32);  // Would cause erroneous overflow detection.
-    adds(rd, rn, o, cond);
-  } else {
-    ASSERT(rn != IP);
-    if (Operand::CanHold(~value, &o)) {
-      mvn(IP, o, cond);
-      subs(rd, rn, Operand(IP), cond);
-    } else if (Operand::CanHold(~(-value), &o)) {
-      ASSERT(value != kMinInt32);  // Would cause erroneous overflow detection.
-      mvn(IP, o, cond);
-      adds(rd, rn, Operand(IP), cond);
-    } else {
-      LoadDecodableImmediate(IP, value, cond);
-      subs(rd, rn, Operand(IP), cond);
-    }
-  }
+  ASSERT(value != kMinInt32);  // Cannot be negated.
+  AddImmediateSetFlags(rd, rn, -value, cond);
 }
 
 void Assembler::AndImmediate(Register rd,
@@ -3444,7 +3426,7 @@
 // R0 receiver, R9 ICData entries array
 // Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryJIT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
 #if defined(TESTING) || defined(DEBUG)
   bool saved_use_far_branches = use_far_branches();
   set_use_far_branches(false);
@@ -3480,7 +3462,7 @@
 // R0 receiver, R9 guarded cid as Smi.
 // Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryAOT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
 #if defined(TESTING) || defined(DEBUG)
   bool saved_use_far_branches = use_far_branches();
   set_use_far_branches(false);
@@ -3505,7 +3487,7 @@
 }
 
 void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
     bkpt(0);
   }
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 600bf63..c62fc4a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1552,7 +1552,7 @@
 // R0 receiver, R5 ICData entries array
 // Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryJIT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   const bool saved_use_far_branches = use_far_branches();
   set_use_far_branches(false);
   const intptr_t start = CodeSize();
@@ -1589,7 +1589,7 @@
 // R0 receiver, R5 guarded cid as Smi.
 // Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryAOT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   bool saved_use_far_branches = use_far_branches();
   set_use_far_branches(false);
 
@@ -1615,7 +1615,7 @@
 }
 
 void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
     brk(0);
   }
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index d9e2ae6..00f2bd7 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2123,7 +2123,7 @@
 // EBX receiver, ECX ICData entries array
 // Preserve EDX (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryJIT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
@@ -2162,7 +2162,7 @@
 }
 
 void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
     int3();
   }
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 0b02b8e..137aba2 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1801,7 +1801,7 @@
 // RDX receiver, RBX ICData entries array
 // Preserve R10 (ARGS_DESC_REG), not required today, but maybe later.
 void Assembler::MonomorphicCheckedEntryJIT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
@@ -1834,7 +1834,7 @@
 }
 
 void Assembler::MonomorphicCheckedEntryAOT() {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   intptr_t start = CodeSize();
   Label have_cid, miss;
   Bind(&miss);
@@ -1865,7 +1865,7 @@
 }
 
 void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
-  has_single_entry_point_ = false;
+  has_monomorphic_entry_ = true;
   while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
     int3();
   }
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index 9564a41..36f8cae 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -258,8 +258,7 @@
       PcDescriptors::Handle(zone, code.pc_descriptors());
   THR_Print("%s}\n", descriptors.ToCString());
 
-  const auto& instructions = Instructions::Handle(code.instructions());
-  const uword start = instructions.PayloadStart();
+  const uword start = code.PayloadStart();
   const uword base = FLAG_disassemble_relative ? 0 : start;
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
index 78bb0c1..11c7973 100644
--- a/runtime/vm/compiler/backend/compile_type.h
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -84,11 +84,7 @@
 
   // Return true if value of this type is assignable to a location of the
   // given type.
-  bool IsAssignableTo(NNBDMode mode, const AbstractType& type) {
-    bool is_instance;
-    return CanComputeIsInstanceOf(mode, type, kNullable, &is_instance) &&
-           is_instance;
-  }
+  bool IsAssignableTo(NNBDMode mode, const AbstractType& type);
 
   // Create a new CompileType representing given combination of class id and
   // abstract type. The pair is assumed to be coherent.
@@ -188,6 +184,9 @@
   // Return true if value of this type is a non-nullable double.
   bool IsDouble() { return !is_nullable() && IsNullableDouble(); }
 
+  // Return true if value of this type is a non-nullable double.
+  bool IsBool() { return !is_nullable() && IsNullableBool(); }
+
   // Return true if value of this type is either int or null.
   bool IsNullableInt() {
     if (cid_ == kSmiCid || cid_ == kMintCid) {
@@ -222,6 +221,17 @@
     return false;
   }
 
+  // Return true if value of this type is either double or null.
+  bool IsNullableBool() {
+    if (cid_ == kBoolCid) {
+      return true;
+    }
+    if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
+      return type_ != nullptr && compiler::IsBoolType(*type_);
+    }
+    return false;
+  }
+
   bool Specialize(GrowableArray<intptr_t>* class_ids);
 
   bool IsNotSmi();
@@ -243,11 +253,6 @@
   Definition* owner() const { return owner_; }
 
  private:
-  bool CanComputeIsInstanceOf(NNBDMode mode,
-                              const AbstractType& type,
-                              bool is_nullable,
-                              bool* is_instance);
-
   bool is_nullable_;
   classid_t cid_;
   const AbstractType* type_;
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index fb02b0b..a188fe8 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -804,7 +804,7 @@
   const Object& value = def->constant_value();
   const AbstractType& checked_type = instr->type();
   // If the checked type is a top type, the result is always true.
-  if (checked_type.IsTopType(instr->nnbd_mode())) {
+  if (checked_type.IsTopType()) {
     SetValue(instr, Bool::True());
   } else if (IsNonConstant(value)) {
     intptr_t value_cid = instr->value()->definition()->Type()->ToCid();
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index ef9fa48..6d11d0c 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1680,8 +1680,9 @@
     const intptr_t deopt_id = (deopt_target != NULL)
                                   ? deopt_target->DeoptimizationTarget()
                                   : DeoptId::kNone;
-    converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id,
-                                   use->instruction()->speculative_mode());
+    converted = UnboxInstr::Create(
+        to, use->CopyWithType(), deopt_id,
+        use->instruction()->SpeculativeModeOfInput(use->use_index()));
   } else if ((to == kTagged) && Boxing::Supports(from)) {
     converted = BoxInstr::Create(from, use->CopyWithType());
   } else {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 5f55829..f4c6d79 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2260,7 +2260,7 @@
   // never have a value of a function type, then we can safely do a 4-type
   // test instead of a 6-type test.
   const AbstractType& bound = AbstractType::Handle(zone(), type_param.bound());
-  return !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
+  return !bound.IsTopType() && !bound.IsFunctionType() &&
                  !bound.IsDartFunctionType() && bound.IsType()
              ? kTestTypeFourArgs
              : kTestTypeSixArgs;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 0133861..23038c1 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -619,39 +619,27 @@
                                            NNBDMode mode,
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
-  ASSERT(!type.IsTopType(mode));  // Already checked.
+  ASSERT(!type.IsTopType());  // Already checked.
   const Register kInstantiatorTypeArgumentsReg = R2;
   const Register kFunctionTypeArgumentsReg = R1;
   __ PushList((1 << kInstantiatorTypeArgumentsReg) |
               (1 << kFunctionTypeArgumentsReg));
 
   compiler::Label is_instance, is_not_instance;
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
+  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+  // In addition, 'null' is an instance of any nullable type.
   // It is also an instance of FutureOr<T> if it is an instance of T.
-  if (mode == NNBDMode::kLegacyLib) {
-    // See Legacy_NullIsInstanceOf().
-    if (type.IsInstantiated()) {
-      AbstractType& type_arg = AbstractType::Handle(type.raw());
-      while (type_arg.IsFutureOr(&type_arg)) {
-      }
-      __ CompareObject(R0, Object::null_object());
-      __ b((type_arg.IsNullType() || type_arg.Legacy_IsTopType())
-               ? &is_instance
-               : &is_not_instance,
-           EQ);
-    }
-  } else {
-    ASSERT(mode == NNBDMode::kOptedInLib);
-    // Test is valid on uninstantiated type, unless nullability is undetermined.
-    // See NNBD_NullIsInstanceOf().
-    if (!type.IsUndetermined()) {
-      __ CompareObject(R0, Object::null_object());
-      __ b((type.IsNullable() || type.IsLegacy()) ? &is_instance
-                                                  : &is_not_instance,
-           EQ);
-    }
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type.UnwrapFutureOr());
+  if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
+    // Only nullable type parameter remains nullable after instantiation.
+    // See NullIsInstanceOf().
+    __ CompareObject(R0, Object::null_object());
+    __ b((unwrapped_type.IsNullable() ||
+          (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
+             ? &is_instance
+             : &is_not_instance,
+         EQ);
   }
 
   // Generate inline instanceof test.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 9278863..a68439b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -596,38 +596,26 @@
                                            NNBDMode mode,
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
-  ASSERT(!type.IsTopType(mode));  // Already checked.
+  ASSERT(!type.IsTopType());  // Already checked.
   const Register kInstantiatorTypeArgumentsReg = R1;
   const Register kFunctionTypeArgumentsReg = R2;
   __ PushPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
 
   compiler::Label is_instance, is_not_instance;
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
+  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+  // In addition, 'null' is an instance of any nullable type.
   // It is also an instance of FutureOr<T> if it is an instance of T.
-  if (mode == NNBDMode::kLegacyLib) {
-    // See Legacy_NullIsInstanceOf().
-    if (type.IsInstantiated()) {
-      AbstractType& type_arg = AbstractType::Handle(type.raw());
-      while (type_arg.IsFutureOr(&type_arg)) {
-      }
-      __ CompareObject(R0, Object::null_object());
-      __ b((type_arg.IsNullType() || type_arg.Legacy_IsTopType())
-               ? &is_instance
-               : &is_not_instance,
-           EQ);
-    }
-  } else {
-    ASSERT(mode == NNBDMode::kOptedInLib);
-    // Test is valid on uninstantiated type, unless nullability is undetermined.
-    // See NNBD_NullIsInstanceOf().
-    if (!type.IsUndetermined()) {
-      __ CompareObject(R0, Object::null_object());
-      __ b((type.IsNullable() || type.IsLegacy()) ? &is_instance
-                                                  : &is_not_instance,
-           EQ);
-    }
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type.UnwrapFutureOr());
+  if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
+    // Only nullable type parameter remains nullable after instantiation.
+    // See NullIsInstanceOf().
+    __ CompareObject(R0, Object::null_object());
+    __ b((unwrapped_type.IsNullable() ||
+          (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
+             ? &is_instance
+             : &is_not_instance,
+         EQ);
   }
 
   // Generate inline instanceof test.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index da3e9c5..79e0c81 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -598,7 +598,7 @@
                                            NNBDMode mode,
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
-  ASSERT(!type.IsTopType(mode));  // Already checked.
+  ASSERT(!type.IsTopType());  // Already checked.
 
   __ pushl(EDX);  // Store instantiator type arguments.
   __ pushl(ECX);  // Store function type arguments.
@@ -606,30 +606,19 @@
   const compiler::Immediate& raw_null =
       compiler::Immediate(reinterpret_cast<intptr_t>(Object::null()));
   compiler::Label is_instance, is_not_instance;
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
+  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+  // In addition, 'null' is an instance of any nullable type.
   // It is also an instance of FutureOr<T> if it is an instance of T.
-  if (mode == NNBDMode::kLegacyLib) {
-    // See Legacy_NullIsInstanceOf().
-    if (type.IsInstantiated()) {
-      AbstractType& type_arg = AbstractType::Handle(type.raw());
-      while (type_arg.IsFutureOr(&type_arg)) {
-      }
-      __ cmpl(EAX, raw_null);
-      __ j(EQUAL, (type_arg.IsNullType() || type_arg.Legacy_IsTopType())
-                      ? &is_instance
-                      : &is_not_instance);
-    }
-  } else {
-    ASSERT(mode == NNBDMode::kOptedInLib);
-    // Test is valid on uninstantiated type, unless nullability is undetermined.
-    // See NNBD_NullIsInstanceOf().
-    if (!type.IsUndetermined()) {
-      __ cmpl(EAX, raw_null);
-      __ j(EQUAL, (type.IsNullable() || type.IsLegacy()) ? &is_instance
-                                                         : &is_not_instance);
-    }
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type.UnwrapFutureOr());
+  if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
+    // Only nullable type parameter remains nullable after instantiation.
+    // See NullIsInstanceOf().
+    __ cmpl(EAX, raw_null);
+    __ j(EQUAL, (unwrapped_type.IsNullable() ||
+                 (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
+                    ? &is_instance
+                    : &is_not_instance);
   }
 
   // Generate inline instanceof test.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 2c26964..21bc2df 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -621,33 +621,22 @@
                                            NNBDMode mode,
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
-  ASSERT(!type.IsTopType(mode));  // Already checked.
+  ASSERT(!type.IsTopType());  // Already checked.
 
   compiler::Label is_instance, is_not_instance;
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
+  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+  // In addition, 'null' is an instance of any nullable type.
   // It is also an instance of FutureOr<T> if it is an instance of T.
-  if (mode == NNBDMode::kLegacyLib) {
-    // See Legacy_NullIsInstanceOf().
-    if (type.IsInstantiated()) {
-      AbstractType& type_arg = AbstractType::Handle(type.raw());
-      while (type_arg.IsFutureOr(&type_arg)) {
-      }
-      __ CompareObject(RAX, Object::null_object());
-      __ j(EQUAL, (type_arg.IsNullType() || type_arg.Legacy_IsTopType())
-                      ? &is_instance
-                      : &is_not_instance);
-    }
-  } else {
-    ASSERT(mode == NNBDMode::kOptedInLib);
-    // Test is valid on uninstantiated type, unless nullability is undetermined.
-    // See NNBD_NullIsInstanceOf().
-    if (!type.IsUndetermined()) {
-      __ CompareObject(RAX, Object::null_object());
-      __ j(EQUAL, (type.IsNullable() || type.IsLegacy()) ? &is_instance
-                                                         : &is_not_instance);
-    }
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type.UnwrapFutureOr());
+  if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
+    // Only nullable type parameter remains nullable after instantiation.
+    // See NullIsInstanceOf().
+    __ CompareObject(RAX, Object::null_object());
+    __ j(EQUAL, (unwrapped_type.IsNullable() ||
+                 (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
+                    ? &is_instance
+                    : &is_not_instance);
   }
 
   // Generate inline instanceof test.
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2fcc181..b4f750d 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1971,7 +1971,7 @@
 }
 
 bool UnboxInt32Instr::ComputeCanDeoptimize() const {
-  if (speculative_mode() == kNotSpeculative) {
+  if (SpeculativeModeOfInputs() == kNotSpeculative) {
     return false;
   }
   const intptr_t value_cid = value()->Type()->ToCid();
@@ -1995,7 +1995,7 @@
 
 bool UnboxUint32Instr::ComputeCanDeoptimize() const {
   ASSERT(is_truncating());
-  if (speculative_mode() == kNotSpeculative) {
+  if (SpeculativeModeOfInputs() == kNotSpeculative) {
     return false;
   }
   if ((value()->Type()->ToCid() == kSmiCid) ||
@@ -2433,7 +2433,7 @@
         BinaryIntegerOpInstr* shift = BinaryIntegerOpInstr::Make(
             representation(), Token::kSHL, left()->CopyWithType(),
             new Value(constant_1), GetDeoptId(), can_overflow(),
-            is_truncating(), range(), speculative_mode());
+            is_truncating(), range(), SpeculativeModeOfInputs());
         if (shift != nullptr) {
           // Assign a range to the shift factor, just in case range
           // analysis no longer runs after this rewriting.
@@ -3024,7 +3024,7 @@
 
   // For all x, box(unbox(x)) = x.
   if (auto unbox = value()->definition()->AsUnboxInt64()) {
-    if (unbox->speculative_mode() == kNotSpeculative) {
+    if (unbox->SpeculativeModeOfInputs() == kNotSpeculative) {
       return unbox->value()->definition();
     }
   } else if (auto unbox = value()->definition()->AsUnboxedConstant()) {
@@ -3241,13 +3241,13 @@
   if (type->IsNone()) {
     return false;
   }
-  auto& compile_type = AbstractType::Handle(type->ToAbstractType()->raw());
-  while (compile_type.IsFutureOr(&compile_type)) {
-  }
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type->ToAbstractType()->UnwrapFutureOr());
   // Note that type 'Number' is a subtype of itself.
-  return compile_type.Legacy_IsTopType() || compile_type.IsTypeParameter() ||
-         compile_type.IsSubtypeOf(NNBDMode::kLegacyLib,
-                                  Type::Handle(Type::Number()), Heap::kOld);
+  return unwrapped_type.IsTopType() || unwrapped_type.IsObjectType() ||
+         unwrapped_type.IsTypeParameter() ||
+         unwrapped_type.IsSubtypeOf(NNBDMode::kLegacyLib,
+                                    Type::Handle(Type::Number()), Heap::kOld);
 }
 
 // Returns a replacement for a strict comparison and signals if the result has
@@ -4900,7 +4900,7 @@
 }
 
 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  if (speculative_mode() == kNotSpeculative) {
+  if (SpeculativeModeOfInputs() == kNotSpeculative) {
     switch (representation()) {
       case kUnboxedDouble:
       case kUnboxedFloat:
@@ -4929,7 +4929,7 @@
         break;
     }
   } else {
-    ASSERT(speculative_mode() == kGuardInputs);
+    ASSERT(SpeculativeModeOfInputs() == kGuardInputs);
     const intptr_t value_cid = value()->Type()->ToCid();
     const intptr_t box_cid = BoxCid();
 
@@ -5055,7 +5055,8 @@
 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
                                                         Value* new_right) {
   return new RelationalOpInstr(token_pos(), kind(), new_left, new_right,
-                               operation_cid(), deopt_id(), speculative_mode());
+                               operation_cid(), deopt_id(),
+                               SpeculativeModeOfInputs());
 }
 
 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 202a0ce..0e433b0 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -979,8 +979,19 @@
     return kTagged;
   }
 
-  // By default, instructions should check types of inputs when unboxing.
-  virtual SpeculativeMode speculative_mode() const { return kGuardInputs; }
+  SpeculativeMode SpeculativeModeOfInputs() const {
+    for (intptr_t i = 0; i < InputCount(); i++) {
+      if (SpeculativeModeOfInput(i) == kGuardInputs) {
+        return kGuardInputs;
+      }
+    }
+    return kNotSpeculative;
+  }
+
+  // By default, instructions should check types of inputs when unboxing
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return kGuardInputs;
+  }
 
   // Representation of the value produced by this computation.
   virtual Representation representation() const { return kTagged; }
@@ -2378,7 +2389,7 @@
   virtual void set_representation(Representation r) { representation_ = r; }
 
   // In AOT mode Phi instructions do not check types of inputs when unboxing.
-  virtual SpeculativeMode speculative_mode() const {
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
     return FLAG_precompiled_mode ? kNotSpeculative : kGuardInputs;
   }
 
@@ -4203,12 +4214,13 @@
     return kTagged;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool AttributesEqual(Instruction* other) const {
     return ComparisonInstr::AttributesEqual(other) &&
-           (speculative_mode() ==
-            other->AsEqualityCompare()->speculative_mode());
+           (speculative_mode_ == other->AsEqualityCompare()->speculative_mode_);
   }
 
   PRINT_OPERANDS_TO_SUPPORT
@@ -4250,11 +4262,13 @@
     return kTagged;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool AttributesEqual(Instruction* other) const {
     return ComparisonInstr::AttributesEqual(other) &&
-           (speculative_mode() == other->AsRelationalOp()->speculative_mode());
+           (speculative_mode_ == other->AsRelationalOp()->speculative_mode_);
   }
 
   PRINT_OPERANDS_TO_SUPPORT
@@ -4881,7 +4895,7 @@
                                 token_pos,
                                 kind) {}
 
-  virtual SpeculativeMode speculative_mode() const {
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
     // In AOT unbox is done based on TFA, therefore it was proven to be correct
     // and it can never deoptmize.
     return (IsUnboxedStore() && FLAG_precompiled_mode) ? kNotSpeculative
@@ -4906,6 +4920,9 @@
       return false;
     }
 
+    if (value()->definition()->Type()->IsBool()) {
+      return false;
+    }
     return value()->NeedsWriteBarrier() &&
            (emit_store_barrier_ == kEmitStoreBarrier);
   }
@@ -5358,11 +5375,16 @@
       return false;
     }
 
+    if (value()->definition()->Type()->IsBool()) {
+      return false;
+    }
     return value()->NeedsWriteBarrier() &&
            (emit_store_barrier_ == kEmitStoreBarrier);
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
@@ -6306,7 +6328,9 @@
 
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
-  virtual SpeculativeMode speculative_mode() const { return kNotSpeculative; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return kNotSpeculative;
+  }
 
   virtual CompileType ComputeType() const;
   virtual bool RecomputeType();
@@ -6375,7 +6399,7 @@
   Value* value() const { return inputs_[0]; }
 
   virtual bool ComputeCanDeoptimize() const {
-    if (speculative_mode() == kNotSpeculative) {
+    if (SpeculativeModeOfInputs() == kNotSpeculative) {
       return false;
     }
 
@@ -6393,7 +6417,9 @@
     return true;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual Representation representation() const { return representation_; }
 
@@ -6403,7 +6429,7 @@
   virtual bool AttributesEqual(Instruction* other) const {
     UnboxInstr* other_unbox = other->AsUnbox();
     return (representation() == other_unbox->representation()) &&
-           (speculative_mode() == other_unbox->speculative_mode());
+           (speculative_mode_ == other_unbox->speculative_mode_);
   }
 
   Definition* Canonicalize(FlowGraph* flow_graph);
@@ -6763,7 +6789,9 @@
     return kUnboxedDouble;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual intptr_t DeoptimizationTarget() const {
     // Direct access since this instruction cannot deoptimize, and the deopt-id
@@ -6781,7 +6809,7 @@
   virtual bool AttributesEqual(Instruction* other) const {
     const BinaryDoubleOpInstr* other_bin_op = other->AsBinaryDoubleOp();
     return (op_kind() == other_bin_op->op_kind()) &&
-           (speculative_mode() == other_bin_op->speculative_mode());
+           (speculative_mode_ == other_bin_op->speculative_mode_);
   }
 
  private:
@@ -6939,11 +6967,14 @@
   }
 
   virtual bool AttributesEqual(Instruction* other) const {
+    UnaryInt64OpInstr* unary_op_other = other->AsUnaryInt64Op();
     return UnaryIntegerOpInstr::AttributesEqual(other) &&
-           (speculative_mode() == other->speculative_mode());
+           (speculative_mode_ == unary_op_other->speculative_mode_);
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   DECLARE_INSTRUCTION(UnaryInt64Op)
 
@@ -7259,11 +7290,13 @@
     return kUnboxedInt64;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool AttributesEqual(Instruction* other) const {
     return BinaryIntegerOpInstr::AttributesEqual(other) &&
-           (speculative_mode() == other->AsBinaryInt64Op()->speculative_mode());
+           (speculative_mode_ == other->AsBinaryInt64Op()->speculative_mode_);
   }
 
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
@@ -7321,7 +7354,9 @@
                     intptr_t deopt_id)
       : ShiftIntegerOpInstr(op_kind, left, right, deopt_id) {}
 
-  virtual SpeculativeMode speculative_mode() const { return kNotSpeculative; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return kNotSpeculative;
+  }
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual bool MayThrow() const { return true; }
 
@@ -7380,7 +7415,9 @@
                      intptr_t deopt_id)
       : ShiftIntegerOpInstr(op_kind, left, right, deopt_id) {}
 
-  virtual SpeculativeMode speculative_mode() const { return kNotSpeculative; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return kNotSpeculative;
+  }
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual bool MayThrow() const { return true; }
 
@@ -7465,10 +7502,12 @@
     return kUnboxedDouble;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool AttributesEqual(Instruction* other) const {
-    return speculative_mode() == other->AsUnaryDoubleOp()->speculative_mode();
+    return speculative_mode_ == other->AsUnaryDoubleOp()->speculative_mode_;
   }
 
   PRINT_OPERANDS_TO_SUPPORT
@@ -7614,10 +7653,12 @@
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual bool AttributesEqual(Instruction* other) const {
-    return speculative_mode() == other->AsInt64ToDouble()->speculative_mode();
+    return speculative_mode_ == other->AsInt64ToDouble()->speculative_mode_;
   }
 
  private:
@@ -7746,7 +7787,9 @@
     return kUnboxedDouble;
   }
 
-  virtual SpeculativeMode speculative_mode() const { return speculative_mode_; }
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return speculative_mode_;
+  }
 
   virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
 
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 6db8c2c..13d80a5 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -1655,7 +1655,8 @@
     UnboxInstr* unbox = def->AsUnboxInt64();
     Value* value = unbox->value()->CopyWithType();
     intptr_t deopt_id = unbox->DeoptimizationTarget();
-    return new (Z) UnboxUint32Instr(value, deopt_id, def->speculative_mode());
+    return new (Z)
+        UnboxUint32Instr(value, deopt_id, def->SpeculativeModeOfInputs());
   } else if (def->IsUnaryInt64Op()) {
     UnaryInt64OpInstr* op = def->AsUnaryInt64Op();
     Token::Kind op_kind = op->op_kind();
diff --git a/runtime/vm/compiler/backend/sexpression.cc b/runtime/vm/compiler/backend/sexpression.cc
index 241361e..8b33ea5 100644
--- a/runtime/vm/compiler/backend/sexpression.cc
+++ b/runtime/vm/compiler/backend/sexpression.cc
@@ -484,22 +484,25 @@
             buf[new_pos] = '\t';
             break;
           case 'u': {
-            if (old_pos + 4 >= token->length()) {
+            const intptr_t first = old_pos + 1;
+            const intptr_t last = old_pos + 4;
+            if (last >= token->length()) {
               PARSE_ERROR(escape_pos, ErrorStrings::kBadUnicodeEscape);
             }
             intptr_t val = 0;
-            for (intptr_t i = old_pos + 4; i > old_pos; old_pos--) {
+            for (const char *cursor = cstr + first, *end = cstr + last + 1;
+                 cursor < end; cursor++) {
               val *= 16;
-              if (!Utils::IsHexDigit(i)) {
+              if (!Utils::IsHexDigit(*cursor)) {
                 PARSE_ERROR(escape_pos, ErrorStrings::kBadUnicodeEscape);
               }
-              val += Utils::HexDigitToInt(i);
+              val += Utils::HexDigitToInt(*cursor);
             }
             // Currently, just handle encoded ASCII instead of doing
             // handling Unicode characters.
             // (TextBuffer::AddEscapedString uses this for characters < 0x20.)
             ASSERT(val <= 0x7F);
-            old_pos += 5;
+            old_pos = last;
             buf[new_pos] = val;
             break;
           }
diff --git a/runtime/vm/compiler/backend/sexpression.h b/runtime/vm/compiler/backend/sexpression.h
index 8ed38b2..461e3eb 100644
--- a/runtime/vm/compiler/backend/sexpression.h
+++ b/runtime/vm/compiler/backend/sexpression.h
@@ -191,7 +191,7 @@
       : SExpParser(zone, cstr, strlen(cstr)) {}
   SExpParser(Zone* zone, const char* cstr, intptr_t len)
       : zone_(zone),
-        buffer_(cstr),
+        buffer_(ASSERT_NOTNULL(cstr)),
         buffer_size_(strnlen(cstr, len)),
         cur_label_(nullptr),
         cur_value_(nullptr),
@@ -228,6 +228,7 @@
   intptr_t error_pos() const { return error_pos_; }
   const char* error_message() const { return error_message_; }
 
+  const char* Input() const { return buffer_; }
   SExpression* Parse();
   DART_NORETURN void ReportError() const;
 
diff --git a/runtime/vm/compiler/backend/sexpression_test.cc b/runtime/vm/compiler/backend/sexpression_test.cc
index 7b6b85b..db0b1ed 100644
--- a/runtime/vm/compiler/backend/sexpression_test.cc
+++ b/runtime/vm/compiler/backend/sexpression_test.cc
@@ -10,6 +10,27 @@
 
 namespace dart {
 
+#define EXPECT_SEXP_PARSE_ERROR(sexp, parser, pos, message)                    \
+  do {                                                                         \
+    if (sexp != nullptr) {                                                     \
+      dart::Expect(__FILE__, __LINE__)                                         \
+          .Fail("parse unexpectedly succeeded for \"%s\"", parser.Input());    \
+    }                                                                          \
+    EXPECT_EQ(pos, parser.error_pos());                                        \
+    EXPECT_STREQ(message, parser.error_message());                             \
+  } while (false);
+
+#define EXPECT_SEXP_PARSE_SUCCESS(sexp, parser)                                \
+  do {                                                                         \
+    if (sexp == nullptr) {                                                     \
+      EXPECT_NOTNULL(parser.error_message());                                  \
+      dart::Expect(__FILE__, __LINE__)                                         \
+          .Fail("parse unexpectedly failed at \"%s\": %" Pd ": %s",            \
+                parser.Input() + parser.error_pos(), parser.error_pos(),       \
+                parser.error_message());                                       \
+    }                                                                          \
+  } while (false);
+
 static const char* const shared_sexp_cstr =
     "(def v0 (Constant 3) { type (CompileType 147 { nullable false, name "
     "\"T{Smi}\"}), })";
@@ -70,7 +91,7 @@
     const char* const cstr = "(def v0 (Constant 3) { foo \"123\\\\\" })";
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NOTNULL(sexp);
+    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
     EXPECT(sexp->IsList());
     EXPECT_EQ(1, sexp->AsList()->ExtraLength());
     EXPECT(sexp->AsList()->ExtraHasKey("foo"));
@@ -78,6 +99,20 @@
     EXPECT(val->IsString());
     EXPECT_STREQ("123\\", val->AsString()->value());
   }
+  // Valid unicode escapes are properly handled.
+  {
+    const char* const cstr =
+        "(def v0 (Constant 3) { foo \"\\u0001\\u0020\\u0054\" })";
+    SExpParser parser(zone, cstr, strlen(cstr));
+    SExpression* const sexp = parser.Parse();
+    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
+    EXPECT(sexp->IsList());
+    EXPECT_EQ(1, sexp->AsList()->ExtraLength());
+    EXPECT(sexp->AsList()->ExtraHasKey("foo"));
+    auto val = sexp->AsList()->ExtraLookupValue("foo");
+    EXPECT(val->IsString());
+    EXPECT_STREQ("\x01 T", val->AsString()->value());
+  }
 }
 
 ISOLATE_UNIT_TEST_CASE(DeserializeSExpNumbers) {
@@ -88,7 +123,7 @@
     const char* const cstr = "(-4 -50 -1414243)";
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NOTNULL(sexp);
+    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
     EXPECT(sexp->IsList());
     auto list = sexp->AsList();
     EXPECT_EQ(3, list->Length());
@@ -104,7 +139,7 @@
     const char* const cstr = "(1.05 0.05 .03 1e100 1e-100)";
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NOTNULL(sexp);
+    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
     EXPECT(sexp->IsList());
     auto list = sexp->AsList();
     EXPECT_EQ(5, list->Length());
@@ -131,7 +166,7 @@
     const char* const cstr = "(NaN Infinity -Infinity)";
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NOTNULL(sexp);
+    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
     EXPECT(sexp->IsList());
     auto list = sexp->AsList();
     EXPECT_EQ(3, list->Length());
@@ -190,11 +225,9 @@
     const intptr_t error_pos = strlen(cstr);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kOpenSExpList, start_pos);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Non-symbol label in map pair
   {
@@ -204,11 +237,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         SExpParser::ErrorStrings::kNonSymbolLabel;
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // No values in a map pair
   {
@@ -220,11 +251,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kNoMapValue, label);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Multiple values in a map pair
   {
@@ -236,11 +265,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kExtraMapValue, label);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Unterminated quoted string
   {
@@ -252,11 +279,9 @@
     const intptr_t error_pos = strlen(cstr);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kOpenString, string_pos);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Unterminated extra info map
   {
@@ -270,11 +295,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kOpenMap, map_pos);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Repeated extra info map label
   {
@@ -286,11 +309,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kRepeatedMapLabel, label);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Unicode escape with non-hex digits.
   {
@@ -300,11 +321,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         SExpParser::ErrorStrings::kBadUnicodeEscape;
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Unicode escape with less than four hex digits.
   {
@@ -314,11 +333,9 @@
     const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         SExpParser::ErrorStrings::kBadUnicodeEscape;
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
   // Treating backslashed quote appropriately to detect unterminated string
   {
@@ -329,11 +346,9 @@
     const intptr_t error_pos = strlen(cstr);
     SExpParser parser(zone, cstr, strlen(cstr));
     SExpression* const sexp = parser.Parse();
-    EXPECT_NULLPTR(sexp);
-    EXPECT_EQ(error_pos, parser.error_pos());
     const char* const expected_message =
         OS::SCreate(zone, SExpParser::ErrorStrings::kOpenString, string_pos);
-    EXPECT_STREQ(expected_message, parser.error_message());
+    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
   }
 }
 
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 15664f7..523b039 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -801,13 +801,20 @@
   return !smi.IsSubtypeOf(NNBDMode::kLegacyLib, *type, Heap::Space::kNew);
 }
 
-bool CompileType::CanComputeIsInstanceOf(NNBDMode mode,
-                                         const AbstractType& type,
-                                         bool is_nullable,
-                                         bool* is_instance) {
-  ASSERT(is_instance != NULL);
-  if (type.IsTopType(mode)) {
-    *is_instance = true;
+bool CompileType::IsSubtypeOf(NNBDMode mode, const AbstractType& other) {
+  if (other.IsTopType()) {
+    return true;
+  }
+
+  if (IsNone()) {
+    return false;
+  }
+
+  return ToAbstractType()->IsSubtypeOf(mode, other, Heap::kOld);
+}
+
+bool CompileType::IsAssignableTo(NNBDMode mode, const AbstractType& other) {
+  if (other.IsTopType()) {
     return true;
   }
 
@@ -818,51 +825,20 @@
   // Consider the compile type of the value.
   const AbstractType& compile_type = *ToAbstractType();
 
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
-  // It is also an instance of FutureOr<T> if it is an instance of T.
-  // Functions that do not explicitly return a value, implicitly return null,
-  // except generative constructors, which return the object being constructed.
-  // It is therefore acceptable for void functions to return null.
   if (compile_type.IsNullType()) {
-    if (mode == NNBDMode::kLegacyLib) {
-      // Using legacy testing.
-      if (!type.IsInstantiated()) {
-        return false;
-      }
-      AbstractType& type_arg = AbstractType::Handle(type.raw());
-      while (type_arg.IsFutureOr(&type_arg)) {
-      }
-      *is_instance =
-          is_nullable || type_arg.IsNullType() || type_arg.Legacy_IsTopType();
-    } else {
-      ASSERT(mode == NNBDMode::kOptedInLib);
-      // Using nnbd testing.
-      if (type.IsUndetermined()) {
-        return false;
-      }
-      *is_instance = is_nullable || type.IsNullable() || type.IsLegacy();
+    if (!FLAG_strong_non_nullable_type_checks) {
+      // In weak mode, 'null' is assignable to any type.
+      return true;
     }
-    return true;
+    // In strong mode, 'null' is assignable to any nullable or legacy type.
+    // It is also assignable to FutureOr<T> if it is assignable to T.
+    const AbstractType& unwrapped_other =
+        AbstractType::Handle(other.UnwrapFutureOr());
+    // A nullable or legacy type parameter will still be either nullable or
+    // legacy after instantiation.
+    return unwrapped_other.IsNullable() || unwrapped_other.IsLegacy();
   }
-
-  // If the value can be null then we can't eliminate the
-  // check unless null is allowed.
-  if (is_nullable_ && !is_nullable) {
-    return false;
-  }
-
-  *is_instance = compile_type.IsSubtypeOf(mode, type, Heap::kOld);
-  return *is_instance;
-}
-
-bool CompileType::IsSubtypeOf(NNBDMode mode, const AbstractType& other) {
-  if (IsNone()) {
-    return false;
-  }
-
-  return ToAbstractType()->IsSubtypeOf(mode, other, Heap::kOld);
+  return compile_type.IsSubtypeOf(mode, other, Heap::kOld);
 }
 
 bool CompileType::Specialize(GrowableArray<intptr_t>* class_ids) {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index adbd711..af81cd0 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -858,7 +858,7 @@
 
   // Build an AssertAssignable if necessary.
   const AbstractType& dst_type = AbstractType::ZoneHandle(zone(), field.type());
-  if (I->argument_type_checks() && !dst_type.IsTopType(target.nnbd_mode())) {
+  if (I->argument_type_checks() && !dst_type.IsTopType()) {
     // Compute if we need to type check the value. Always type check if
     // at a dynamic invocation.
     bool needs_check = true;
@@ -1101,24 +1101,15 @@
     }
     bool is_subtype = false;
     if (cls.IsNullClass()) {
-      // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-      // In addition, 'null' is an instance of Never and Object with legacy
-      // testing, or of any nullable or legacy type with nnbd testing.
+      // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+      // In addition, 'null' is an instance of any nullable type.
       // It is also an instance of FutureOr<T> if it is an instance of T.
-      if (mode == NNBDMode::kLegacyLib) {
-        // Using legacy testing.
-        ASSERT(type.IsInstantiated());
-        AbstractType& type_arg = AbstractType::Handle(type.raw());
-        while (type_arg.IsFutureOr(&type_arg)) {
-        }
-        is_subtype = type_arg.IsNullType() || type_arg.Legacy_IsTopType();
-      } else {
-        ASSERT(mode == NNBDMode::kOptedInLib);
-        // Using nnbd testing.
-        ASSERT(!type.IsUndetermined());
-        is_subtype =
-            type.IsNullable() || type.IsLegacy() || type.NNBD_IsTopType();
-      }
+      const AbstractType& unwrapped_type =
+          AbstractType::Handle(type.UnwrapFutureOr());
+      ASSERT(unwrapped_type.IsInstantiated() &&
+             !unwrapped_type.IsUndetermined());
+      is_subtype = unwrapped_type.IsTopType() || unwrapped_type.IsNullable() ||
+                   (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType());
     } else {
       is_subtype = Class::IsSubtypeOf(mode, cls, Object::null_type_arguments(),
                                       type_class, Object::null_type_arguments(),
@@ -1186,9 +1177,9 @@
       return false;
     }
   }
-  if (mode == NNBDMode::kOptedInLib && !type.IsNonNullable()) {
+  if (type.IsNullable() || type.IsTopType() || type.IsNeverType()) {
     // A class id check is not sufficient, since a null instance also satisfies
-    // the test against a nullable or legacy type.
+    // the test against a nullable type.
     // TODO(regis): Add a null check in addition to the class id check?
     return false;
   }
@@ -1211,22 +1202,20 @@
 
   // The goal is to emit code that will determine the result of 'x is type'
   // depending solely on the fact that x == null or not.
-  // 'null' is an instance of Null, Object*, Object?, void, and dynamic.
-  // In addition, 'null' is an instance of Never and Object with legacy testing,
-  // or of any nullable or legacy type with nnbd testing.
+  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
+  // In addition, 'null' is an instance of any nullable type.
   // It is also an instance of FutureOr<T> if it is an instance of T.
-  if (mode == NNBDMode::kLegacyLib) {
-    // Using legacy testing of null instance.
-    if (type.Legacy_IsTopType() || !type.IsInstantiated()) {
-      return false;  // Always true or cannot tell.
-    }
-  } else {
-    ASSERT(mode == NNBDMode::kOptedInLib);
-    // Checking whether the receiver is null cannot help in an opted-in library.
-    // Indeed, its static type would have to be nullable to legally hold null.
-    // For the static type to be a subtype of the tested type, the tested type
-    // has to be nullable as well, in which case it makes no difference if the
-    // receiver is null or not.
+  const AbstractType& unwrapped_type =
+      AbstractType::Handle(type.UnwrapFutureOr());
+  if (unwrapped_type.IsTopType() || !unwrapped_type.IsInstantiated()) {
+    return false;  // Always true or cannot tell.
+  }
+
+  // Checking whether the receiver is null can only help if the tested type is
+  // legacy (including Never*) or the Null type.
+  if (!unwrapped_type.IsLegacy() && !unwrapped_type.IsNullType()) {
+    // TODO(regis): We should optimize this into a constant if the type
+    // is nullable or non-nullable.
     return false;
   }
 
@@ -1239,7 +1228,9 @@
   if (left_value->Type()->IsSubtypeOf(mode, type)) {
     Definition* replacement = new (Z) StrictCompareInstr(
         call->token_pos(),
-        type.IsNullType() ? Token::kEQ_STRICT : Token::kNE_STRICT,
+        (unwrapped_type.IsNullType() || unwrapped_type.IsNeverType())
+            ? Token::kEQ_STRICT
+            : Token::kNE_STRICT,
         left_value->CopyWithType(Z),
         new (Z) Value(flow_graph()->constant_null()),
         /* number_check = */ false, DeoptId::kNone);
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc
index 9966465..13b01f3 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention.cc
@@ -244,7 +244,7 @@
                                       Zone* zone) {
   const auto& payload_type_converted = ConvertIfSoftFp(payload_type, zone);
   const auto& container_type =
-      CallingConventions::kArgumentRegisterExtension == kExtendedTo4
+      CallingConventions::kReturnRegisterExtension == kExtendedTo4
           ? payload_type_converted.WidenTo4Bytes(zone)
           : payload_type_converted;
   if (container_type.IsFloat()) {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 3348981..9c19f71 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -384,7 +384,6 @@
   checks.Add(function);
   checks.Add(default_args);
 
-  const NNBDMode nnbd_mode = function.nnbd_mode();
   const auto& type_params =
       TypeArguments::Handle(Z, function.type_parameters());
   if (!type_params.IsNull()) {
@@ -393,7 +392,7 @@
     for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
       type_param ^= type_params.TypeAt(i);
       bound = type_param.bound();
-      if (!bound.IsTopType(nnbd_mode) && !type_param.IsGenericCovariantImpl()) {
+      if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
         name = type_param.name();
         ASSERT(type_param.IsFinalized());
         check = ParameterTypeCheck::New();
@@ -419,7 +418,7 @@
   const bool has_optional_parameters = function.HasOptionalParameters();
   for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
     type = function.ParameterTypeAt(i);
-    if (!type.IsTopType(nnbd_mode) && !is_generic_covariant_impl.Contains(i) &&
+    if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
         !is_covariant.Contains(i)) {
       name = function.ParameterNameAt(i);
       intptr_t index;
@@ -2261,8 +2260,7 @@
     function.set_is_declared_in_bytecode(true);
     function.set_has_pragma(has_pragma);
     function.set_end_token_pos(end_position);
-    function.set_is_no_such_method_forwarder(
-        (flags & kIsNoSuchMethodForwarderFlag) != 0);
+    function.set_is_synthetic((flags & kIsNoSuchMethodForwarderFlag) != 0);
     function.set_is_reflectable((flags & kIsReflectableFlag) != 0);
     function.set_is_debuggable((flags & kIsDebuggableFlag) != 0);
     function.set_is_extension_member(is_extension_member);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index fd826d9..a0d6cca 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3575,9 +3575,8 @@
                     ? NNBDMode::kOptedInLib
                     : NNBDMode::kLegacyLib;
   } else {
-    nnbd_mode = parsed_function()->function().nnbd_mode();
+    nnbd_mode = NNBDMode::kLegacyLib;
   }
-  ASSERT(nnbd_mode == parsed_function()->function().nnbd_mode());
 
   Fragment instructions = BuildExpression();  // read operand.
 
@@ -3585,7 +3584,7 @@
 
   // The VM does not like an instanceOf call with a dynamic type. We need to
   // special case this situation by detecting a top type.
-  if (type.IsTopType(nnbd_mode)) {
+  if (type.IsTopType()) {
     // Evaluate the expression on the left but ignore its result.
     instructions += Drop();
 
@@ -3630,16 +3629,11 @@
 
   const uint8_t flags = ReadFlags();  // read flags.
   const bool is_type_error = (flags & kAsExpressionFlagTypeError) != 0;
-  const NNBDMode nnbd_mode =
-      ((flags & kAsExpressionFlagForNonNullableByDefault) != 0)
-          ? NNBDMode::kOptedInLib
-          : NNBDMode::kLegacyLib;
-  ASSERT(nnbd_mode == parsed_function()->function().nnbd_mode());
 
   Fragment instructions = BuildExpression();  // read operand.
 
   const AbstractType& type = T.BuildType();  // read type.
-  if (type.IsInstantiated() && type.IsTopType(nnbd_mode)) {
+  if (type.IsInstantiated() && type.IsTopType()) {
     // We already evaluated the operand on the left and just leave it there as
     // the result of the `obj as dynamic` expression.
   } else {
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index ea5bf45..1c1e494 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -469,11 +469,11 @@
     Fragment initialize(is_uninitialized);
     if (is_static) {
       initialize += StaticCall(position, init_function,
-                               /* argument_count = */ 0, ICData::kStatic);
+                               /* argument_count = */ 0, ICData::kNoRebind);
     } else {
       initialize += LoadLocal(instance);
       initialize += StaticCall(position, init_function,
-                               /* argument_count = */ 1, ICData::kStatic);
+                               /* argument_count = */ 1, ICData::kNoRebind);
     }
     initialize += StoreLocal(position, temp);
     initialize += Drop();
@@ -1706,14 +1706,11 @@
   String& name = String::Handle(Z);
   AbstractType& bound = AbstractType::Handle(Z);
   Fragment check_bounds;
-  const NNBDMode nnbd_mode = forwarding_target != nullptr
-                                 ? forwarding_target->nnbd_mode()
-                                 : dart_function.nnbd_mode();
   for (intptr_t i = 0; i < num_type_params; ++i) {
     type_param ^= type_parameters.TypeAt(i);
 
     bound = type_param.bound();
-    if (bound.IsTopType(nnbd_mode)) {
+    if (bound.IsTopType()) {
       continue;
     }
 
@@ -1770,7 +1767,7 @@
           &AbstractType::ZoneHandle(Z, forwarding_target->ParameterTypeAt(i));
     }
 
-    if (target_type->IsTopType(nnbd_mode)) continue;
+    if (target_type->IsTopType()) continue;
 
     const bool is_covariant = param->is_explicit_covariant_parameter();
     Fragment* checks = is_covariant ? explicit_checks : implicit_checks;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index d5c3b6d..1cfc228 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -545,6 +545,7 @@
     kRedirectingFactoryConstructor = 1 << 6,
     kNoSuchMethodForwarder = 1 << 7,
     kExtensionMember = 1 << 8,
+    kMemberSignature = 1 << 9,
   };
 
   explicit ProcedureHelper(KernelReaderHelper* helper)
@@ -571,6 +572,7 @@
     return (flags_ & kNoSuchMethodForwarder) != 0;
   }
   bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; }
+  bool IsMemberSignature() const { return (flags_ & kMemberSignature) != 0; }
 
   NameIndex canonical_name_;
   TokenPosition start_position_;
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 1a8d269..998f0d6 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -1016,12 +1016,6 @@
   Object& result = Object::Handle(zone);
   Array& functions = Array::Handle(zone, cls.functions());
   Function& func = Function::Handle(zone);
-  // Class dynamic lives in the vm isolate. Its array fields cannot be set to
-  // an empty array.
-  if (functions.IsNull()) {
-    ASSERT(cls.IsDynamicClass());
-    return Error::null();
-  }
   // Compile all the regular functions.
   for (int i = 0; i < functions.Length(); i++) {
     func ^= functions.At(i);
@@ -1046,12 +1040,6 @@
   ASSERT(error.IsNull());
   Array& functions = Array::Handle(zone, cls.functions());
   Function& func = Function::Handle(zone);
-  // Class dynamic lives in the vm isolate. Its array fields cannot be set to
-  // an empty array.
-  if (functions.IsNull()) {
-    ASSERT(cls.IsDynamicClass());
-    return Error::null();
-  }
   // Compile all the regular functions.
   for (int i = 0; i < functions.Length(); i++) {
     func ^= functions.At(i);
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 2e39b42..48bf5a7 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -157,8 +157,7 @@
           offset_into_target = call.distance();
         }
 
-        const uword destination_payload =
-            Instructions::PayloadStart(destination_.instructions());
+        const uword destination_payload = destination_.PayloadStart();
         const uword entry_point = call_entry_point == Code::kUncheckedEntry
                                       ? destination_.UncheckedEntryPoint()
                                       : destination_.EntryPoint();
@@ -272,17 +271,16 @@
       offset_into_target = call.distance();
     }
 
-    const uword destination_payload =
-        Instructions::PayloadStart(destination_.instructions());
+    const uword destination_payload = destination_.PayloadStart();
     const uword entry_point = call_entry_point == Code::kUncheckedEntry
                                   ? destination_.UncheckedEntryPoint()
                                   : destination_.EntryPoint();
 
     offset_into_target += (entry_point - destination_payload);
 
-    const intptr_t text_offset = code_text_offset +
-                                 compiler::target::Instructions::HeaderSize() +
-                                 call_instruction_offset;
+    const intptr_t text_offset =
+        code_text_offset + AdjustPayloadOffset(call_instruction_offset);
+
     UnresolvedCall unresolved_call(code.raw(), call_instruction_offset,
                                    text_offset, destination_.raw(),
                                    offset_into_target);
@@ -368,12 +366,12 @@
   const intptr_t call_text_offset = unresolved_call->text_offset;
   const intptr_t call_offset = unresolved_call->call_offset;
 
-  auto caller = Code::InstructionsOf(unresolved_call->caller);
   const int32_t distance = destination_text - call_text_offset;
   {
-    uword addr = Instructions::PayloadStart(caller) + call_offset;
+    auto const caller = unresolved_call->caller;
+    uword addr = Code::PayloadStartOf(caller) + call_offset;
     if (FLAG_write_protect_code) {
-      addr -= HeapPage::Of(caller)->AliasOffset();
+      addr -= HeapPage::Of(Code::InstructionsOf(caller))->AliasOffset();
     }
     PcRelativeCallPattern call(addr);
     ASSERT(call.IsValid());
@@ -510,9 +508,15 @@
 intptr_t CodeRelocator::FindDestinationInText(
     const RawInstructions* destination,
     intptr_t offset_into_target) {
-  auto destination_offset = text_offsets_.LookupValue(destination);
-  return destination_offset + compiler::target::Instructions::HeaderSize() +
-         offset_into_target;
+  auto const destination_offset = text_offsets_.LookupValue(destination);
+  return destination_offset + AdjustPayloadOffset(offset_into_target);
+}
+
+intptr_t CodeRelocator::AdjustPayloadOffset(intptr_t payload_offset) {
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    return payload_offset;
+  }
+  return compiler::target::Instructions::HeaderSize() + payload_offset;
 }
 
 #endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
diff --git a/runtime/vm/compiler/relocation.h b/runtime/vm/compiler/relocation.h
index 50db3e1..2022f81 100644
--- a/runtime/vm/compiler/relocation.h
+++ b/runtime/vm/compiler/relocation.h
@@ -178,6 +178,8 @@
   intptr_t FindDestinationInText(const RawInstructions* destination,
                                  intptr_t offset_into_target);
 
+  static intptr_t AdjustPayloadOffset(intptr_t payload_offset);
+
   bool IsTargetInRangeFor(UnresolvedCall* unresolved_call,
                           intptr_t target_text_offset);
 
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index d24699f..e63cb0c 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -51,6 +51,10 @@
   return type.IsDoubleType();
 }
 
+bool IsBoolType(const AbstractType& type) {
+  return type.IsBoolType();
+}
+
 bool IsIntType(const AbstractType& type) {
   return type.IsIntType();
 }
@@ -513,6 +517,11 @@
 
 const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
 
+word InstructionsSection::HeaderSize() {
+  return Utils::RoundUp(InstructionsSection::UnalignedHeaderSize(),
+                        target::kWordSize);
+}
+
 word Instructions::HeaderSize() {
   return Utils::RoundUp(Instructions::UnalignedHeaderSize(), target::kWordSize);
 }
@@ -911,6 +920,10 @@
   return -kWordSize;
 }
 
+word InstructionsSection::NextFieldOffset() {
+  return -kWordSize;
+}
+
 word Instructions::NextFieldOffset() {
   return -kWordSize;
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index d427bb5..ba31240 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -124,6 +124,9 @@
 // Returns true if [type] is the "double" type.
 bool IsDoubleType(const AbstractType& type);
 
+// Returns true if [type] is the "double" type.
+bool IsBoolType(const AbstractType& type);
+
 // Returns true if [type] is the "_Smi" type.
 bool IsSmiType(const AbstractType& type);
 
@@ -1063,6 +1066,14 @@
   static const word kSizeOfClassPairLog2;
 };
 
+class InstructionsSection : public AllStatic {
+ public:
+  static word HeaderSize();
+  static word UnalignedHeaderSize();
+  static word InstanceSize();
+  static word NextFieldOffset();
+};
+
 class Instructions : public AllStatic {
  public:
   static const word kMonomorphicEntryOffsetJIT;
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index f73ebd4..9b969cc 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -415,6 +415,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -874,6 +878,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -1326,6 +1334,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -1786,6 +1798,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -2238,6 +2254,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -2691,6 +2711,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -3137,6 +3161,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -3591,6 +3619,10 @@
 static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
+static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -4079,6 +4111,10 @@
 static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word
@@ -4581,6 +4617,10 @@
     12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -5087,6 +5127,10 @@
     12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -5549,7 +5593,7 @@
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 112;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
-static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 60;
+static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
     8;
 static constexpr dart::compiler::target::word
@@ -5582,6 +5626,10 @@
 static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word
@@ -6077,6 +6125,10 @@
     12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -6576,6 +6628,10 @@
     12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index c7bd6ae..955c36b 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -286,6 +286,8 @@
   SIZEOF(Instance, InstanceSize, RawInstance)                                  \
   SIZEOF(Instructions, InstanceSize, RawInstructions)                          \
   SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions)                   \
+  SIZEOF(InstructionsSection, InstanceSize, RawInstructionsSection)            \
+  SIZEOF(InstructionsSection, UnalignedHeaderSize, RawInstructionsSection)     \
   SIZEOF(Int32x4, InstanceSize, RawInt32x4)                                    \
   SIZEOF(Integer, InstanceSize, RawInteger)                                    \
   SIZEOF(KernelProgramInfo, InstanceSize, RawKernelProgramInfo)                \
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 9df918e..6fddb9b 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -27,7 +27,7 @@
   kNotExtended,
   // Values smaller than 4 bytes are passed around zero- or signextended to
   // 4 bytes.
-  kExtendedTo4
+  kExtendedTo4,
 };
 
 }  // namespace dart
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index b25b343..24baafd 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -389,6 +389,7 @@
 
   // Whether 1 or 2 byte-sized arguments or return values are passed extended
   // to 4 bytes.
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kExtendedTo4;
   static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo4;
   static constexpr ExtensionStrategy kArgumentStackExtension = kExtendedTo4;
 
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 6b3959b..4378cc2 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -233,8 +233,10 @@
   // Whether 1 or 2 byte-sized arguments or return values are passed extended
   // to 4 bytes.
 #if defined(TARGET_OS_MACOS_IOS)
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kExtendedTo4;
   static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo4;
 #else
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kNotExtended;
   static constexpr ExtensionStrategy kArgumentRegisterExtension = kNotExtended;
 #endif
   static constexpr ExtensionStrategy kArgumentStackExtension = kNotExtended;
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 6346e75..de68339 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -182,6 +182,7 @@
 
   // Whether 1 or 2 byte-sized arguments or return values are passed extended
   // to 4 bytes.
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kNotExtended;
   static constexpr ExtensionStrategy kArgumentRegisterExtension = kNotExtended;
   static constexpr ExtensionStrategy kArgumentStackExtension = kExtendedTo4;
 };
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 7665d65..2a6d1cc 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -214,6 +214,7 @@
 
   // Whether 1 or 2 byte-sized arguments or return values are passed extended
   // to 4 bytes.
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kNotExtended;
   static constexpr ExtensionStrategy kArgumentRegisterExtension = kNotExtended;
   static constexpr ExtensionStrategy kArgumentStackExtension = kNotExtended;
 
@@ -275,7 +276,11 @@
 
   // Whether 1 or 2 byte-sized arguments or return values are passed extended
   // to 4 bytes.
-  static constexpr ExtensionStrategy kArgumentRegisterExtension = kNotExtended;
+  // Note that `kReturnRegisterExtension != kArgumentRegisterExtension`, which
+  // effectively means that the caller is responsable for truncating and
+  // extending both arguments and return value.
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kNotExtended;
+  static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo4;
   static constexpr ExtensionStrategy kArgumentStackExtension = kExtendedTo4;
 
 #endif
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ce28a06..1fc4d44 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -845,6 +845,10 @@
   do {                                                                         \
     buffer.AddString(value ? (" " #name) : (" no-" #name));                    \
   } while (0);
+#define ADD_P(name, T, DV, C) ADD_FLAG(name, FLAG_##name)
+#define ADD_R(name, PV, T, DV, C) ADD_FLAG(name, FLAG_##name)
+#define ADD_C(name, PCV, PV, T, DV, C) ADD_FLAG(name, FLAG_##name)
+#define ADD_D(name, T, DV, C) ADD_FLAG(name, FLAG_##name)
 
 #define ADD_ISOLATE_FLAG(name, isolate_flag, flag)                             \
   do {                                                                         \
@@ -853,7 +857,7 @@
   } while (0);
 
   if (Snapshot::IncludesCode(kind)) {
-    VM_GLOBAL_FLAG_LIST(ADD_FLAG);
+    VM_GLOBAL_FLAG_LIST(ADD_P, ADD_R, ADD_C, ADD_D);
 
     // enabling assertions affects deopt ids.
     ADD_ISOLATE_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
@@ -901,6 +905,10 @@
     buffer.AddString(" nnbd-experiment");
   }
 #undef ADD_ISOLATE_FLAG
+#undef ADD_D
+#undef ADD_C
+#undef ADD_R
+#undef ADD_P
 #undef ADD_FLAG
 
   return buffer.Steal();
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index c44b0cc..11e5c43 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -126,13 +126,7 @@
 
   // TODO(dartbug.com/40342): Delete these functions.
   static void set_non_nullable_flag(bool value) { non_nullable_flag_ = value; }
-  static bool non_nullable_flag() {
-#ifdef DART_BUILT_WITH_NNBD_FLAG
-    return true;
-#else
-    return non_nullable_flag_;
-#endif
-  }
+  static bool non_nullable_flag() { return true; }
 
  private:
   static void WaitForIsolateShutdown();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index aa6e4db..f5c8580 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1981,14 +1981,35 @@
   return Api::Null();
 }
 
+DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
+  TransitionNativeToVM transition(Thread::Current());
+  return Api::UnwrapHandle(object) == Object::null();
+}
+
 DART_EXPORT Dart_Handle Dart_EmptyString() {
   ASSERT(Isolate::Current() != NULL);
   return Api::EmptyString();
 }
 
-DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
-  TransitionNativeToVM transition(Thread::Current());
-  return Api::UnwrapHandle(object) == Object::null();
+DART_EXPORT Dart_Handle Dart_TypeDynamic() {
+  DARTSCOPE(Thread::Current());
+  CHECK_CALLBACK_STATE(T);
+  API_TIMELINE_DURATION(T);
+  return Api::NewHandle(T, Type::DynamicType());
+}
+
+DART_EXPORT Dart_Handle Dart_TypeVoid() {
+  DARTSCOPE(Thread::Current());
+  CHECK_CALLBACK_STATE(T);
+  API_TIMELINE_DURATION(T);
+  return Api::NewHandle(T, Type::VoidType());
+}
+
+DART_EXPORT Dart_Handle Dart_TypeNever() {
+  DARTSCOPE(Thread::Current());
+  CHECK_CALLBACK_STATE(T);
+  API_TIMELINE_DURATION(T);
+  return Api::NewHandle(T, Type::NeverType());
 }
 
 DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
@@ -2268,7 +2289,8 @@
 #if defined(DEBUG)
     const Library& lib = Library::Handle(Z, owner.library());
     if (lib.IsNull()) {
-      ASSERT(owner.IsDynamicClass() || owner.IsVoidClass());
+      ASSERT(owner.IsDynamicClass() || owner.IsVoidClass() ||
+             owner.IsNeverClass());
     }
 #endif
     return Api::NewHandle(T, owner.library());
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 218778c..f6860f2 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -798,6 +798,46 @@
   Dart_Handle empty = Dart_EmptyString();
   EXPECT_VALID(empty);
   EXPECT(!Dart_IsNull(empty));
+  EXPECT(Dart_IsString(empty));
+  intptr_t length = -1;
+  EXPECT_VALID(Dart_StringLength(empty, &length));
+  EXPECT_EQ(0, length);
+}
+
+TEST_CASE(DartAPI_TypeDynamic) {
+  Dart_Handle type = Dart_TypeDynamic();
+  EXPECT_VALID(type);
+  EXPECT(Dart_IsType(type));
+
+  Dart_Handle str = Dart_ToString(type);
+  EXPECT_VALID(str);
+  const char* cstr = nullptr;
+  EXPECT_VALID(Dart_StringToCString(str, &cstr));
+  EXPECT_STREQ("dynamic", cstr);
+}
+
+TEST_CASE(DartAPI_TypeVoid) {
+  Dart_Handle type = Dart_TypeVoid();
+  EXPECT_VALID(type);
+  EXPECT(Dart_IsType(type));
+
+  Dart_Handle str = Dart_ToString(type);
+  EXPECT_VALID(str);
+  const char* cstr = nullptr;
+  EXPECT_VALID(Dart_StringToCString(str, &cstr));
+  EXPECT_STREQ("void", cstr);
+}
+
+TEST_CASE(DartAPI_TypeNever) {
+  Dart_Handle type = Dart_TypeNever();
+  EXPECT_VALID(type);
+  EXPECT(Dart_IsType(type));
+
+  Dart_Handle str = Dart_ToString(type);
+  EXPECT_VALID(str);
+  const char* cstr = nullptr;
+  EXPECT_VALID(Dart_StringToCString(str, &cstr));
+  EXPECT_STREQ("Never", cstr);
 }
 
 TEST_CASE(DartAPI_IdentityEquals) {
@@ -1142,11 +1182,6 @@
   const char* str = NULL;
   Dart_StringToCString(lib_url, &str);
   EXPECT_STREQ("dart:core", str);
-
-  // Case with no library.
-  type = Dart_GetType(lib, NewString("dynamic"), 0, NULL);
-  EXPECT_VALID(type);
-  EXPECT(Dart_IsNull(Dart_ClassLibrary(type)));
 }
 
 TEST_CASE(DartAPI_BooleanValues) {
@@ -5051,7 +5086,9 @@
       "  ChannelReadResult(this.handles);\n"
       "}\n"
       "void expectListOfString(List<String> _) {}\n"
-      "void expectListOfDynamic(List<dynamic> _) {}\n";
+      "void expectListOfDynamic(List<dynamic> _) {}\n"
+      "void expectListOfVoid(List<void> _) {}\n"
+      "void expectListOfNever(List<Never> _) {}\n";
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
 
   Dart_Handle zxhandle_type = Dart_GetType(lib, NewString("ZXHandle"), 0, NULL);
@@ -5093,14 +5130,28 @@
   EXPECT_VALID(
       Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args));
 
-  Dart_Handle dynamic_type =
-      Dart_GetType(dart_core, NewString("dynamic"), 0, NULL);
+  Dart_Handle dynamic_type = Dart_TypeDynamic();
   EXPECT_VALID(dynamic_type);
-  Dart_Handle dynamic_list = Dart_NewListOfType(string_type, 0);
+  Dart_Handle dynamic_list = Dart_NewListOfType(dynamic_type, 0);
   EXPECT_VALID(dynamic_list);
   args[0] = dynamic_list;
   EXPECT_VALID(
       Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args));
+
+  Dart_Handle void_type = Dart_TypeVoid();
+  EXPECT_VALID(void_type);
+  Dart_Handle void_list = Dart_NewListOfType(void_type, 0);
+  EXPECT_VALID(void_list);
+  args[0] = void_list;
+  EXPECT_VALID(Dart_Invoke(lib, NewString("expectListOfVoid"), kNumArgs, args));
+
+  Dart_Handle never_type = Dart_TypeNever();
+  EXPECT_VALID(never_type);
+  Dart_Handle never_list = Dart_NewListOfType(never_type, 0);
+  EXPECT_VALID(never_list);
+  args[0] = never_list;
+  EXPECT_VALID(
+      Dart_Invoke(lib, NewString("expectListOfNever"), kNumArgs, args));
 }
 
 static Dart_Handle PrivateLibName(Dart_Handle lib, const char* str) {
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 20da256..6ae12e6 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -51,6 +51,23 @@
   R(support_disassembler, false, bool, true, "Support the disassembler.")
 #endif
 
+// List of VM-global (i.e. non-isolate specific) flags.
+//
+// The value used for those flags at snapshot generation time needs to be the
+// same as during runtime. Currently, only boolean flags are supported.
+//
+// The syntax used is the same as that for FLAG_LIST below, as these flags are
+// automatically included in FLAG_LIST.
+#define VM_GLOBAL_FLAG_LIST(P, R, C, D)                                        \
+  P(dwarf_stack_traces, bool, false,                                           \
+    "Emit DWARF line number and inlining info"                                 \
+    "in dylib snapshots and don't symbolize stack traces.")                    \
+  P(causal_async_stacks, bool, !USING_PRODUCT, "Improved async stacks")        \
+  P(lazy_async_stacks, bool, false, "Reconstruct async stacks from listeners") \
+  P(use_bare_instructions, bool, true, "Enable bare instructions mode.")       \
+  R(dedup_instructions, true, bool, false,                                     \
+    "Canonicalize instructions when precompiling.")
+
 // List of all flags in the VM.
 // Flags can be one of four categories:
 // * P roduct flags: Can be set in any of the deployment modes, including in
@@ -67,6 +84,8 @@
 //   C(name, precompiled_value, product_value, type, default_value, comment)
 //   D(name, type, default_value, comment)
 #define FLAG_LIST(P, R, C, D)                                                  \
+  VM_GLOBAL_FLAG_LIST(P, R, C, D)                                              \
+  DISASSEMBLE_FLAGS(P, R, C, D)                                                \
   P(experimental_unsafe_mode_use_at_your_own_risk, bool, false,                \
     "Omit runtime strong mode type checks and disable optimizations based on " \
     "types.")                                                                  \
@@ -76,7 +95,8 @@
     "Debugger support async functions.")                                       \
   P(background_compilation, bool, kDartUseBackgroundCompilation,               \
     "Run optimizing compilation in background")                                \
-  P(causal_async_stacks, bool, !USING_PRODUCT, "Improved async stacks")        \
+  R(code_comments, false, bool, false,                                         \
+    "Include comments into code and disassembly.")                             \
   P(collect_code, bool, false, "Attempt to GC infrequently used code.")        \
   P(collect_dynamic_function_names, bool, true,                                \
     "Collects all dynamic function names to identify unique targets")          \
@@ -87,22 +107,14 @@
     "-1 means never")                                                          \
   P(concurrent_mark, bool, true, "Concurrent mark for old generation.")        \
   P(concurrent_sweep, bool, true, "Concurrent sweep for old generation.")      \
-  R(dedup_instructions, true, bool, false,                                     \
-    "Canonicalize instructions when precompiling.")                            \
   C(deoptimize_alot, false, false, bool, false,                                \
     "Deoptimizes we are about to return to Dart code from native entries.")    \
   C(deoptimize_every, 0, 0, int, 0,                                            \
     "Deoptimize on every N stack overflow checks")                             \
   R(disable_alloc_stubs_after_gc, false, bool, false, "Stress testing flag.")  \
-  DISASSEMBLE_FLAGS(P, R, C, D)                                                \
-  R(code_comments, false, bool, false,                                         \
-    "Include comments into code and disassembly.")                             \
   R(dump_megamorphic_stats, false, bool, false,                                \
     "Dump megamorphic cache statistics")                                       \
   R(dump_symbol_stats, false, bool, false, "Dump symbol table statistics")     \
-  P(dwarf_stack_traces, bool, false,                                           \
-    "Emit DWARF line number and inlining info"                                 \
-    "in dylib snapshots and don't symbolize stack traces.")                    \
   R(enable_asserts, false, bool, false, "Enable assert statements.")           \
   P(enable_kernel_expression_compilation, bool, true,                          \
     "Compile expressions with the Kernel front-end.")                          \
@@ -124,7 +136,6 @@
   P(idle_duration_micros, int, 500 * kMicrosecondsPerMillisecond,              \
     "Allow idle tasks to run for this long.")                                  \
   P(interpret_irregexp, bool, false, "Use irregexp bytecode interpreter")      \
-  P(lazy_async_stacks, bool, false, "Reconstruct async stacks from listeners") \
   P(lazy_dispatchers, bool, true, "Generate dispatchers lazily")               \
   P(link_natives_lazily, bool, false, "Link native calls lazily")              \
   R(log_marker_tasks, false, bool, false,                                      \
@@ -177,7 +188,6 @@
     "Stress test async stack traces")                                          \
   P(strong_non_nullable_type_checks, bool, false,                              \
     "Enable strong non-nullable type checking mode.")                          \
-  P(use_bare_instructions, bool, true, "Enable bare instructions mode.")       \
   P(use_table_dispatch, bool, true, "Enable dispatch table based calls.")      \
   P(enable_isolate_groups, bool, false, "Enable isolate group support.")       \
   P(show_invisible_frames, bool, false,                                        \
@@ -239,17 +249,4 @@
     "Throw API error on invalid member access throuh native API. See "         \
     "entry_point_pragma.md")
 
-// List of VM-global (i.e. non-isolate specific) flags.
-//
-// The value used for those flags at snapshot generation time needs to be the
-// same as during runtime. Currently only boolean flags are supported.
-//
-// Usage:
-//   V(name, command-line-flag-name)
-#define VM_GLOBAL_FLAG_LIST(V)                                                 \
-  V(dwarf_stack_traces, FLAG_dwarf_stack_traces)                               \
-  V(causal_async_stacks, FLAG_causal_async_stacks)                             \
-  V(lazy_async_stacks, FLAG_lazy_async_stacks)                                 \
-  V(use_bare_instructions, FLAG_use_bare_instructions)
-
 #endif  // RUNTIME_VM_FLAG_LIST_H_
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index d70d64e..9b05b88 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -78,6 +78,12 @@
 #define NOT_IN_PRECOMPILED(code) code
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
+#if defined(DART_PRECOMPILED_RUNTIME)
+#define ONLY_IN_PRECOMPILED(code) code
+#else
+#define ONLY_IN_PRECOMPILED(code)
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
     defined(TARGET_ARCH_X64)
 #define ONLY_IN_ARM_ARM64_X64(code) code
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index fafb257..51265aa 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -37,7 +37,7 @@
            intptr_t max_new_gen_semi_words,
            intptr_t max_old_gen_words)
     : isolate_(isolate),
-      new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset),
+      new_space_(this, max_new_gen_semi_words),
       old_space_(this, max_old_gen_words),
       barrier_(),
       barrier_done_(),
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 1c3048b..1e9f008 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -421,12 +421,9 @@
 // on the device's actual speed.
 static const intptr_t kConservativeInitialScavengeSpeed = 40;
 
-Scavenger::Scavenger(Heap* heap,
-                     intptr_t max_semi_capacity_in_words,
-                     uword object_alignment)
+Scavenger::Scavenger(Heap* heap, intptr_t max_semi_capacity_in_words)
     : heap_(heap),
       max_semi_capacity_in_words_(max_semi_capacity_in_words),
-      object_alignment_(object_alignment),
       scavenging_(false),
       delayed_weak_properties_(NULL),
       gc_time_micros_(0),
@@ -1009,7 +1006,7 @@
     return 0;
   }
   ASSERT(to_->Contains(result));
-  ASSERT((result & kObjectAlignmentMask) == object_alignment_);
+  ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
   top_ += size;
   ASSERT(to_->Contains(top_) || (top_ == to_->end()));
   ASSERT(result < top_);
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 7e5f623..8591cb8 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -114,9 +114,7 @@
 
 class Scavenger {
  public:
-  Scavenger(Heap* heap,
-            intptr_t max_semi_capacity_in_words,
-            uword object_alignment);
+  Scavenger(Heap* heap, intptr_t max_semi_capacity_in_words);
   ~Scavenger();
 
   // Check whether this Scavenger contains this address.
@@ -140,7 +138,7 @@
     // the new to_ space. It must succeed.
     ASSERT(size <= remaining);
     ASSERT(to_->Contains(result));
-    ASSERT((result & kObjectAlignmentMask) == object_alignment_);
+    ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
     top_ += size;
     ASSERT((to_->Contains(top_)) || (top_ == to_->end()));
     return result;
@@ -157,7 +155,7 @@
       return 0;
     }
     ASSERT(to_->Contains(result));
-    ASSERT((result & kObjectAlignmentMask) == object_alignment_);
+    ASSERT((result & kObjectAlignmentMask) == kNewObjectAlignmentOffset);
     top += size;
     ASSERT((to_->Contains(top)) || (top == to_->end()));
     thread->set_top(top);
@@ -237,7 +235,9 @@
     kToKBAfterStoreBuffer = 3
   };
 
-  uword FirstObjectStart() const { return to_->start() | object_alignment_; }
+  uword FirstObjectStart() const {
+    return to_->start() + kNewObjectAlignmentOffset;
+  }
   SemiSpace* Prologue(Isolate* isolate);
   void IterateStoreBuffers(Isolate* isolate, ScavengerVisitor* visitor);
   void IterateObjectIdTable(Isolate* isolate, ScavengerVisitor* visitor);
@@ -298,9 +298,6 @@
 
   intptr_t max_semi_capacity_in_words_;
 
-  // All object are aligned to this value.
-  uword object_alignment_;
-
   // Keep track whether a scavenge is currently running.
   bool scavenging_;
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index f3bae71..e740d1b 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -5,6 +5,7 @@
 #include "vm/image_snapshot.h"
 
 #include "platform/assert.h"
+#include "vm/class_id.h"
 #include "vm/compiler/backend/code_statistics.h"
 #include "vm/compiler/runtime_api.h"
 #include "vm/dwarf.h"
@@ -135,6 +136,25 @@
   return offset;
 }
 
+static intptr_t InstructionsSizeInSnapshot(RawInstructions* raw) {
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    // Currently, we align bare instruction payloads on 4 byte boundaries.
+    //
+    // If we later decide to align on larger boundaries to put entries at the
+    // start of cache lines, make sure to account for entry points that are
+    // _not_ at the start of the payload.
+    return Utils::RoundUp(Instructions::Size(raw),
+                          ImageWriter::kBareInstructionsAlignment);
+  }
+#if defined(IS_SIMARM_X64)
+  return Utils::RoundUp(
+      compiler::target::Instructions::HeaderSize() + Instructions::Size(raw),
+      compiler::target::ObjectAlignment::kObjectAlignment);
+#else
+  return raw->HeapSize();
+#endif
+}
+
 #if defined(IS_SIMARM_X64)
 static intptr_t CompressedStackMapsSizeInSnapshot(intptr_t payload_size) {
   // We do not need to round the non-payload size up to a word boundary because
@@ -171,11 +191,6 @@
                         compiler::target::ObjectAlignment::kObjectAlignment);
 }
 
-static intptr_t InstructionsSizeInSnapshot(intptr_t len) {
-  return Utils::RoundUp(compiler::target::Instructions::HeaderSize() + len,
-                        compiler::target::ObjectAlignment::kObjectAlignment);
-}
-
 intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
   const classid_t cid = raw_object->GetClassId();
 
@@ -201,7 +216,7 @@
     }
     case kInstructionsCid: {
       RawInstructions* raw_insns = static_cast<RawInstructions*>(raw_object);
-      return InstructionsSizeInSnapshot(Instructions::Size(raw_insns));
+      return InstructionsSizeInSnapshot(raw_insns);
     }
     default: {
       const Class& clazz = Class::Handle(Object::Handle(raw_object).clazz());
@@ -211,8 +226,13 @@
   }
 }
 #else   // defined(IS_SIMARM_X64)
-intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
-  return raw_object->HeapSize();
+intptr_t ImageWriter::SizeInSnapshot(RawObject* raw) {
+  switch (raw->GetClassId()) {
+    case kInstructionsCid:
+      return InstructionsSizeInSnapshot(static_cast<RawInstructions*>(raw));
+    default:
+      return raw->HeapSize();
+  }
 }
 #endif  // defined(IS_SIMARM_X64)
 
@@ -371,6 +391,10 @@
 #endif
 
 #if defined(IS_SIMARM_X64)
+    static_assert(
+        kObjectAlignment ==
+            compiler::target::ObjectAlignment::kObjectAlignment * 2,
+        "host object alignment is not double target object alignment");
     if (obj.IsCompressedStackMaps()) {
       const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
 
@@ -556,6 +580,9 @@
 #else
   Zone* zone = Thread::Current()->zone();
 
+  const bool bare_instruction_payloads =
+      FLAG_precompiled_mode && FLAG_use_bare_instructions;
+
 #if defined(DART_PRECOMPILER)
   const char* bss_symbol =
       vm ? "_kDartVmSnapshotBss" : "_kDartIsolateSnapshotBss";
@@ -572,13 +599,14 @@
 
   // Start snapshot at page boundary.
   ASSERT(VirtualMemory::PageSize() >= kMaxObjectAlignment);
-  assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
+  Align(VirtualMemory::PageSize());
   assembly_stream_.Print("%s:\n", instructions_symbol);
 
   // This head also provides the gap to make the instructions snapshot
   // look like a HeapPage.
-  intptr_t instructions_length = next_text_offset_;
-  WriteWordLiteralText(instructions_length);
+  const intptr_t image_size = Utils::RoundUp(
+      next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
+  WriteWordLiteralText(image_size);
 
 #if defined(DART_PRECOMPILER)
   assembly_stream_.Print("%s %s - %s\n", kLiteralPrefix, bss_symbol,
@@ -592,6 +620,51 @@
     WriteWordLiteralText(0);
   }
 
+  if (bare_instruction_payloads) {
+    const intptr_t section_size = image_size - Image::kHeaderSize;
+    // Add the RawInstructionsSection header.
+    uword marked_tags = 0;
+    marked_tags = RawObject::OldBit::update(true, marked_tags);
+    marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
+#if defined(IS_SIMARM_X64)
+    static_assert(
+        kObjectAlignment ==
+            compiler::target::ObjectAlignment::kObjectAlignment * 2,
+        "host object alignment is not double target object alignment");
+    marked_tags = RawObject::SizeTag::update(2 * section_size, marked_tags);
+#else
+    marked_tags = RawObject::SizeTag::update(section_size, marked_tags);
+#endif
+    marked_tags =
+        RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
+
+    WriteWordLiteralText(marked_tags);
+    // Calculated using next_text_offset_, which doesn't include post-payload
+    // padding to object alignment.
+    const intptr_t instructions_length =
+        next_text_offset_ - Image::kHeaderSize -
+        compiler::target::InstructionsSection::HeaderSize();
+    WriteWordLiteralText(instructions_length);
+
+    if (profile_writer_ != nullptr) {
+      const intptr_t offset = Image::kHeaderSize;
+      const intptr_t non_instruction_bytes =
+          compiler::target::InstructionsSection::HeaderSize();
+      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
+                                            "InstructionsSection",
+                                            /*name=*/nullptr);
+      profile_writer_->AttributeBytesTo({offset_space_, offset},
+                                        non_instruction_bytes);
+      profile_writer_->AddRoot({offset_space_, offset});
+    }
+  }
+
+  const intptr_t section_headers_size =
+      Image::kHeaderSize +
+      (bare_instruction_payloads
+           ? compiler::target::InstructionsSection::HeaderSize()
+           : 0);
+
   FrameUnwindPrologue();
 
   PcDescriptors& descriptors = PcDescriptors::Handle(zone);
@@ -604,9 +677,19 @@
     const bool is_trampoline = data.trampoline_bytes != nullptr;
     ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
 
+    if (bare_instruction_payloads && profile_writer_ != nullptr) {
+      const intptr_t instructions_sections_offset = Image::kHeaderSize;
+      const intptr_t offset = section_headers_size + text_offset;
+      profile_writer_->AttributeReferenceTo(
+          {offset_space_, instructions_sections_offset},
+          {{offset_space_, offset},
+           V8SnapshotProfileWriter::Reference::kElement,
+           text_offset});
+    }
+
     if (is_trampoline) {
       if (profile_writer_ != nullptr) {
-        const intptr_t offset = Image::kHeaderSize + text_offset;
+        const intptr_t offset = section_headers_size + text_offset;
         profile_writer_->SetObjectTypeAndName({offset_space_, offset},
                                               "Trampolines",
                                               /*name=*/nullptr);
@@ -629,7 +712,7 @@
     descriptors = data.code_->pc_descriptors();
 
     if (profile_writer_ != nullptr) {
-      const intptr_t offset = Image::kHeaderSize + text_offset;
+      const intptr_t offset = section_headers_size + text_offset;
       profile_writer_->SetObjectTypeAndName({offset_space_, offset},
                                             "Instructions",
                                             /*name=*/nullptr);
@@ -637,9 +720,12 @@
                                         SizeInSnapshot(insns.raw()));
     }
 
+    const uword payload_start = insns.PayloadStart();
+
     // 1. Write from the object start to the payload start. This includes the
-    // object header and the fixed fields.
-    {
+    // object header and the fixed fields.  Not written for AOT snapshots using
+    // bare instructions.
+    if (!bare_instruction_payloads) {
       NoSafepointScope no_safepoint;
 
       // Write Instructions with the mark and read-only bits set.
@@ -656,7 +742,7 @@
 #endif
 
 #if defined(IS_SIMARM_X64)
-      const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.Size());
+      const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
       marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
       WriteWordLiteralText(marked_tags);
       text_offset += sizeof(compiler::target::uword);
@@ -664,7 +750,6 @@
       text_offset += sizeof(compiler::target::uword);
 #else   // defined(IS_SIMARM_X64)
       uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
-      uword payload_start = insns.PayloadStart();
       WriteWordLiteralText(marked_tags);
       object_start += sizeof(uword);
       text_offset += sizeof(uword);
@@ -683,7 +768,7 @@
     }
     if (debug_dwarf_ != nullptr) {
       auto const virtual_address =
-          debug_segment_base + Image::kHeaderSize + text_offset;
+          debug_segment_base + section_headers_size + text_offset;
       debug_dwarf_->AddCode(code, virtual_address);
     }
 #endif
@@ -692,19 +777,29 @@
     assembly_stream_.Print("%s:\n", namer.AssemblyNameFor(dwarf_index, code));
 
     {
-      // 3. Write from the payload start to payload end.
+      // 3. Write from the payload start to payload end. For AOT snapshots
+      // with bare instructions, this is the only part serialized.
       NoSafepointScope no_safepoint;
-      const uword payload_start = insns.PayloadStart();
-      const uword payload_size =
-          Utils::RoundUp(insns.Size(), sizeof(compiler::target::uword));
+      assert(kBareInstructionsAlignment <=
+             compiler::target::ObjectAlignment::kObjectAlignment);
+      const auto payload_align = bare_instruction_payloads
+                                     ? kBareInstructionsAlignment
+                                     : sizeof(compiler::target::uword);
+      const uword payload_size = Utils::RoundUp(insns.Size(), payload_align);
       const uword payload_end = payload_start + payload_size;
 
+      ASSERT(Utils::IsAligned(text_offset, payload_align));
+
 #if defined(DART_PRECOMPILER)
       PcDescriptors::Iterator iterator(descriptors,
                                        RawPcDescriptors::kBSSRelocation);
       uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
 
-      for (uword cursor = payload_start; cursor < payload_end;
+      // We only generate BSS relocations that are word-sized and at
+      // word-aligned offsets in the payload.
+      auto const possible_relocations_end =
+          Utils::RoundDown(payload_end, sizeof(compiler::target::uword));
+      for (uword cursor = payload_start; cursor < possible_relocations_end;
            cursor += sizeof(compiler::target::uword)) {
         compiler::target::uword data =
             *reinterpret_cast<compiler::target::uword*>(cursor);
@@ -716,6 +811,8 @@
           WriteWordLiteralText(data);
         }
       }
+      assert(next_reloc_offset != (possible_relocations_end - payload_start));
+      WriteByteSequence(possible_relocations_end, payload_end);
       text_offset += payload_size;
 #else
       text_offset += WriteByteSequence(payload_start, payload_end);
@@ -723,26 +820,39 @@
 
       // 4. Write from the payload end to object end. Note we can't simply copy
       // from the object because the host object may have less alignment filler
-      // than the target object in the cross-word case.
-      uword unaligned_size =
-          compiler::target::Instructions::HeaderSize() + payload_size;
-      uword alignment_size =
-          Utils::RoundUp(unaligned_size,
-                         compiler::target::ObjectAlignment::kObjectAlignment) -
-          unaligned_size;
-      while (alignment_size > 0) {
-        WriteWordLiteralText(compiler::Assembler::GetBreakInstructionFiller());
-        alignment_size -= sizeof(compiler::target::uword);
-        text_offset += sizeof(compiler::target::uword);
-      }
+      // than the target object in the cross-word case. Not written for AOT
+      // snapshots using bare instructions.
+      if (!bare_instruction_payloads) {
+        uword unaligned_size =
+            compiler::target::Instructions::HeaderSize() + payload_size;
+        uword alignment_size =
+            Utils::RoundUp(
+                unaligned_size,
+                compiler::target::ObjectAlignment::kObjectAlignment) -
+            unaligned_size;
+        while (alignment_size > 0) {
+          WriteWordLiteralText(
+              compiler::Assembler::GetBreakInstructionFiller());
+          alignment_size -= sizeof(compiler::target::uword);
+          text_offset += sizeof(compiler::target::uword);
+        }
 
-      ASSERT(kWordSize != compiler::target::kWordSize ||
-             (text_offset - instr_start) == insns.raw()->HeapSize());
+        ASSERT(kWordSize != compiler::target::kWordSize ||
+               (text_offset - instr_start) == insns.raw()->HeapSize());
+      }
     }
 
     ASSERT((text_offset - instr_start) == SizeInSnapshot(insns.raw()));
   }
 
+  // Should be a no-op unless writing bare instruction payloads, in which case
+  // we need to add post-payload padding to the object alignment. The alignment
+  // needs to match the one we used for image_size above.
+  text_offset +=
+      Align(compiler::target::ObjectAlignment::kObjectAlignment, text_offset);
+
+  ASSERT_EQUAL(section_headers_size + text_offset, image_size);
+
   FrameUnwindEpilogue();
 
 #if defined(DART_PRECOMPILER)
@@ -763,7 +873,7 @@
     // we can pass nullptr for the bytes of the section/segment.
     auto const debug_segment_base2 =
         debug_dwarf_->elf()->AddText(instructions_symbol, /*bytes=*/nullptr,
-                                     Image::kHeaderSize + text_offset);
+                                     section_headers_size + text_offset);
     ASSERT(debug_segment_base2 == debug_segment_base);
   }
 
@@ -788,7 +898,7 @@
   const char* data_symbol =
       vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData";
   assembly_stream_.Print(".globl %s\n", data_symbol);
-  assembly_stream_.Print(".balign %" Pd ", 0\n", kMaxObjectAlignment);
+  Align(kMaxObjectAlignment);
   assembly_stream_.Print("%s:\n", data_symbol);
   uword buffer = reinterpret_cast<uword>(clustered_stream->buffer());
   intptr_t length = clustered_stream->bytes_written();
@@ -874,13 +984,33 @@
 }
 
 intptr_t AssemblyImageWriter::WriteByteSequence(uword start, uword end) {
-  for (auto* cursor = reinterpret_cast<compiler::target::uword*>(start);
-       cursor < reinterpret_cast<compiler::target::uword*>(end); cursor++) {
+  assert(end >= start);
+  auto const end_of_words =
+      Utils::RoundDown(end, sizeof(compiler::target::uword));
+  for (auto cursor = reinterpret_cast<compiler::target::uword*>(start);
+       cursor < reinterpret_cast<compiler::target::uword*>(end_of_words);
+       cursor++) {
     WriteWordLiteralText(*cursor);
   }
+  if (end != end_of_words) {
+    auto start_of_rest = reinterpret_cast<const uint8_t*>(end_of_words);
+    assembly_stream_.Print(".byte ");
+    for (auto cursor = start_of_rest;
+         cursor < reinterpret_cast<const uint8_t*>(end); cursor++) {
+      if (cursor != start_of_rest) assembly_stream_.Print(", ");
+      assembly_stream_.Print("0x%0.2" Px "", *cursor);
+    }
+    assembly_stream_.Print("\n");
+  }
   return end - start;
 }
 
+intptr_t AssemblyImageWriter::Align(intptr_t alignment, uword position) {
+  const uword next_position = Utils::RoundUp(position, alignment);
+  assembly_stream_.Print(".balign %" Pd ", 0\n", alignment);
+  return next_position - position;
+}
+
 BlobImageWriter::BlobImageWriter(Thread* thread,
                                  uint8_t** instructions_blob_buffer,
                                  ReAlloc alloc,
@@ -912,7 +1042,9 @@
 }
 
 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
-  const intptr_t instructions_length = next_text_offset_;
+  const bool bare_instruction_payloads =
+      FLAG_precompiled_mode && FLAG_use_bare_instructions;
+
 #ifdef DART_PRECOMPILER
   intptr_t segment_base = 0;
   if (elf_ != nullptr) {
@@ -926,7 +1058,9 @@
 
   // This header provides the gap to make the instructions snapshot look like a
   // HeapPage.
-  instructions_blob_stream_.WriteTargetWord(instructions_length);
+  const intptr_t image_size = Utils::RoundUp(
+      next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
+  instructions_blob_stream_.WriteTargetWord(image_size);
 #if defined(DART_PRECOMPILER)
   instructions_blob_stream_.WriteTargetWord(
       elf_ != nullptr ? bss_base_ - segment_base : 0);
@@ -939,6 +1073,44 @@
     instructions_blob_stream_.WriteTargetWord(0);
   }
 
+  if (bare_instruction_payloads) {
+    const intptr_t section_size = image_size - Image::kHeaderSize;
+    // Add the RawInstructionsSection header.
+    uword marked_tags = 0;
+    marked_tags = RawObject::OldBit::update(true, marked_tags);
+    marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
+#if defined(IS_SIMARM_X64)
+    static_assert(
+        kObjectAlignment ==
+            compiler::target::ObjectAlignment::kObjectAlignment * 2,
+        "host object alignment is not double target object alignment");
+    marked_tags = RawObject::SizeTag::update(2 * section_size, marked_tags);
+#else
+    marked_tags = RawObject::SizeTag::update(section_size, marked_tags);
+#endif
+    marked_tags =
+        RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
+
+    instructions_blob_stream_.WriteTargetWord(marked_tags);
+    // Uses next_text_offset_ to avoid any post-payload padding.
+    const intptr_t instructions_length =
+        next_text_offset_ - Image::kHeaderSize -
+        compiler::target::InstructionsSection::HeaderSize();
+    instructions_blob_stream_.WriteTargetWord(instructions_length);
+
+    if (profile_writer_ != nullptr) {
+      const intptr_t offset = Image::kHeaderSize;
+      const intptr_t non_instruction_bytes =
+          compiler::target::InstructionsSection::HeaderSize();
+      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
+                                            "InstructionsSection",
+                                            /*name=*/nullptr);
+      profile_writer_->AttributeBytesTo({offset_space_, offset},
+                                        non_instruction_bytes);
+      profile_writer_->AddRoot({offset_space_, offset});
+    }
+  }
+
   intptr_t text_offset = 0;
 
 #if defined(DART_PRECOMPILER)
@@ -952,6 +1124,15 @@
     const bool is_trampoline = data.trampoline_bytes != nullptr;
     ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
 
+    if (bare_instruction_payloads && profile_writer_ != nullptr) {
+      const intptr_t instructions_sections_offset = Image::kHeaderSize;
+      profile_writer_->AttributeReferenceTo(
+          {offset_space_, instructions_sections_offset},
+          {{offset_space_, instructions_blob_stream_.Position()},
+           V8SnapshotProfileWriter::Reference::kElement,
+           text_offset});
+    }
+
     if (is_trampoline) {
       const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
       const auto end = start + data.trampline_length;
@@ -965,17 +1146,9 @@
 
     const Instructions& insns = *instructions_[i].insns_;
     AutoTraceImage(insns, 0, &this->instructions_blob_stream_);
+    const uword payload_start = insns.PayloadStart();
 
-    uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
-    uword payload_start = insns.PayloadStart();
-    uword payload_size =
-        Utils::RoundUp(
-            compiler::target::Instructions::HeaderSize() + insns.Size(),
-            compiler::target::ObjectAlignment::kObjectAlignment) -
-        compiler::target::Instructions::HeaderSize();
-    uword object_end = payload_start + payload_size;
-
-    ASSERT(Utils::IsAligned(payload_start, sizeof(uword)));
+    ASSERT(Utils::IsAligned(payload_start, sizeof(compiler::target::uword)));
 
     // Write Instructions with the mark and read-only bits set.
     uword marked_tags = insns.raw_ptr()->tags_;
@@ -989,32 +1162,51 @@
     marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
 #endif
 
-    intptr_t payload_stream_start = 0;
-
 #if defined(IS_SIMARM_X64)
     const intptr_t start_offset = instructions_blob_stream_.bytes_written();
-    const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.Size());
-    marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
-    instructions_blob_stream_.WriteTargetWord(marked_tags);
-    instructions_blob_stream_.WriteFixed<uint32_t>(
-        insns.raw_ptr()->size_and_flags_);
-    payload_stream_start = instructions_blob_stream_.Position();
+
+    if (!bare_instruction_payloads) {
+      const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
+      ASSERT_EQUAL(kObjectAlignment,
+                   compiler::target::ObjectAlignment::kObjectAlignment * 2);
+      marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
+      instructions_blob_stream_.WriteTargetWord(marked_tags);
+      instructions_blob_stream_.WriteFixed<uint32_t>(
+          insns.raw_ptr()->size_and_flags_);
+    } else {
+      ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
+                              kBareInstructionsAlignment));
+    }
+    const intptr_t payload_stream_start = instructions_blob_stream_.Position();
     instructions_blob_stream_.WriteBytes(
         reinterpret_cast<const void*>(insns.PayloadStart()), insns.Size());
-    instructions_blob_stream_.Align(
-        compiler::target::ObjectAlignment::kObjectAlignment);
+    const intptr_t alignment =
+        bare_instruction_payloads
+            ? kBareInstructionsAlignment
+            : compiler::target::ObjectAlignment::kObjectAlignment;
+    instructions_blob_stream_.Align(alignment);
     const intptr_t end_offset = instructions_blob_stream_.bytes_written();
     text_offset += (end_offset - start_offset);
-    USE(object_start);
-    USE(object_end);
 #else   // defined(IS_SIMARM_X64)
-    payload_stream_start = instructions_blob_stream_.Position() +
-                           (insns.PayloadStart() - object_start);
-
-    instructions_blob_stream_.WriteWord(marked_tags);
-    text_offset += sizeof(uword);
-    object_start += sizeof(uword);
-    text_offset += WriteByteSequence(object_start, object_end);
+    // Only payload is output in AOT snapshots.
+    const uword header_size =
+        bare_instruction_payloads
+            ? 0
+            : compiler::target::Instructions::HeaderSize();
+    const uword payload_size = SizeInSnapshot(insns.raw()) - header_size;
+    const uword object_end = payload_start + payload_size;
+    if (!bare_instruction_payloads) {
+      uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
+      instructions_blob_stream_.WriteWord(marked_tags);
+      text_offset += sizeof(uword);
+      object_start += sizeof(uword);
+      text_offset += WriteByteSequence(object_start, payload_start);
+    } else {
+      ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
+                              kBareInstructionsAlignment));
+    }
+    const intptr_t payload_stream_start = instructions_blob_stream_.Position();
+    text_offset += WriteByteSequence(payload_start, object_end);
 #endif
 
 #if defined(DART_PRECOMPILER)
@@ -1076,7 +1268,13 @@
            ImageWriter::SizeInSnapshot(insns.raw()));
   }
 
-  ASSERT(instructions_blob_stream_.bytes_written() == instructions_length);
+  // Should be a no-op unless writing bare instruction payloads, in which case
+  // we need to add post-payload padding to the object alignment. The alignment
+  // should match the alignment used in image_size above.
+  instructions_blob_stream_.Align(
+      compiler::target::ObjectAlignment::kObjectAlignment);
+
+  ASSERT_EQUAL(instructions_blob_stream_.bytes_written(), image_size);
 
 #ifdef DART_PRECOMPILER
   const char* instructions_symbol =
@@ -1114,6 +1312,18 @@
   return ApiError::null();
 }
 
+#if defined(DART_PRECOMPILED_RUNTIME)
+uword ImageReader::GetBareInstructionsAt(uint32_t offset) const {
+  ASSERT(Utils::IsAligned(offset, ImageWriter::kBareInstructionsAlignment));
+  return reinterpret_cast<uword>(instructions_image_) + offset;
+}
+
+uword ImageReader::GetBareInstructionsEnd() const {
+  Image image(instructions_image_);
+  return reinterpret_cast<uword>(image.object_start()) + image.object_size();
+}
+#endif
+
 RawInstructions* ImageReader::GetInstructionsAt(uint32_t offset) const {
   ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 691f22c..6c497b2 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -69,6 +69,8 @@
 
   RawApiError* VerifyAlignment() const;
 
+  ONLY_IN_PRECOMPILED(uword GetBareInstructionsAt(uint32_t offset) const);
+  ONLY_IN_PRECOMPILED(uword GetBareInstructionsEnd() const);
   RawInstructions* GetInstructionsAt(uint32_t offset) const;
   RawObject* GetObjectAt(uint32_t offset) const;
 
@@ -153,6 +155,9 @@
   void ResetOffsets() {
     next_data_offset_ = Image::kHeaderSize;
     next_text_offset_ = Image::kHeaderSize;
+    if (FLAG_use_bare_instructions && FLAG_precompiled_mode) {
+      next_text_offset_ += compiler::target::InstructionsSection::HeaderSize();
+    }
     objects_.Clear();
     instructions_.Clear();
   }
@@ -179,6 +184,7 @@
   void TraceInstructions(const Instructions& instructions);
 
   static intptr_t SizeInSnapshot(RawObject* object);
+  static const intptr_t kBareInstructionsAlignment = 4;
 
  protected:
   void WriteROData(WriteStream* stream);
@@ -329,6 +335,7 @@
   void FrameUnwindPrologue();
   void FrameUnwindEpilogue();
   intptr_t WriteByteSequence(uword start, uword end);
+  intptr_t Align(intptr_t alignment, uword position = 0);
 
 #if defined(TARGET_ARCH_IS_64_BIT)
   const char* kLiteralPrefix = ".quad";
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index e1cb029..69eada8 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -750,14 +750,13 @@
 
   const auto& type_params =
       TypeArguments::Handle(zone, function.type_parameters());
-  const NNBDMode nnbd_mode = function.nnbd_mode();
   if (!type_params.IsNull()) {
     auto& type_param = TypeParameter::Handle(zone);
     auto& bound = AbstractType::Handle(zone);
     for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
       type_param ^= type_params.TypeAt(i);
       bound = type_param.bound();
-      if (!bound.IsTopType(nnbd_mode) && !type_param.IsGenericCovariantImpl()) {
+      if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
         return true;
       }
     }
@@ -771,7 +770,7 @@
   auto& type = AbstractType::Handle(zone);
   for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
     type = function.ParameterTypeAt(i);
-    if (!type.IsTopType(nnbd_mode) && !is_generic_covariant_impl.Contains(i) &&
+    if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
         !is_covariant.Contains(i)) {
       return true;
     }
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 187d3c0..d89e50a 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 = 38;
+static const uint32_t kMaxSupportedKernelFormatVersion = 39;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b783ee8..076f004 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1917,8 +1917,8 @@
                        script_class, procedure_helper.start_position_));
   function.set_has_pragma(has_pragma_annotation);
   function.set_end_token_pos(procedure_helper.end_position_);
-  function.set_is_no_such_method_forwarder(
-      procedure_helper.IsNoSuchMethodForwarder());
+  function.set_is_synthetic(procedure_helper.IsNoSuchMethodForwarder() ||
+                            procedure_helper.IsMemberSignature());
   if (register_function) {
     functions_.Add(&function);
   } else {
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index 31ea517..5a4706e 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -45,21 +45,20 @@
  */
 class MutexLocker : public ValueObject {
  public:
-  explicit MutexLocker(Mutex* mutex, bool no_safepoint_scope = true)
+  explicit MutexLocker(Mutex* mutex)
       :
 #if defined(DEBUG)
-        no_safepoint_scope_(no_safepoint_scope),
+        no_safepoint_scope_(true),
 #endif
         mutex_(mutex) {
-    ASSERT(mutex != NULL);
+    ASSERT(mutex != nullptr);
 #if defined(DEBUG)
-    if (no_safepoint_scope_) {
-      Thread* thread = Thread::Current();
-      if (thread != NULL) {
-        thread->IncrementNoSafepointScopeDepth();
-      } else {
-        no_safepoint_scope_ = false;
-      }
+    Thread* thread = Thread::Current();
+    if ((thread != nullptr) &&
+        (thread->execution_state() != Thread::kThreadInNative)) {
+      thread->IncrementNoSafepointScopeDepth();
+    } else {
+      no_safepoint_scope_ = false;
     }
 #endif
     mutex_->Lock();
diff --git a/runtime/vm/native_symbol_win.cc b/runtime/vm/native_symbol_win.cc
index 0a26ebd..d138ab0 100644
--- a/runtime/vm/native_symbol_win.cc
+++ b/runtime/vm/native_symbol_win.cc
@@ -27,7 +27,9 @@
   HANDLE hProcess = GetCurrentProcess();
   if (!SymInitialize(hProcess, NULL, TRUE)) {
     DWORD error = GetLastError();
-    printf("Failed to init NativeSymbolResolver (SymInitialize %d)\n", error);
+    OS::PrintErr("Failed to init NativeSymbolResolver (SymInitialize %" Pu32
+                 ")\n",
+                 error);
     return;
   }
 }
@@ -41,7 +43,9 @@
   HANDLE hProcess = GetCurrentProcess();
   if (!SymCleanup(hProcess)) {
     DWORD error = GetLastError();
-    printf("Failed to shutdown NativeSymbolResolver (SymCleanup  %d)\n", error);
+    OS::PrintErr("Failed to shutdown NativeSymbolResolver (SymCleanup  %" Pu32
+                 ")\n",
+                 error);
   }
 }
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bb16eb8..1084cd5c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -150,6 +150,8 @@
 RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::instructions_section_class_ =
+    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::code_source_map_class_ =
@@ -793,6 +795,9 @@
   cls = Class::New<Instructions, RTN::Instructions>(isolate);
   instructions_class_ = cls.raw();
 
+  cls = Class::New<InstructionsSection, RTN::InstructionsSection>(isolate);
+  instructions_section_class_ = cls.raw();
+
   cls = Class::New<ObjectPool, RTN::ObjectPool>(isolate);
   object_pool_class_ = cls.raw();
 
@@ -1041,13 +1046,7 @@
   void_type_->SetCanonical();
 
   cls = never_class_;
-  *never_type_ =
-      Type::New(cls, Object::null_type_arguments(), TokenPosition::kNoSource,
-                Dart::non_nullable_flag() ? Nullability::kNonNullable
-                                          : Nullability::kLegacy);
-  never_type_->SetIsFinalized();
-  never_type_->ComputeHash();
-  never_type_->SetCanonical();
+  *never_type_ = Type::NewNonParameterizedType(cls);
 
   // Since TypeArguments objects are passed as function arguments, make them
   // behave as Dart instances, although they are just VM objects.
@@ -1227,6 +1226,7 @@
   code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+  instructions_section_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   code_source_map_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -1329,6 +1329,7 @@
   SET_CLASS_NAME(code, Code);
   SET_CLASS_NAME(bytecode, Bytecode);
   SET_CLASS_NAME(instructions, Instructions);
+  SET_CLASS_NAME(instructions_section, InstructionsSection);
   SET_CLASS_NAME(object_pool, ObjectPool);
   SET_CLASS_NAME(code_source_map, CodeSourceMap);
   SET_CLASS_NAME(pc_descriptors, PcDescriptors);
@@ -3920,8 +3921,7 @@
   }
 
   AbstractType& parameter_type = AbstractType::Handle(zone);
-  AbstractType& argument_type =
-      AbstractType::Handle(zone, value.GetType(Heap::kOld));
+  NNBDMode mode = nnbd_mode();
 
   if (field.IsNull()) {
     const Function& setter =
@@ -3939,14 +3939,9 @@
                                InvocationMirror::kSetter);
     }
     parameter_type = setter.ParameterTypeAt(0);
-    if (nnbd_mode() != NNBDMode::kLegacyLib) {
-      // TODO(regis): Make type check nullability aware.
-      UNIMPLEMENTED();
-    }
-    if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
-        !value.IsInstanceOf(nnbd_mode(), parameter_type,
-                            Object::null_type_arguments(),
-                            Object::null_type_arguments())) {
+    if (!value.RuntimeTypeIsSubtypeOf(mode, parameter_type,
+                                      Object::null_type_arguments(),
+                                      Object::null_type_arguments())) {
       const String& argument_name =
           String::Handle(zone, setter.ParameterNameAt(0));
       return ThrowTypeError(setter.token_pos(), value, parameter_type,
@@ -3967,14 +3962,9 @@
   }
 
   parameter_type = field.type();
-  if (nnbd_mode() != NNBDMode::kLegacyLib) {
-    // TODO(regis): Make type check nullability aware.
-    UNIMPLEMENTED();
-  }
-  if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
-      !value.IsInstanceOf(nnbd_mode(), parameter_type,
-                          Object::null_type_arguments(),
-                          Object::null_type_arguments())) {
+  if (!value.RuntimeTypeIsSubtypeOf(mode, parameter_type,
+                                    Object::null_type_arguments(),
+                                    Object::null_type_arguments())) {
     const String& argument_name = String::Handle(zone, field.name());
     return ThrowTypeError(field.token_pos(), value, parameter_type,
                           argument_name);
@@ -4542,6 +4532,8 @@
       return Symbols::Bytecode().ToCString();
     case kInstructionsCid:
       return Symbols::Instructions().ToCString();
+    case kInstructionsSectionCid:
+      return Symbols::InstructionsSection().ToCString();
     case kObjectPoolCid:
       return Symbols::ObjectPool().ToCString();
     case kCodeSourceMapCid:
@@ -4766,7 +4758,7 @@
   ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
   ASSERT((declaration_type() == Object::null()) ||
          (declaration_type() == value.raw()));  // Set during own finalization.
-  // Since declaration type is used as the runtime type of  instances of a
+  // Since declaration type is used as the runtime type of instances of a
   // non-generic class, the nullability is set to kNonNullable instead of
   // kLegacy when the non-nullable experiment is enabled.
   ASSERT(value.type_class_id() != kNullCid || value.IsNullable());
@@ -4874,7 +4866,7 @@
       }
       const AbstractType& other_type_arg =
           AbstractType::Handle(zone, other_type_arguments.TypeAt(0));
-      if (other_type_arg.IsTopType(mode)) {
+      if (other_type_arg.IsTopType()) {
         return true;
       }
       if (!type_arguments.IsNull() && this_class.IsFutureClass()) {
@@ -4904,7 +4896,7 @@
       // below), we only check a subvector of the proper length.
       // Check for covariance.
       if (other_type_arguments.IsNull() ||
-          other_type_arguments.IsTopTypes(mode, from_index, num_type_params)) {
+          other_type_arguments.IsTopTypes(from_index, num_type_params)) {
         return true;
       }
       if (type_arguments.IsNull() ||
@@ -5693,14 +5685,12 @@
   return true;
 }
 
-bool TypeArguments::IsTopTypes(NNBDMode mode,
-                               intptr_t from_index,
-                               intptr_t len) const {
+bool TypeArguments::IsTopTypes(intptr_t from_index, intptr_t len) const {
   ASSERT(Length() >= (from_index + len));
   AbstractType& type = AbstractType::Handle();
   for (intptr_t i = 0; i < len; i++) {
     type = TypeAt(from_index + i);
-    if (type.IsNull() || !type.IsTopType(mode)) {
+    if (type.IsNull() || !type.IsTopType()) {
       return false;
     }
   }
@@ -7713,7 +7703,7 @@
                                         Heap::Space space) const {
   const AbstractType& param_type =
       AbstractType::Handle(ParameterTypeAt(parameter_position));
-  if (param_type.IsTopType(mode)) {
+  if (param_type.IsTopType()) {
     return true;
   }
   const AbstractType& other_param_type =
@@ -7793,7 +7783,7 @@
   const AbstractType& other_res_type =
       AbstractType::Handle(zone, other.result_type());
   // 'void Function()' is a subtype of 'Object Function()'.
-  if (!other_res_type.IsTopType(mode)) {
+  if (!other_res_type.IsTopType()) {
     const AbstractType& res_type = AbstractType::Handle(zone, result_type());
     if (!res_type.IsSubtypeOf(mode, other_res_type, space)) {
       return false;
@@ -7898,7 +7888,7 @@
   result.set_is_generated_body(false);
   result.set_has_pragma(false);
   result.set_is_polymorphic_target(false);
-  result.set_is_no_such_method_forwarder(false);
+  result.set_is_synthetic(false);
   NOT_IN_PRECOMPILED(result.set_state_bits(0));
   result.set_owner(owner);
   NOT_IN_PRECOMPILED(result.set_token_pos(token_pos));
@@ -8101,14 +8091,23 @@
   }
   closure_function.InheritBinaryDeclarationFrom(*this);
 
-  // Change covariant parameter types to Object in the implicit closure.
+  // Change covariant parameter types to either Object? for an opted-in implicit
+  // closure or to Object* for a legacy implicit closure.
   if (!is_static()) {
     BitVector is_covariant(zone, NumParameters());
     BitVector is_generic_covariant_impl(zone, NumParameters());
     kernel::ReadParameterCovariance(*this, &is_covariant,
                                     &is_generic_covariant_impl);
 
-    const Type& object_type = Type::Handle(zone, Type::ObjectType());
+    Type& object_type = Type::Handle(zone, Type::ObjectType());
+    if (Dart::non_nullable_flag()) {
+      // TODO(regis): Add nullable_object_type() to object store in addition to
+      // existing legacy_object_type() and remove this ToNullability call.
+      object_type = object_type.ToNullability(
+          nnbd_mode() == NNBDMode::kOptedInLib ? Nullability::kNullable
+                                               : Nullability::kLegacy,
+          Heap::kOld);
+    }
     for (intptr_t i = kClosure; i < num_params; ++i) {
       const intptr_t original_param_index = has_receiver - kClosure + i;
       if (is_covariant.Contains(original_param_index) ||
@@ -8555,7 +8554,7 @@
 }
 
 RawString* Function::GetSource() const {
-  if (IsImplicitConstructor() || IsSignatureFunction()) {
+  if (IsImplicitConstructor() || IsSignatureFunction() || is_synthetic()) {
     // We may need to handle more cases when the restrictions on mixins are
     // relaxed. In particular we might start associating some source with the
     // forwarding constructors when it becomes possible to specify a particular
@@ -10060,6 +10059,9 @@
     return;
   }
 
+  // We should never try to record a sentinel.
+  ASSERT(value.raw() != Object::sentinel().raw());
+
   if ((guarded_cid() == kDynamicCid) ||
       (is_nullable() && value.raw() == Object::null())) {
     // Nothing to do: the field is not guarded or we are storing null into
@@ -11835,12 +11837,6 @@
   core_lib.Register(thread);
   isolate->object_store()->set_bootstrap_library(ObjectStore::kCore, core_lib);
   isolate->object_store()->set_root_library(Library::Handle());
-
-  // Hook up predefined classes without setting their library pointers. These
-  // classes are coming from the VM isolate, and are shared between multiple
-  // isolates so setting their library pointers would be wrong.
-  const Class& cls = Class::Handle(zone, Object::dynamic_class());
-  core_lib.AddObject(cls, String::Handle(zone, cls.Name()));
 }
 
 // Invoke the function, or noSuchMethod if it is null.
@@ -13113,7 +13109,7 @@
 }
 #endif  // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
 
-RawInstructions* Instructions::New(intptr_t size, bool has_single_entry_point) {
+RawInstructions* Instructions::New(intptr_t size, bool has_monomorphic_entry) {
   ASSERT(size >= 0);
   ASSERT(Object::instructions_class() != Class::null());
   if (size < 0 || size > kMaxElements) {
@@ -13128,7 +13124,7 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetSize(size);
-    result.SetHasSingleEntryPoint(has_single_entry_point);
+    result.SetHasMonomorphicEntry(has_monomorphic_entry);
     result.set_stats(nullptr);
   }
   return result.raw();
@@ -13153,6 +13149,10 @@
 #endif
 }
 
+const char* InstructionsSection::ToCString() const {
+  return "InstructionsSection";
+}
+
 // Encode integer |value| in SLEB128 format and store into |data|.
 static void EncodeSLEB128(GrowableArray<uint8_t>* data, intptr_t value) {
   bool is_last_part = false;
@@ -15330,12 +15330,11 @@
   if (!FLAG_support_disassembler) {
     return;
   }
-  const Instructions& instr = Instructions::Handle(instructions());
-  uword start = instr.PayloadStart();
+  const uword start = PayloadStart();
   if (formatter == NULL) {
-    Disassembler::Disassemble(start, start + instr.Size(), *this);
+    Disassembler::Disassemble(start, start + Size(), *this);
   } else {
-    Disassembler::Disassemble(start, start + instr.Size(), formatter, *this);
+    Disassembler::Disassemble(start, start + Size(), formatter, *this);
   }
 #endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 }
@@ -15475,7 +15474,7 @@
   assembler->GetSelfHandle() = code.raw();
 #endif
   Instructions& instrs = Instructions::ZoneHandle(Instructions::New(
-      assembler->CodeSize(), assembler->has_single_entry_point()));
+      assembler->CodeSize(), assembler->has_monomorphic_entry()));
 
   {
     // Important: if GC is triggerred at any point between Instructions::New
@@ -15876,11 +15875,10 @@
 
 bool Code::VerifyBSSRelocations() const {
   const auto& descriptors = PcDescriptors::Handle(pc_descriptors());
-  const auto& insns = Instructions::Handle(instructions());
   PcDescriptors::Iterator iterator(descriptors,
                                    RawPcDescriptors::kBSSRelocation);
   while (iterator.MoveNext()) {
-    const uword reloc = insns.PayloadStart() + iterator.PcOffset();
+    const uword reloc = PayloadStart() + iterator.PcOffset();
     const word target = *reinterpret_cast<word*>(reloc);
     // The relocation is in its original unpatched form -- the addend
     // representing the target symbol itself.
@@ -17404,21 +17402,17 @@
 Specification of instance checks (e is T) and casts (e as T), where e evaluates
 to a value v and v has runtime type S:
 
-Instance checks (e is T) in weak checking mode in a legacy library:
-  If S is Null return LEGACY_SUBTYPE(T, Null) || LEGACY_SUBTYPE(Object, T)
+Instance checks (e is T) in weak checking mode in a legacy or opted-in library:
+  If v == null and T is a legacy type
+    return LEGACY_SUBTYPE(T, Null) || LEGACY_SUBTYPE(Object, T)
+  If v == null and T is not a legacy type, return NNBD_SUBTYPE(Null, T)
   Otherwise return LEGACY_SUBTYPE(S, T)
 
-Instance checks (e is T) in weak checking mode in an opted-in library:
-  If S is Null return NNBD_SUBTYPE(Null, T)
-  Otherwise return LEGACY_SUBTYPE(S, T)
-
-Instance checks (e is T) in strong checking mode in a legacy library:
-  If S is Null return NNBD_SUBTYPE(T, Null) || NNBD_SUBTYPE(Object, T)
+Instance checks (e is T) in strong checking mode in a legacy or opted-in lib:
+  If v == null and T is a legacy type
+    return LEGACY_SUBTYPE(T, Null) || LEGACY_SUBTYPE(Object, T)
   Otherwise return NNBD_SUBTYPE(S, T)
 
-Instance checks (e is T) in strong checking mode in an opted-in library:
-  return NNBD_SUBTYPE(S, T)
-
 Casts (e as T) in weak checking mode in a legacy or opted-in library:
   If LEGACY_SUBTYPE(S, T) then e as T evaluates to v.
   Otherwise a CastError is thrown.
@@ -17433,27 +17427,11 @@
     const AbstractType& other,
     const TypeArguments& other_instantiator_type_arguments,
     const TypeArguments& other_function_type_arguments) const {
-  ASSERT(other.IsFinalized());
   ASSERT(!other.IsDynamicType());
-  ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
-  // Note that Object::sentinel() has Null class, but !IsNull().
-  ASSERT(raw() != Object::sentinel().raw());
   if (IsNull()) {
-    if (mode == NNBDMode::kOptedInLib) {
-      // Compute NNBD_SUBTYPE(Null, other), either in weak or strong mode.
-      return Instance::NNBD_NullIsInstanceOf(other,
-                                             other_instantiator_type_arguments,
-                                             other_function_type_arguments);
-    }
-    ASSERT(mode == NNBDMode::kLegacyLib);
-    // In weak mode,
-    //   compute LEGACY_SUBTYPE(other, Null) || LEGACY_SUBTYPE(Object, other).
-    // In strong mode,
-    //   compute NNBD_SUBTYPE(other, Null) || NNBD_SUBTYPE(Object, other).
-    // Note that both expressions yield the same results for any 'other' type.
-    return Instance::Legacy_NullIsInstanceOf(other,
-                                             other_instantiator_type_arguments,
-                                             other_function_type_arguments);
+    return Instance::NullIsInstanceOf(mode, other,
+                                      other_instantiator_type_arguments,
+                                      other_function_type_arguments);
   }
   // In strong mode, compute NNBD_SUBTYPE(runtimeType, other).
   // In weak mode, compute LEGACY_SUBTYPE(runtimeType, other).
@@ -17466,11 +17444,7 @@
     const AbstractType& other,
     const TypeArguments& other_instantiator_type_arguments,
     const TypeArguments& other_function_type_arguments) const {
-  ASSERT(other.IsFinalized());
   ASSERT(!other.IsDynamicType());
-  ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
-  // Note that Object::sentinel() has Null class, but !IsNull().
-  ASSERT(raw() != Object::sentinel().raw());
   // In weak mode type casts, whether in legacy or opted-in libraries, the null
   // instance is detected and handled in inlined code and therefore cannot be
   // encountered here as a Dart null receiver.
@@ -17481,69 +17455,42 @@
                                 other_function_type_arguments);
 }
 
-// In strong mode, for kLegacyLib mode:
-//   return NNBD_SUBTYPE(other, Null) || NNBD_SUBTYPE(Object, other).
-// In weak mode, for kLegacyLib mode:
+// If 'other' type (once instantiated) is a legacy type:
 //   return LEGACY_SUBTYPE(other, Null) || LEGACY_SUBTYPE(Object, other).
-// Note that both expressions yield the same results.
+// Otherwise return NNBD_SUBTYPE(Null, T).
+// Use 'mode' to instantiate 'other'. TODO(regis): Remove unused mode.
 // Ignore value of strong flag value.
-bool Instance::Legacy_NullIsInstanceOf(
+bool Instance::NullIsInstanceOf(
+    NNBDMode mode,
     const AbstractType& other,
     const TypeArguments& other_instantiator_type_arguments,
     const TypeArguments& other_function_type_arguments) {
-  if (other.IsNullType() || other.Legacy_IsTopType()) {
+  ASSERT(other.IsFinalized());
+  ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
+  // TODO(regis): Verify that the nullability of an instantiated FutureOr
+  // always matches the nullability of its type argument. For now, be safe.
+  AbstractType& type = AbstractType::Handle(other.UnwrapFutureOr());
+  Nullability nullability = type.nullability();
+  if (nullability == Nullability::kNullable) {
+    // The type will remain nullable after instantiation.
     return true;
   }
-  AbstractType& instantiated_other = AbstractType::Handle(other.raw());
-  if (!other.IsInstantiated()) {
-    instantiated_other = other.InstantiateFrom(
-        NNBDMode::kLegacyLib, other_instantiator_type_arguments,
-        other_function_type_arguments, kAllFree, NULL, Heap::kOld);
-    if (instantiated_other.IsTypeRef()) {
-      instantiated_other = TypeRef::Cast(instantiated_other).type();
+  // No need to instantiate type, unless it is a type parameter.
+  // Note that a typeref cannot refer to a type parameter.
+  if (type.IsTypeParameter()) {
+    type = type.InstantiateFrom(mode, other_instantiator_type_arguments,
+                                other_function_type_arguments, kAllFree, NULL,
+                                Heap::kOld);
+    if (type.IsTypeRef()) {
+      type = TypeRef::Cast(type).type();
     }
+    type = type.UnwrapFutureOr();
   }
-  // instantiated_other is not modified if not FutureOr<T>.
-  while (instantiated_other.IsFutureOr(&instantiated_other)) {
+  nullability = type.nullability();
+  if (nullability == Nullability::kLegacy) {
+    return type.IsNullType() || type.IsTopType() || type.IsNeverType();
   }
-  return instantiated_other.IsNullType() ||
-         instantiated_other.Legacy_IsTopType();
-}
-
-// In strong mode, for kOptedInLib mode:
-//   return NNBD_SUBTYPE(Null, other).
-// In weak mode, for kOptedInLib mode:
-//   return NNBD_SUBTYPE(Null, other).
-// Ignore value of strong flag value.
-bool Instance::NNBD_NullIsInstanceOf(
-    const AbstractType& other,
-    const TypeArguments& other_instantiator_type_arguments,
-    const TypeArguments& other_function_type_arguments) {
-  Nullability other_nullability = other.nullability();
-  if (other_nullability == Nullability::kNullable ||
-      other_nullability == Nullability::kLegacy) {
-    // This includes Null type and top types when using nnbd testing.
-    // Also, an uninstantiated type that is either nullable or legacy will
-    // be either nullable or legacy after instantiation and cannot throw a
-    // type error during instantiation.
-    return true;
-  }
-  AbstractType& instantiated_other = AbstractType::Handle(other.raw());
-  if (!other.IsInstantiated()) {
-    instantiated_other = other.InstantiateFrom(
-        NNBDMode::kOptedInLib, other_instantiator_type_arguments,
-        other_function_type_arguments, kAllFree, NULL, Heap::kOld);
-    if (instantiated_other.IsTypeRef()) {
-      instantiated_other = TypeRef::Cast(instantiated_other).type();
-    }
-  }
-  // instantiated_other is not modified if not FutureOr<T>.
-  while (instantiated_other.IsFutureOr(&instantiated_other)) {
-  }
-  // Test nullability again after instantiation.
-  other_nullability = instantiated_other.nullability();
-  return other_nullability == Nullability::kNullable ||
-         other_nullability == Nullability::kLegacy;
+  return nullability == Nullability::kNullable;
 }
 
 bool Instance::RuntimeTypeIsSubtypeOf(
@@ -17552,10 +17499,11 @@
     const TypeArguments& other_instantiator_type_arguments,
     const TypeArguments& other_function_type_arguments) const {
   ASSERT(other.IsFinalized());
-  ASSERT(!other.IsDynamicType());
   ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
+  // Note that Object::sentinel() has Null class, but !IsNull().
+  ASSERT(raw() != Object::sentinel().raw());
   // Instance may not have runtimeType dynamic, void, or Never.
-  if (other.IsTopType(mode)) {
+  if (other.IsTopType()) {
     return true;
   }
   // In weak testing mode, Null type is a subtype of any type.
@@ -17577,7 +17525,7 @@
       if (instantiated_other.IsTypeRef()) {
         instantiated_other = TypeRef::Cast(instantiated_other).type();
       }
-      if (instantiated_other.IsTopType(mode) ||
+      if (instantiated_other.IsTopType() ||
           instantiated_other.IsDartFunctionType()) {
         return true;
       }
@@ -17617,7 +17565,7 @@
     if (instantiated_other.IsTypeRef()) {
       instantiated_other = TypeRef::Cast(instantiated_other).type();
     }
-    if (instantiated_other.IsTopType(mode)) {
+    if (instantiated_other.IsTopType()) {
       return true;
     }
   }
@@ -17654,7 +17602,7 @@
         TypeArguments::Handle(zone, other.arguments());
     const AbstractType& other_type_arg =
         AbstractType::Handle(zone, other_type_arguments.TypeAt(0));
-    if (other_type_arg.IsTopType(mode)) {
+    if (other_type_arg.IsTopType()) {
       return true;
     }
     if (Class::Handle(zone, clazz()).IsFutureClass()) {
@@ -17894,45 +17842,32 @@
   return Nullability::kNullable;
 }
 
-RawAbstractType* AbstractType::CheckInstantiatedNullability(
-    NNBDMode mode,
+RawAbstractType* AbstractType::SetInstantiatedNullability(
     const TypeParameter& type_param,
     Heap::Space space) const {
   Nullability result_nullability;
   const Nullability arg_nullability = nullability();
-  if (mode == NNBDMode::kOptedInLib) {
-    const Nullability var_nullability = type_param.nullability();
-    // Adjust nullability of result 'arg' instantiated from 'var' (x throws).
-    // arg/var ! ? * %
-    //  !      ! ? * !
-    //  ?      x ? ? ?
-    //  *      * ? * *
-    //  %      x ? * %
-    if (var_nullability == Nullability::kNonNullable &&
-        (arg_nullability == Nullability::kNullable ||
-         arg_nullability == Nullability::kUndetermined)) {
-      const String& error =
-          String::Handle(String::New("non-nullable type parameter"));
-      Exceptions::CreateAndThrowTypeError(TokenPosition::kNoSource, *this,
-                                          type_param, error);
-      UNREACHABLE();
-    }
-    if (var_nullability == Nullability::kNullable ||
-        arg_nullability == Nullability::kNullable) {
-      result_nullability = Nullability::kNullable;
-    } else if (var_nullability == Nullability::kLegacy ||
-               arg_nullability == Nullability::kLegacy) {
-      result_nullability = Nullability::kLegacy;
-    } else {
-      result_nullability = arg_nullability;
-    }
-  } else {
-    const classid_t cid = type_class_id();
-    if (cid == kDynamicCid || cid == kVoidCid || cid == kNullCid) {
-      // Do not force result to kLegacy.
-      return raw();
-    }
+  const Nullability var_nullability = type_param.nullability();
+  // Adjust nullability of result 'arg' instantiated from 'var' (x throws).
+  // arg/var ! ? * %
+  //  !      ! ? * !
+  //  ?      x ? ? ?
+  //  *      * ? * *
+  //  %      x ? * %
+  // If the assert below triggers, file an issue against CFE.
+  // A non-nullable type parameter cannot be instantiated to a nullable type.
+  ASSERT(var_nullability != Nullability::kNonNullable ||
+         (arg_nullability != Nullability::kNullable &&
+          arg_nullability != Nullability::kUndetermined));
+
+  if (var_nullability == Nullability::kNullable ||
+      arg_nullability == Nullability::kNullable) {
+    result_nullability = Nullability::kNullable;
+  } else if (var_nullability == Nullability::kLegacy ||
+             arg_nullability == Nullability::kLegacy) {
     result_nullability = Nullability::kLegacy;
+  } else {
+    result_nullability = arg_nullability;
   }
   if (arg_nullability == result_nullability) {
     return raw();
@@ -17947,7 +17882,7 @@
   // a type by cloning it may break the graph of a recursive type.
   ASSERT(IsTypeRef());
   return AbstractType::Handle(TypeRef::Cast(*this).type())
-      .CheckInstantiatedNullability(mode, type_param, space);
+      .SetInstantiatedNullability(type_param, space);
 }
 
 bool AbstractType::IsInstantiated(Genericity genericity,
@@ -18254,41 +18189,18 @@
 }
 
 bool AbstractType::IsNullType() const {
-  const classid_t cid = type_class_id();
-  return cid == kNullCid ||
-         (cid == kNeverCid &&
-          (!FLAG_strong_non_nullable_type_checks || IsNullable()));
+  return type_class_id() == kNullCid;
 }
 
 bool AbstractType::IsNeverType() const {
-  return FLAG_strong_non_nullable_type_checks && type_class_id() == kNeverCid &&
-         !IsNullable();
+  return type_class_id() == kNeverCid;
 }
 
-bool AbstractType::IsTopType(NNBDMode mode) const {
-  return (FLAG_strong_non_nullable_type_checks || mode == NNBDMode::kOptedInLib)
-             ? NNBD_IsTopType()
-             : Legacy_IsTopType();
-}
-
-bool AbstractType::Legacy_IsTopType() const {
-  const classid_t cid = type_class_id();
-  if (cid == kIllegalCid) {  // Includes TypeParameter.
-    return false;
-  }
-  if (cid == kDynamicCid || cid == kVoidCid || cid == kInstanceCid) {
-    return true;
-  }
+// Caution: IsTopType() does not return true for non-nullable Object.
+bool AbstractType::IsTopType() const {
   // FutureOr<T> where T is a top type behaves as a top type.
-  AbstractType& type_arg = AbstractType::Handle(raw());
-  if (IsFutureOr(&type_arg)) {
-    return type_arg.Legacy_IsTopType();
-  }
-  return false;
-}
-
-bool AbstractType::NNBD_IsTopType() const {
-  const classid_t cid = type_class_id();
+  const AbstractType& unwrapped_type = AbstractType::Handle(UnwrapFutureOr());
+  classid_t cid = unwrapped_type.type_class_id();
   if (cid == kIllegalCid) {  // Includes TypeParameter.
     return false;
   }
@@ -18298,11 +18210,6 @@
   if (cid == kInstanceCid) {  // Object type.
     return !IsNonNullable();  // kLegacy or kNullable.
   }
-  // FutureOr<T> where T is a top type behaves as a top type.
-  AbstractType& type_arg = AbstractType::Handle(raw());
-  if (IsFutureOr(&type_arg)) {
-    return type_arg.NNBD_IsTopType();
-  }
   return false;
 }
 
@@ -18354,28 +18261,38 @@
   return HasTypeClass() && type_class_id() == kFfiPointerCid;
 }
 
-bool AbstractType::IsFutureOr(AbstractType* type_arg) const {
-  if (IsType()) {
-    Thread* thread = Thread::Current();
-    REUSABLE_CLASS_HANDLESCOPE(thread);
-    Class& cls = thread->ClassHandle();
-    cls = type_class();
-    if (cls.IsFutureOrClass()) {
-      if (type_arg == nullptr) {
-        return true;
-      }
-      if (arguments() == TypeArguments::null()) {
-        *type_arg = Type::dynamic_type().raw();
-        return true;
-      }
-      REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
-      TypeArguments& type_args = thread->TypeArgumentsHandle();
-      type_args = arguments();
-      *type_arg = type_args.TypeAt(0);
-      return true;
-    }
+RawAbstractType* AbstractType::UnwrapFutureOr() const {
+  if (!IsType()) {
+    return raw();
   }
-  return false;
+  Thread* thread = Thread::Current();
+  REUSABLE_CLASS_HANDLESCOPE(thread);
+  Class& cls = thread->ClassHandle();
+  cls = type_class();
+  if (!cls.IsFutureOrClass()) {
+    return raw();
+  }
+  if (arguments() == TypeArguments::null()) {
+    return Type::dynamic_type().raw();
+  }
+  REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
+  TypeArguments& type_args = thread->TypeArgumentsHandle();
+  type_args = arguments();
+  REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread);
+  AbstractType& type_arg = thread->AbstractTypeHandle();
+  type_arg = type_args.TypeAt(0);
+  while (type_arg.IsType()) {
+    cls = type_arg.type_class();
+    if (!cls.IsFutureOrClass()) {
+      break;
+    }
+    if (type_arg.arguments() == TypeArguments::null()) {
+      return Type::dynamic_type().raw();
+    }
+    type_args = type_arg.arguments();
+    type_arg = type_args.TypeAt(0);
+  }
+  return type_arg.raw();
 }
 
 bool AbstractType::IsSubtypeOf(NNBDMode mode,
@@ -18383,25 +18300,23 @@
                                Heap::Space space) const {
   ASSERT(IsFinalized());
   ASSERT(other.IsFinalized());
-  if (other.IsTopType(mode) || IsNeverType()) {
+  if (other.IsTopType() || (FLAG_strong_non_nullable_type_checks &&
+                            IsNeverType() && !IsNullable())) {
     return true;
   }
   if (IsDynamicType() || IsVoidType()) {
     return false;
   }
-  if (IsNullType()) {
+  if (IsNullType() ||
+      (IsNeverType() &&
+       (!FLAG_strong_non_nullable_type_checks || IsNullable()))) {
     // In weak testing mode, Null type is a subtype of any type.
     if (!FLAG_strong_non_nullable_type_checks) {
       return true;
     }
-    if (other.IsTypeParameter()) {
-      return false;
-    }
-    AbstractType& other_type_arg = AbstractType::Handle(other.raw());
-    // other_type_arg is not modified if not FutureOr<T>.
-    while (other_type_arg.IsFutureOr(&other_type_arg)) {
-    }
-    return !other_type_arg.IsTypeParameter() && !other_type_arg.IsNonNullable();
+    const AbstractType& unwrapped_other =
+        AbstractType::Handle(other.UnwrapFutureOr());
+    return unwrapped_other.IsNullable() || unwrapped_other.IsLegacy();
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -18525,7 +18440,7 @@
         TypeArguments::Handle(zone, other.arguments());
     const AbstractType& other_type_arg =
         AbstractType::Handle(zone, other_type_arguments.TypeAt(0));
-    if (other_type_arg.IsTopType(mode)) {
+    if (other_type_arg.IsTopType()) {
       return true;
     }
     // Retry the IsSubtypeOf check after unwrapping type arg of FutureOr.
@@ -19213,7 +19128,9 @@
 #endif  // DEBUG
 
 void Type::EnumerateURIs(URIs* uris) const {
-  if (IsDynamicType() || IsVoidType()) {
+  // N.B. Not all types with kNeverCid answer true to IsNeverType, but none of
+  // them have a URI.
+  if (IsDynamicType() || IsVoidType() || (type_class_id() == kNeverCid)) {
     return;
   }
   Thread* thread = Thread::Current();
@@ -19454,7 +19371,8 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const AbstractType& ref_type = AbstractType::Handle(zone, type());
-  ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType());
+  ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType() &&
+         !ref_type.IsNeverType());
   const Class& cls = Class::Handle(zone, ref_type.type_class());
   const String& name = String::Handle(zone, cls.UserVisibleName());
   const Library& library = Library::Handle(zone, cls.library());
@@ -19664,7 +19582,7 @@
     }
     const AbstractType& result =
         AbstractType::Handle(function_type_arguments.TypeAt(index()));
-    return result.CheckInstantiatedNullability(mode, *this, space);
+    return result.SetInstantiatedNullability(*this, space);
   }
   ASSERT(IsClassTypeParameter());
   if (instantiator_type_arguments.IsNull()) {
@@ -19681,7 +19599,7 @@
   }
   const AbstractType& result =
       AbstractType::Handle(instantiator_type_arguments.TypeAt(index()));
-  return result.CheckInstantiatedNullability(mode, *this, space);
+  return result.SetInstantiatedNullability(*this, space);
   // There is no need to canonicalize the instantiated type parameter, since all
   // type arguments are canonicalized at type finalization time. It would be too
   // early to canonicalize the returned type argument here, since instantiation
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 6b7c8bb..36f10e1 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -482,6 +482,9 @@
   static RawClass* code_class() { return code_class_; }
   static RawClass* bytecode_class() { return bytecode_class_; }
   static RawClass* instructions_class() { return instructions_class_; }
+  static RawClass* instructions_section_class() {
+    return instructions_section_class_;
+  }
   static RawClass* object_pool_class() { return object_pool_class_; }
   static RawClass* pc_descriptors_class() { return pc_descriptors_class_; }
   static RawClass* code_source_map_class() { return code_source_map_class_; }
@@ -766,6 +769,8 @@
   static RawClass* code_class_;                 // Class of the Code vm object.
   static RawClass* bytecode_class_;      // Class of the Bytecode vm object.
   static RawClass* instructions_class_;  // Class of the Instructions vm object.
+  static RawClass*
+      instructions_section_class_;       // Class of InstructionsSection.
   static RawClass* object_pool_class_;   // Class of the ObjectPool vm object.
   static RawClass* pc_descriptors_class_;   // Class of PcDescriptors vm object.
   static RawClass* code_source_map_class_;  // Class of CodeSourceMap vm object.
@@ -2479,6 +2484,8 @@
   RawObject* RawOwner() const { return raw_ptr()->owner_; }
 
   // The NNBD mode to use when compiling type tests.
+  // TODO(alexmarkov): nnbd_mode() doesn't work for mixins.
+  // It should be either removed or fixed.
   NNBDMode nnbd_mode() const { return Class::Handle(origin()).nnbd_mode(); }
 
   RawRegExp* regexp() const;
@@ -3393,7 +3400,7 @@
   V(GeneratedBody, is_generated_body)                                          \
   V(PolymorphicTarget, is_polymorphic_target)                                  \
   V(HasPragma, has_pragma)                                                     \
-  V(IsNoSuchMethodForwarder, is_no_such_method_forwarder)                      \
+  V(IsSynthetic, is_synthetic)                                                 \
   V(IsExtensionMember, is_extension_member)
 
 #define DEFINE_ACCESSORS(name, accessor_name)                                  \
@@ -5061,21 +5068,13 @@
     return SizeBits::decode(instr->ptr()->size_and_flags_);
   }
 
-  bool HasSingleEntryPoint() const {
+  bool HasMonomorphicEntry() const {
     return FlagsBits::decode(raw_ptr()->size_and_flags_);
   }
-  static bool HasSingleEntryPoint(const RawInstructions* instr) {
+  static bool HasMonomorphicEntry(const RawInstructions* instr) {
     return FlagsBits::decode(instr->ptr()->size_and_flags_);
   }
 
-  static bool ContainsPc(RawInstructions* instruction, uword pc) {
-    const uword offset = pc - PayloadStart(instruction);
-    // We use <= instead of < here because the saved-pc can be outside the
-    // instruction stream if the last instruction is a call we don't expect to
-    // return (e.g. because it throws an exception).
-    return offset <= static_cast<uword>(Size(instruction));
-  }
-
   uword PayloadStart() const { return PayloadStart(raw()); }
   uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(raw()); }
   uword EntryPoint() const { return EntryPoint(raw()); }
@@ -5111,7 +5110,7 @@
 
   static uword MonomorphicEntryPoint(const RawInstructions* instr) {
     uword entry = PayloadStart(instr);
-    if (!HasSingleEntryPoint(instr)) {
+    if (HasMonomorphicEntry(instr)) {
       entry += !FLAG_precompiled_mode ? kMonomorphicEntryOffsetJIT
                                       : kMonomorphicEntryOffsetAOT;
     }
@@ -5120,7 +5119,7 @@
 
   static uword EntryPoint(const RawInstructions* instr) {
     uword entry = PayloadStart(instr);
-    if (!HasSingleEntryPoint(instr)) {
+    if (HasMonomorphicEntry(instr)) {
       entry += !FLAG_precompiled_mode ? kPolymorphicEntryOffsetJIT
                                       : kPolymorphicEntryOffsetAOT;
     }
@@ -5170,7 +5169,7 @@
                     SizeBits::update(value, raw_ptr()->size_and_flags_));
   }
 
-  void SetHasSingleEntryPoint(bool value) const {
+  void SetHasMonomorphicEntry(bool value) const {
     StoreNonPointer(&raw_ptr()->size_and_flags_,
                     FlagsBits::update(value, raw_ptr()->size_and_flags_));
   }
@@ -5179,7 +5178,7 @@
   // only be created using the Code::FinalizeCode method. This method creates
   // the RawInstruction and RawCode objects, sets up the pointer offsets
   // and links the two in a GC safe manner.
-  static RawInstructions* New(intptr_t size, bool has_single_entry_point);
+  static RawInstructions* New(intptr_t size, bool has_monomorphic_entry);
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
   friend class Class;
@@ -5189,6 +5188,34 @@
   friend class ImageWriter;
 };
 
+// Used only to provide memory accounting for the bare instruction payloads
+// we serialize, since they are no longer part of RawInstructions objects.
+class InstructionsSection : public Object {
+ public:
+  // Excludes HeaderSize().
+  intptr_t Size() const { return raw_ptr()->payload_length_; }
+  static intptr_t Size(const RawInstructionsSection* instr) {
+    return instr->ptr()->payload_length_;
+  }
+  static intptr_t InstanceSize() {
+    ASSERT(sizeof(RawInstructionsSection) ==
+           OFFSET_OF_RETURNED_VALUE(RawInstructionsSection, data));
+    return 0;
+  }
+
+  static intptr_t InstanceSize(intptr_t size) {
+    return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
+  }
+
+  static intptr_t HeaderSize() {
+    return Utils::RoundUp(sizeof(RawInstructionsSection), kWordSize);
+  }
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object);
+  friend class Class;
+};
+
 class LocalVarDescriptors : public Object {
  public:
   intptr_t Length() const;
@@ -5564,11 +5591,6 @@
     return code->ptr()->instructions_;
   }
 
-  // Returns the entry point of [InstructionsOf(code)].
-  static uword EntryPointOf(const RawCode* code) {
-    return Instructions::EntryPoint(InstructionsOf(code));
-  }
-
   static intptr_t saved_instructions_offset() {
     return OFFSET_OF(RawCode, instructions_);
   }
@@ -5618,12 +5640,38 @@
   bool is_alive() const { return AliveBit::decode(raw_ptr()->state_bits_); }
   void set_is_alive(bool value) const;
 
-  // Returns the payload start of [instructions()].
-  uword PayloadStart() const {
-    return Instructions::PayloadStart(instructions());
+  bool HasMonomorphicEntry() const { return HasMonomorphicEntry(raw()); }
+  static bool HasMonomorphicEntry(const RawCode* code) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return code->ptr()->entry_point_ != code->ptr()->monomorphic_entry_point_;
+#else
+    return Instructions::HasMonomorphicEntry(InstructionsOf(code));
+#endif
   }
+
+  // Returns the payload start of [instructions()].
+  uword PayloadStart() const { return PayloadStartOf(raw()); }
+  static uword PayloadStartOf(const RawCode* code) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    const uword entry_offset = HasMonomorphicEntry(code)
+                                   ? Instructions::kPolymorphicEntryOffsetAOT
+                                   : 0;
+    return EntryPointOf(code) - entry_offset;
+#else
+    return Instructions::PayloadStart(InstructionsOf(code));
+#endif
+  }
+
   // Returns the entry point of [instructions()].
-  uword EntryPoint() const { return Instructions::EntryPoint(instructions()); }
+  uword EntryPoint() const { return EntryPointOf(raw()); }
+  static uword EntryPointOf(const RawCode* code) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return code->ptr()->entry_point_;
+#else
+    return Instructions::EntryPoint(InstructionsOf(code));
+#endif
+  }
+
   // Returns the unchecked entry point of [instructions()].
   uword UncheckedEntryPoint() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -5634,7 +5682,11 @@
   }
   // Returns the monomorphic entry point of [instructions()].
   uword MonomorphicEntryPoint() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return raw_ptr()->monomorphic_entry_point_;
+#else
     return Instructions::MonomorphicEntryPoint(instructions());
+#endif
   }
   // Returns the unchecked monomorphic entry point of [instructions()].
   uword MonomorphicUncheckedEntryPoint() const {
@@ -5644,8 +5696,16 @@
     return MonomorphicEntryPoint() + raw_ptr()->unchecked_offset_;
 #endif
   }
+
   // Returns the size of [instructions()].
-  intptr_t Size() const { return Instructions::Size(instructions()); }
+  intptr_t Size() const { return PayloadSizeOf(raw()); }
+  static intptr_t PayloadSizeOf(const RawCode* code) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    return code->ptr()->instructions_length_;
+#else
+    return Instructions::Size(InstructionsOf(code));
+#endif
+  }
 
   RawObjectPool* GetObjectPool() const;
   // Returns whether the given PC address is in [instructions()].
@@ -5654,8 +5714,8 @@
   }
 
   // Returns whether the given PC address is in [InstructionsOf(code)].
-  static bool ContainsInstructionAt(const RawCode* code, uword addr) {
-    return Instructions::ContainsPc(InstructionsOf(code), addr);
+  static bool ContainsInstructionAt(const RawCode* code, uword pc) {
+    return RawCode::ContainsPC(code, pc);
   }
 
   // Returns true if there is a debugger breakpoint set in this code object.
@@ -6059,11 +6119,13 @@
 
   // Returns the unchecked entry point offset for [instructions_].
   uint32_t UncheckedEntryPointOffset() const {
+    return UncheckedEntryPointOffsetOf(raw());
+  }
+  static uint32_t UncheckedEntryPointOffsetOf(RawCode* code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
-    return raw_ptr()->unchecked_entry_point_ - raw_ptr()->entry_point_;
 #else
-    return raw_ptr()->unchecked_offset_;
+    return code->ptr()->unchecked_offset_;
 #endif
   }
 
@@ -6101,6 +6163,7 @@
   friend class FunctionSerializationCluster;
   friend class CodeSerializationCluster;
   friend class CodeDeserializationCluster;
+  friend class Deserializer;           // for InitializeCachedEntryPointsFrom
   friend class StubCode;               // for set_object_pool
   friend class MegamorphicCacheTable;  // for set_object_pool
   friend class CodePatcher;            // for set_instructions
@@ -6864,18 +6927,9 @@
       const TypeArguments& other_instantiator_type_arguments,
       const TypeArguments& other_function_type_arguments) const;
 
-  // Return true if the null instance is an instance of other type according to
-  // legacy semantics (independently of the current value of the strong flag).
-  // It only makes sense in a legacy library.
-  static bool Legacy_NullIsInstanceOf(
-      const AbstractType& other,
-      const TypeArguments& other_instantiator_type_arguments,
-      const TypeArguments& other_function_type_arguments);
-
-  // Return true if the null instance is an instance of other type according to
-  // NNBD semantics (independently of the current value of the strong flag).
-  // It only makes sense in an opted-in library.
-  static bool NNBD_NullIsInstanceOf(
+  // Return true if the null instance is an instance of other type.
+  static bool NullIsInstanceOf(
+      NNBDMode mode,
       const AbstractType& other,
       const TypeArguments& other_instantiator_type_arguments,
       const TypeArguments& other_function_type_arguments);
@@ -7027,7 +7081,7 @@
   // Check if the subvector of length 'len' starting at 'from_index' of this
   // type argument vector consists solely of DynamicType, (nullable) ObjectType,
   // or VoidType.
-  bool IsTopTypes(NNBDMode mode, intptr_t from_index, intptr_t len) const;
+  bool IsTopTypes(intptr_t from_index, intptr_t len) const;
 
   // Check the subtype relationship, considering only a subvector of length
   // 'len' starting at 'from_index'.
@@ -7223,8 +7277,7 @@
   virtual bool IsLegacy() const {
     return nullability() == Nullability::kLegacy;
   }
-  virtual RawAbstractType* CheckInstantiatedNullability(
-      NNBDMode mode,
+  virtual RawAbstractType* SetInstantiatedNullability(
       const TypeParameter& type_param,
       Heap::Space space) const;
 
@@ -7263,6 +7316,7 @@
   // must remain uninstantiated, because only T is a free variable in this type.
   //
   // Return a new type, or return 'this' if it is already instantiated.
+  // TODO(regis): mode is not needed anymore. Remove it here and in all callers.
   virtual RawAbstractType* InstantiateFrom(
       NNBDMode mode,
       const TypeArguments& instantiator_type_arguments,
@@ -7352,17 +7406,7 @@
   bool IsObjectType() const { return type_class_id() == kInstanceCid; }
 
   // Check if this type represents a top type.
-  bool IsTopType(NNBDMode mode) const;
-
-  // Check if this type represents a top type according to legacy
-  // semantics (independently of the current value of the strong flag or of the
-  // nnbd mode).
-  bool Legacy_IsTopType() const;
-
-  // Check if this type represents a top type according to NNBD
-  // semantics (independently of the current value of the strong flag or of the
-  // nnbd mode).
-  bool NNBD_IsTopType() const;
+  bool IsTopType() const;
 
   // Check if this type represents the 'bool' type.
   bool IsBoolType() const { return type_class_id() == kBoolCid; }
@@ -7400,9 +7444,9 @@
   // Check if this type represents the 'Pointer' type from "dart:ffi".
   bool IsFfiPointerType() const;
 
-  // Returns true if this type has the form FutureOr<T> and sets type_arg to T.
-  // Returns false otherwise.
-  bool IsFutureOr(AbstractType* type_arg) const;
+  // Returns the type argument of this (possibly nested) 'FutureOr' type.
+  // Returns unmodified type if this type is not a 'FutureOr' type.
+  RawAbstractType* UnwrapFutureOr() const;
 
   // Check the subtype relationship.
   bool IsSubtypeOf(NNBDMode mode,
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index cf6b22f..a01e9e5 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -667,6 +667,10 @@
   }
 }
 
+void InstructionsSection::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
 void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index b1aed90..1f86f3d 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -366,7 +366,7 @@
     // We only care about thread locals with destructors.
     return;
   }
-  MutexLocker ml(mutex_, false);
+  MutexLocker ml(mutex_);
 #if defined(DEBUG)
   // Verify that we aren't added twice.
   for (intptr_t i = 0; i < thread_locals_->length(); i++) {
@@ -380,7 +380,7 @@
 
 void ThreadLocalData::RemoveThreadLocal(ThreadLocalKey key) {
   ASSERT(thread_locals_ != NULL);
-  MutexLocker ml(mutex_, false);
+  MutexLocker ml(mutex_);
   intptr_t i = 0;
   for (; i < thread_locals_->length(); i++) {
     const ThreadLocalEntry& entry = thread_locals_->At(i);
@@ -405,7 +405,7 @@
     return;
   }
   ASSERT(mutex_ != NULL);
-  MutexLocker ml(mutex_, false);
+  MutexLocker ml(mutex_);
   for (intptr_t i = 0; i < thread_locals_->length(); i++) {
     const ThreadLocalEntry& entry = thread_locals_->At(i);
     // We access the exiting thread's TLS variable here.
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index f6613fa..00a2772 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -29,9 +29,6 @@
     ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
     while (it.HasNext()) {
       cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
       visitor->Visit(cls);
     }
     patches = lib.used_scripts();
@@ -55,10 +52,6 @@
         field_(Field::Handle(zone)) {}
 
   void Visit(const Class& cls) {
-    if (cls.IsDynamicClass()) {
-      return;  // class 'dynamic' is in the read-only VM isolate.
-    }
-
     functions_ = cls.functions();
     for (intptr_t j = 0; j < functions_.Length(); j++) {
       function_ ^= functions_.At(j);
@@ -1125,14 +1118,14 @@
   DedupCodeSourceMaps();
   DedupLists();
 
-#if defined(PRODUCT)
   // Reduces binary size but obfuscates profiler results.
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    DedupInstructionsWithSameMetadata();
-  } else {
-    DedupInstructions();
+  if (FLAG_dedup_instructions) {
+    if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+      DedupInstructionsWithSameMetadata();
+    } else {
+      DedupInstructions();
+    }
   }
-#endif
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 8d38f6e..5e9f70e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -106,6 +106,13 @@
       instance_size = Instructions::InstanceSize(instructions_size);
       break;
     }
+    case kInstructionsSectionCid: {
+      const RawInstructionsSection* raw_section =
+          reinterpret_cast<const RawInstructionsSection*>(this);
+      intptr_t section_size = InstructionsSection::Size(raw_section);
+      instance_size = InstructionsSection::InstanceSize(section_size);
+      break;
+    }
     case kContextCid: {
       const RawContext* raw_context = reinterpret_cast<const RawContext*>(this);
       intptr_t num_variables = raw_context->ptr()->num_variables_;
@@ -555,6 +562,7 @@
 REGULAR_VISITOR(Pointer)
 NULL_VISITOR(DynamicLibrary)
 VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
+VARIABLE_NULL_VISITOR(InstructionsSection, InstructionsSection::Size(raw_obj))
 VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->ptr()->length_)
 VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->ptr()->length_)
 VARIABLE_NULL_VISITOR(CompressedStackMaps, raw_obj->ptr()->payload_size())
@@ -570,12 +578,12 @@
 // Smi has no heap representation.
 UNREACHABLE_VISITOR(Smi)
 
-bool RawCode::ContainsPC(RawObject* raw_obj, uword pc) {
-  if (raw_obj->IsCode()) {
-    RawCode* raw_code = static_cast<RawCode*>(raw_obj);
-    return RawInstructions::ContainsPC(raw_code->ptr()->instructions_, pc);
-  }
-  return false;
+bool RawCode::ContainsPC(const RawObject* raw_obj, uword pc) {
+  if (!raw_obj->IsCode()) return false;
+  auto const raw_code = static_cast<const RawCode*>(raw_obj);
+  const uword start = Code::PayloadStartOf(raw_code);
+  const uword size = Code::PayloadSizeOf(raw_code);
+  return (pc - start) <= size;  // pc may point just past last instruction.
 }
 
 intptr_t RawCode::VisitCodePointers(RawCode* raw_obj,
@@ -589,8 +597,7 @@
   // instructions. The variable portion of a Code object describes where to
   // find those pointers for tracing.
   if (Code::AliveBit::decode(obj->state_bits_)) {
-    uword entry_point = reinterpret_cast<uword>(obj->instructions_->ptr()) +
-                        Instructions::HeaderSize();
+    uword entry_point = Code::PayloadStartOf(raw_obj);
     for (intptr_t i = 0; i < length; i++) {
       int32_t offset = obj->data()[i];
       visitor->VisitPointer(
@@ -632,12 +639,13 @@
   return ObjectPool::InstanceSize(length);
 }
 
-bool RawInstructions::ContainsPC(RawInstructions* raw_instr, uword pc) {
-  uword start_pc =
-      reinterpret_cast<uword>(raw_instr->ptr()) + Instructions::HeaderSize();
-  uword end_pc = start_pc + Instructions::Size(raw_instr);
-  ASSERT(end_pc > start_pc);
-  return (pc >= start_pc) && (pc < end_pc);
+bool RawInstructions::ContainsPC(const RawInstructions* raw_instr, uword pc) {
+  const uword start = Instructions::PayloadStart(raw_instr);
+  const uword size = Instructions::Size(raw_instr);
+  // We use <= instead of < here because the saved-pc can be outside the
+  // instruction stream if the last instruction is a call we don't expect to
+  // return (e.g. because it throws an exception).
+  return (pc - start) <= size;
 }
 
 intptr_t RawInstance::VisitInstancePointers(RawInstance* raw_obj,
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 74dc667..c7552e3 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1408,8 +1408,11 @@
 class RawCode : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
 
-  // When in the precompiled runtime, there is no active_instructions_ field
-  // and the entry point caches should contain entry points for instructions_.
+  // When in the precompiled runtime, there is no disabling of Code objects
+  // and thus no active_instructions_ field. Thus, the entry point caches are
+  // only set once during deserialization. If not using bare instructions,
+  // the caches should match the entry points for instructions_.
+  //
   // Otherwise, they should contain entry points for active_instructions_.
 
   uword entry_point_;  // Accessed from generated code.
@@ -1497,12 +1500,14 @@
   // Caches the unchecked entry point offset for instructions_, in case we need
   // to reset the active_instructions_ to instructions_.
   NOT_IN_PRECOMPILED(uint32_t unchecked_offset_);
+  // Stores the instructions length when not using RawInstructions objects.
+  ONLY_IN_PRECOMPILED(uint32_t instructions_length_);
 
   // Variable length data follows here.
   int32_t* data() { OPEN_ARRAY_START(int32_t, int32_t); }
   const int32_t* data() const { OPEN_ARRAY_START(int32_t, int32_t); }
 
-  static bool ContainsPC(RawObject* raw_obj, uword pc);
+  static bool ContainsPC(const RawObject* raw_obj, uword pc);
 
   friend class Function;
   template <bool>
@@ -1584,7 +1589,7 @@
   // Private helper function used while visiting stack frames. The
   // code which iterates over dart frames is also called during GC and
   // is not allowed to create handles.
-  static bool ContainsPC(RawInstructions* raw_instr, uword pc);
+  static bool ContainsPC(const RawInstructions* raw_instr, uword pc);
 
   friend class RawCode;
   friend class RawFunction;
@@ -1599,6 +1604,19 @@
   friend class BlobImageWriter;
 };
 
+// Used only to provide memory accounting for the bare instruction payloads
+// we serialize, since they are no longer part of RawInstructions objects.
+class RawInstructionsSection : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection);
+  VISIT_NOTHING();
+
+  // Instructions section payload length in bytes.
+  uword payload_length_;
+
+  // Variable length data follows here.
+  uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
+};
+
 class RawPcDescriptors : public RawObject {
  public:
 // The macro argument V is passed two arguments, the raw name of the enum value
@@ -2975,8 +2993,9 @@
          RawObject::IsTwoByteStringClassId(index) ||
          RawObject::IsTypedDataClassId(index) || (index == kContextCid) ||
          (index == kTypeArgumentsCid) || (index == kInstructionsCid) ||
-         (index == kObjectPoolCid) || (index == kPcDescriptorsCid) ||
-         (index == kCodeSourceMapCid) || (index == kCompressedStackMapsCid) ||
+         (index == kInstructionsSectionCid) || (index == kObjectPoolCid) ||
+         (index == kPcDescriptorsCid) || (index == kCodeSourceMapCid) ||
+         (index == kCompressedStackMapsCid) ||
          (index == kLocalVarDescriptorsCid) ||
          (index == kExceptionHandlersCid) || (index == kCodeCid) ||
          (index == kContextScopeCid) || (index == kInstanceCid) ||
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index bcb86b6..c39aa72 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -541,6 +541,7 @@
 MESSAGE_SNAPSHOT_UNREACHABLE(Function);
 MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
 MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
+MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
 MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
 MESSAGE_SNAPSHOT_UNREACHABLE(Library);
 MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
diff --git a/runtime/vm/reverse_pc_lookup_cache.cc b/runtime/vm/reverse_pc_lookup_cache.cc
index 325d98f..4757d24 100644
--- a/runtime/vm/reverse_pc_lookup_cache.cc
+++ b/runtime/vm/reverse_pc_lookup_cache.cc
@@ -11,13 +11,11 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
 
 static uword BeginPcFromCode(const RawCode* code) {
-  auto instr = Code::InstructionsOf(code);
-  return Instructions::PayloadStart(instr);
+  return Code::PayloadStartOf(code);
 }
 
 static uword EndPcFromCode(const RawCode* code) {
-  auto instr = Code::InstructionsOf(code);
-  return Instructions::PayloadStart(instr) + Instructions::Size(instr);
+  return Code::PayloadStartOf(code) + Code::PayloadSizeOf(code);
 }
 
 void ReversePcLookupCache::BuildAndAttachToIsolate(Isolate* isolate) {
diff --git a/runtime/vm/reverse_pc_lookup_cache.h b/runtime/vm/reverse_pc_lookup_cache.h
index 8300b62..7de0bff 100644
--- a/runtime/vm/reverse_pc_lookup_cache.h
+++ b/runtime/vm/reverse_pc_lookup_cache.h
@@ -66,7 +66,11 @@
   }
 
   // Looks up the [Code] object from a given [pc].
-  inline RawCode* Lookup(uword pc) {
+  //
+  // If [is_return_address] is true, then the PC may be immediately after the
+  // payload, if the last instruction is a call that is guaranteed not to
+  // return. Otherwise, the PC must be within the payload.
+  inline RawCode* Lookup(uword pc, bool is_return_address = false) {
     NoSafepointScope no_safepoint_scope;
 
     intptr_t left = 0;
@@ -81,6 +85,14 @@
       uword middle_pc = pc_array_[middle];
       if (middle_pc < pc_offset) {
         left = middle + 1;
+      } else if (!is_return_address && middle_pc == pc_offset) {
+        // This case should only happen if we have bare instruction payloads.
+        // Otherwise, the instruction payloads of two RawInstructions objects
+        // will never be immediately adjacent in memory due to the header of
+        // the second object.
+        ASSERT(FLAG_use_bare_instructions);
+        left = middle + 1;
+        break;
       } else {
         right = middle;
       }
@@ -116,7 +128,9 @@
 
   inline bool Contains(uword pc) { return false; }
 
-  inline RawCode* Lookup(uword pc) { UNREACHABLE(); }
+  inline RawCode* Lookup(uword pc, bool is_return_address = false) {
+    UNREACHABLE();
+  }
 };
 
 #endif  // defined(DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 134bf7b..6e38723 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1601,12 +1601,6 @@
 }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(PRODUCT)
-const bool kInstructionsCanBeDeduped = true;
-#else
-const bool kInstructionsCanBeDeduped = false;
-#endif  // defined(PRODUCT)
-
 // Handle the first use of an instance call
 //   Arg2: UnlinkedCall.
 //   Arg1: Receiver.
@@ -1661,7 +1655,7 @@
   //
   // See [MonomorphicMiss]
   const bool need_saved_unlinked_call =
-      (FLAG_use_bare_instructions && kInstructionsCanBeDeduped);
+      (FLAG_use_bare_instructions && FLAG_dedup_instructions);
 
   // We transition from an unlinked call to a monomorphic call. This transition
   // will cause us to loose the argument descriptor information on the call
@@ -1777,7 +1771,7 @@
 
   String& name = String::Handle(zone);
   Array& descriptor = Array::Handle(zone);
-  if (FLAG_use_bare_instructions && kInstructionsCanBeDeduped) {
+  if (FLAG_use_bare_instructions && FLAG_dedup_instructions) {
     const auto& unlinked_call = UnlinkedCall::Handle(
         zone, LoadUnlinkedCall(zone, isolate, caller_frame->pc()));
     name = unlinked_call.target_name();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index f5e3248..1aad8d9 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -631,7 +631,8 @@
         pobj_ = ReadObjectImpl(read_as_reference);
         result->SetFieldAtOffset(offset, pobj_);
         if ((offset != type_argument_field_offset) &&
-            (kind_ == Snapshot::kMessage) && isolate()->use_field_guards()) {
+            (kind_ == Snapshot::kMessage) && isolate()->use_field_guards() &&
+            (pobj_.raw() != Object::sentinel().raw())) {
           // TODO(fschneider): Consider hoisting these lookups out of the loop.
           // This would involve creating a handle, since cls_ can't be reused
           // across the call to ReadObjectImpl.
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 2b07d46..61505e1 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -105,7 +105,7 @@
       return true;
   }
   if (func.is_abstract() || func.IsImplicitConstructor() ||
-      func.IsRedirectingFactory() || func.is_no_such_method_forwarder()) {
+      func.IsRedirectingFactory() || func.is_synthetic()) {
     return true;
   }
   // Note that context_scope() remains null for closures declared in bytecode,
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index ff5ac18..564d610 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -126,7 +126,7 @@
   if (auto isolate = IsolateOfBareInstructionsFrame()) {
     Code code;
     auto rct = isolate->reverse_pc_lookup_cache();
-    code = rct->Lookup(pc());
+    code = rct->Lookup(pc(), /*is_return_address=*/true);
 
     const intptr_t cid = code.owner()->GetClassId();
     ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
@@ -141,7 +141,7 @@
   if (auto isolate = IsolateOfBareInstructionsFrame()) {
     Code code;
     auto rct = isolate->reverse_pc_lookup_cache();
-    code = rct->Lookup(pc());
+    code = rct->Lookup(pc(), /*is_return_address=*/true);
 
     const intptr_t cid = code.owner()->GetClassId();
     ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
@@ -253,7 +253,8 @@
   Code code;
 
   if (auto isolate = IsolateOfBareInstructionsFrame()) {
-    code = isolate->reverse_pc_lookup_cache()->Lookup(pc());
+    auto const rct = isolate->reverse_pc_lookup_cache();
+    code = rct->Lookup(pc(), /*is_return_address=*/true);
   } else {
     RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
         fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
@@ -387,7 +388,8 @@
   NoSafepointScope no_safepoint;
 #endif
   if (auto isolate = IsolateOfBareInstructionsFrame()) {
-    return isolate->reverse_pc_lookup_cache()->Lookup(pc());
+    auto const rct = isolate->reverse_pc_lookup_cache();
+    return rct->Lookup(pc(), /*is_return_address=*/true);
   }
 
   RawCode* code = GetCodeObject();
@@ -401,7 +403,8 @@
 RawCode* StackFrame::GetCodeObject() const {
   ASSERT(!is_interpreted());
   if (auto isolate = IsolateOfBareInstructionsFrame()) {
-    return isolate->reverse_pc_lookup_cache()->Lookup(pc());
+    auto const rct = isolate->reverse_pc_lookup_cache();
+    return rct->Lookup(pc(), /*is_return_address=*/true);
   } else {
     RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
         fp() + runtime_frame_layout.code_from_fp * kWordSize));
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index e8b5a14..5316ec2 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -178,6 +178,7 @@
   V(IndexToken, "[]")                                                          \
   V(InitPrefix, "init:")                                                       \
   V(Instructions, "Instructions")                                              \
+  V(InstructionsSection, "InstructionsSection")                                \
   V(Int, "int")                                                                \
   V(Int16List, "Int16List")                                                    \
   V(Int32List, "Int32List")                                                    \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 43bfbfc..eebe318 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -146,12 +146,12 @@
 static const struct ALIGN16 {
   uint64_t a;
   uint64_t b;
-} double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL};
+} double_negate_constant = {0x8000000000000000ULL, 0x8000000000000000ULL};
 
 static const struct ALIGN16 {
   uint64_t a;
   uint64_t b;
-} double_abs_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
+} double_abs_constant = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL};
 
 static const struct ALIGN16 {
   uint32_t a;
diff --git a/sdk/lib/_internal/vm/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
index 57af07f..8f36206 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
@@ -84,6 +84,7 @@
 class _MirrorSystem extends MirrorSystem {
   final TypeMirror dynamicType = new _SpecialTypeMirror._('dynamic');
   final TypeMirror voidType = new _SpecialTypeMirror._('void');
+  final TypeMirror neverType = new _SpecialTypeMirror._('Never');
 
   var _libraries;
   Map<Uri, LibraryMirror> get libraries {
@@ -685,13 +686,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
@@ -893,13 +896,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
@@ -995,13 +1000,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 151edc4..f51cdb5 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -400,11 +400,13 @@
   /// The entry object of the first element in the queue.
   ///
   /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
-  /// Returns the entry object corresponding to the first element of the queue.
+  ///
+  /// Returns the entry object corresponding to the first element of the queue,
+  /// or `null` if the queue is empty.
   ///
   /// The entry objects can also be accessed using [lastEntry],
-  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-  /// [DoubleLinkedQueueEntry.previousEntry()].
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and
+  /// [DoubleLinkedQueueEntry.previousEntry].
   DoubleLinkedQueueEntry<E> firstEntry() {
     return _sentinel.nextEntry();
   }
@@ -412,11 +414,13 @@
   /// The entry object of the last element in the queue.
   ///
   /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
-  /// Returns the entry object corresponding to the last element of the queue.
+  ///
+  /// Returns the entry object corresponding to the last element of the queue,
+  /// or `null` if the queue is empty.
   ///
   /// The entry objects can also be accessed using [firstEntry],
-  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-  /// [DoubleLinkedQueueEntry.previousEntry()].
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and
+  /// [DoubleLinkedQueueEntry.previousEntry].
   DoubleLinkedQueueEntry<E> lastEntry() {
     return _sentinel.previousEntry();
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 9e856ea..0dd1b95 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -12163,8 +12163,8 @@
    *
    * * [isTagSupported]
    */
-  factory Element.tag(String tag, [String typeExtention]) =>
-      _ElementFactoryProvider.createElement_tag(tag, typeExtention);
+  factory Element.tag(String tag, [String typeExtension]) =>
+      _ElementFactoryProvider.createElement_tag(tag, typeExtension);
 
   /// Creates a new `<a>` element.
   ///
@@ -14845,7 +14845,7 @@
   }
 
   List<EventTarget> get path =>
-      JS('bool', '!!#.composedPath', this) ? composedPath() : [];
+      JS<bool>('bool', '!!#.composedPath', this) ? composedPath() : [];
 
   factory Event._(String type, [Map eventInitDict]) {
     if (eventInitDict != null) {
@@ -16194,24 +16194,21 @@
     }
 
     int watchId;
-    // TODO(jacobr): it seems like a bug that we have to specifiy the static
-    // type here for controller.stream to have the right type.
-    // dartbug.com/26278
-    StreamController<Geoposition> controller;
-    controller = new StreamController<Geoposition>(
-        sync: true,
-        onListen: () {
-          assert(watchId == null);
-          watchId = _watchPosition((position) {
-            controller.add(_ensurePosition(position));
-          }, (error) {
-            controller.addError(error);
-          }, options);
-        },
-        onCancel: () {
-          assert(watchId != null);
-          _clearWatch(watchId);
-        });
+    StreamController<Geoposition> controller =
+        new StreamController<Geoposition>(
+            sync: true,
+            onCancel: () {
+              assert(watchId != null);
+              _clearWatch(watchId);
+            });
+    controller.onListen = () {
+      assert(watchId == null);
+      watchId = _watchPosition((position) {
+        controller.add(_ensurePosition(position));
+      }, (error) {
+        controller.addError(error);
+      }, options);
+    };
 
     return controller.stream;
   }
@@ -17121,8 +17118,6 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Node item(int index) native;
-
   Object namedItem(String name) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -18447,16 +18442,16 @@
 
   bool indeterminate;
 
-  List<Node> get labels;
-
   String name;
 
+  String value;
+
+  List<Node> get labels;
+
   String get validationMessage;
 
   ValidityState get validity;
 
-  String value;
-
   bool get willValidate;
 
   bool checkValidity();
@@ -22099,7 +22094,7 @@
     // TODO(vsm): Use the native remove when available.
     if (this.parentNode != null) {
       final Node parent = this.parentNode;
-      parentNode._removeChild(this);
+      parent._removeChild(this);
     }
   }
 
@@ -22111,7 +22106,6 @@
       final Node parent = this.parentNode;
       parent._replaceChild(otherNode, this);
     } catch (e) {}
-    ;
     return this;
   }
 
@@ -22587,11 +22581,7 @@
 @Native("Notification")
 class Notification extends EventTarget {
   factory Notification(String title,
-      {String dir: null,
-      String body: null,
-      String lang: null,
-      String tag: null,
-      String icon: null}) {
+      {String dir, String body, String lang, String tag, String icon}) {
     var parsedOptions = {};
     if (dir != null) parsedOptions['dir'] = dir;
     if (body != null) parsedOptions['body'] = body;
@@ -25004,7 +24994,7 @@
   factory Range() => document.createRange();
 
   factory Range.fromPoint(Point point) =>
-      document._caretRangeFromPoint(point.x, point.y);
+      document._caretRangeFromPoint(point.x.toInt(), point.y.toInt());
   // To suppress missing implicit constructor warnings.
   factory Range._() {
     throw new UnsupportedError("Not supported");
@@ -28923,17 +28913,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 @Native("TouchList")
 class TouchList extends Interceptor
     with ListMixin<Touch>, ImmutableListMixin<Touch>
     implements JavaScriptIndexingBehavior<Touch>, List<Touch> {
-  /// NB: This constructor likely does not work as you might expect it to! This
-  /// constructor will simply fail (returning null) if you are not on a device
-  /// with touch enabled. See dartbug.com/8314.
-  // TODO(5760): createTouchList now uses varargs.
-  factory TouchList() => null; //document._createTouchList();
   // To suppress missing implicit constructor warnings.
   factory TouchList._() {
     throw new UnsupportedError("Not supported");
@@ -31019,7 +31002,7 @@
   @Returns('Window|=Object')
   final dynamic _get_opener;
 
-  set opener(Window value) {
+  set opener(WindowBase value) {
     JS("void", "#.opener = #", this, value);
   }
 
@@ -32089,7 +32072,7 @@
    *   from W3C.
    */
   void moveTo(Point p) {
-    _moveTo(p.x, p.y);
+    _moveTo(p.x.toInt(), p.y.toInt());
   }
 
   @JSName('openDatabase')
diff --git a/sdk/lib/html/html_common/html_common.dart b/sdk/lib/html/html_common/html_common.dart
index 6d6b08b..aab2cef 100644
--- a/sdk/lib/html/html_common/html_common.dart
+++ b/sdk/lib/html/html_common/html_common.dart
@@ -10,7 +10,6 @@
 import 'dart:html';
 import 'dart:js' as js;
 import 'dart:_internal' show WhereIterable;
-import 'dart:mirrors';
 import 'dart:nativewrappers';
 import 'dart:typed_data';
 import 'dart:web_gl' as gl;
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 1241331..f4ba2c4 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -217,11 +217,6 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
-      "mirrors": {
-        "uri": "mirrors/mirrors.dart",
-        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
-        "supported": false
-      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -327,11 +322,6 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
-      "mirrors": {
-        "uri": "mirrors/mirrors.dart",
-        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
-        "supported": false
-      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -399,9 +389,6 @@
       "_js_helper": {
         "uri": "_internal/js_dev_runtime/private/js_helper.dart"
       },
-      "_js_mirrors": {
-        "uri": "_internal/js_dev_runtime/private/js_mirrors.dart"
-      },
       "_js_primitives": {
         "uri": "_internal/js_dev_runtime/private/js_primitives.dart"
       },
@@ -441,11 +428,6 @@
         "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
         "supported": false
       },
-      "mirrors": {
-        "uri": "mirrors/mirrors.dart",
-        "patches": "_internal/js_dev_runtime/patch/mirrors_patch.dart",
-        "supported": false
-      },
       "math": {
         "uri": "math/math.dart",
         "patches": "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 191c2c3..cbf0080 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -214,11 +214,6 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
-    mirrors:
-      uri: "mirrors/mirrors.dart"
-      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
-      supported: false
-
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -322,11 +317,6 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
-    mirrors:
-      uri: "mirrors/mirrors.dart"
-      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
-      supported: false
-
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -392,9 +382,6 @@
       _js_helper:
         uri: "_internal/js_dev_runtime/private/js_helper.dart"
 
-      _js_mirrors:
-        uri: "_internal/js_dev_runtime/private/js_mirrors.dart"
-
       _js_primitives:
         uri: "_internal/js_dev_runtime/private/js_primitives.dart"
 
@@ -434,11 +421,6 @@
         patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
         supported: false
 
-      mirrors:
-        uri: "mirrors/mirrors.dart"
-        patches: "_internal/js_dev_runtime/patch/mirrors_patch.dart"
-        supported: false
-
       math:
         uri: "math/math.dart"
         patches: "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 2a1e197..731a0a5 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -60,6 +60,7 @@
 library dart.mirrors;
 
 import 'dart:async' show Future;
+import "dart:_internal" show Since;
 
 /**
  * A [MirrorSystem] is the main interface used to reflect on a set of
@@ -111,6 +112,12 @@
   TypeMirror get voidType;
 
   /**
+   * A mirror on the [:Never:] type.
+   */
+  @Since("2.8")
+  TypeMirror get neverType;
+
+  /**
    * Returns the name of [symbol].
    *
    * The following text is non-normative:
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index 6390fb4..afa8d39 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -32,7 +32,8 @@
         Creates,
         JSName,
         Native,
-        JavaScriptIndexingBehavior;
+        JavaScriptIndexingBehavior,
+        Returns;
 
 // 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
diff --git a/sdk_nnbd/lib/_http/http_headers.dart b/sdk_nnbd/lib/_http/http_headers.dart
index f23dce2..dfccd75 100644
--- a/sdk_nnbd/lib/_http/http_headers.dart
+++ b/sdk_nnbd/lib/_http/http_headers.dart
@@ -624,12 +624,12 @@
 
 class _HeaderValue implements HeaderValue {
   String _value;
-  Map<String, String?>? _parameters;
-  Map<String, String?>? _unmodifiableParameters;
+  Map<String, String>? _parameters;
+  Map<String, String>? _unmodifiableParameters;
 
-  _HeaderValue([this._value = "", Map<String, String?>? parameters]) {
+  _HeaderValue([this._value = "", Map<String, String>? parameters]) {
     if (parameters != null) {
-      _parameters = new HashMap<String, String?>.from(parameters);
+      _parameters = new HashMap<String, String>.from(parameters);
     }
   }
 
@@ -645,10 +645,10 @@
 
   String get value => _value;
 
-  Map<String, String?> _ensureParameters() =>
-      _parameters ??= HashMap<String, String?>();
+  Map<String, String> _ensureParameters() =>
+      _parameters ??= HashMap<String, String>();
 
-  Map<String, String?> get parameters =>
+  Map<String, String> get parameters =>
       _unmodifiableParameters ??= UnmodifiableMapView(_ensureParameters());
 
   String toString() {
@@ -656,8 +656,12 @@
     sb.write(_value);
     var parameters = this._parameters;
     if (parameters != null && parameters.length > 0) {
-      parameters.forEach((String name, String? value) {
-        sb..write("; ")..write(name)..write("=")..write(value ?? "");
+      parameters.forEach((String name, String value) {
+        sb
+          ..write("; ")
+          ..write(name)
+          ..write("=")
+          ..write(value == "" ? '""' : value);
       });
     }
     return sb.toString();
@@ -717,7 +721,7 @@
         return s.substring(start, index).toLowerCase();
       }
 
-      String? parseParameterValue() {
+      String parseParameterValue() {
         if (!done() && s[index] == "\"") {
           // Parse quoted value.
           StringBuffer sb = new StringBuffer();
@@ -742,8 +746,7 @@
           return sb.toString();
         } else {
           // Parse non-quoted value.
-          var val = parseValue();
-          return val == "" ? null : val;
+          return parseValue();
         }
       }
 
@@ -753,17 +756,17 @@
         String name = parseParameterName();
         skipWS();
         if (done()) {
-          parameters[name] = null;
+          parameters[name] = "";
           return;
         }
         maybeExpect("=");
         skipWS();
         if (done()) {
-          parameters[name] = null;
+          parameters[name] = "";
           return;
         }
-        String? value = parseParameterValue();
-        if (name == 'charset' && this is _ContentType && value != null) {
+        String value = parseParameterValue();
+        if (name == 'charset' && this is _ContentType) {
           // Charset parameter of ContentTypes are always lower-case.
           value = value.toLowerCase();
         }
@@ -790,17 +793,17 @@
   String _subType = "";
 
   _ContentType(String primaryType, String subType, String? charset,
-      Map<String, String?>? parameters)
+      Map<String, String>? parameters)
       : _primaryType = primaryType,
         _subType = subType,
         super("") {
     _value = "$_primaryType/$_subType";
     if (parameters != null) {
       var parameterMap = _ensureParameters();
-      parameters.forEach((String key, String? value) {
+      parameters.forEach((String key, String value) {
         String lowerCaseKey = key.toLowerCase();
         if (lowerCaseKey == "charset") {
-          value = value?.toLowerCase();
+          value = value.toLowerCase();
         }
         parameterMap[lowerCaseKey] = value;
       });
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index b5cc680..a63bf64 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -1512,7 +1512,7 @@
           _gzipAdd = socket.add;
           if (_gzipBufferLength > 0) {
             _gzipSink!.add(new Uint8List.view(_gzipBuffer!.buffer,
-                _gzipBuffer.offsetInBytes, _gzipBufferLength));
+                _gzipBuffer!.offsetInBytes, _gzipBufferLength));
           }
           _gzipBuffer = null;
           _gzipSink!.close();
@@ -1523,7 +1523,7 @@
       // Add any remaining data in the buffer.
       if (_length > 0) {
         socket.add(new Uint8List.view(
-            _buffer!.buffer, _buffer.offsetInBytes, _length));
+            _buffer!.buffer, _buffer!.offsetInBytes, _length));
       }
       // Clear references, for better GC.
       _buffer = null;
@@ -1608,7 +1608,7 @@
         // If _buffer is not null, we have not written the header yet. Write
         // it now.
         add(new Uint8List.view(
-            _buffer!.buffer, _buffer.offsetInBytes, _length));
+            _buffer!.buffer, _buffer!.offsetInBytes, _length));
         _buffer = null;
         _length = 0;
       }
@@ -1616,7 +1616,7 @@
       return;
     }
     if (chunk.length > _buffer!.length - _length) {
-      add(new Uint8List.view(_buffer!.buffer, _buffer.offsetInBytes, _length));
+      add(new Uint8List.view(_buffer!.buffer, _buffer!.offsetInBytes, _length));
       _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
       _length = 0;
     }
diff --git a/sdk_nnbd/lib/_http/http_parser.dart b/sdk_nnbd/lib/_http/http_parser.dart
index ea51e57..cd54c5f 100644
--- a/sdk_nnbd/lib/_http/http_parser.dart
+++ b/sdk_nnbd/lib/_http/http_parser.dart
@@ -932,7 +932,7 @@
 
   void _releaseBuffer() {
     _buffer = null;
-    _index = null;
+    _index = -1;
   }
 
   static bool _isTokenChar(int byte) {
@@ -1075,7 +1075,7 @@
   void _reportBodyError(error, [stackTrace]) {
     _socketSubscription?.cancel();
     _state = _State.FAILURE;
-    _bodyController.addError(error, stackTrace);
+    _bodyController?.addError(error, stackTrace);
     // In case of drain(), error event will close the stream.
     _bodyController?.close();
   }
diff --git a/sdk_nnbd/lib/_http/websocket.dart b/sdk_nnbd/lib/_http/websocket.dart
index 9c670a6..3774ec1 100644
--- a/sdk_nnbd/lib/_http/websocket.dart
+++ b/sdk_nnbd/lib/_http/websocket.dart
@@ -134,7 +134,7 @@
       HeaderValue? requested) {
     var info = new _CompressionMaxWindowBits("", 0);
 
-    String? part = requested?.parameters?.[_serverMaxWindowBits];
+    String? part = requested?.parameters[_serverMaxWindowBits];
     if (part != null) {
       if (part.length >= 2 && part.startsWith('0')) {
         throw new ArgumentError("Illegal 0 padding on value.");
@@ -479,7 +479,7 @@
   /**
    * Sets the user agent to use for WebSocket connections.
    */
-  static set userAgent(String userAgent) {
+  static set userAgent(String? userAgent) {
     _WebSocketImpl.userAgent = userAgent;
   }
 }
diff --git a/sdk_nnbd/lib/_http/websocket_impl.dart b/sdk_nnbd/lib/_http/websocket_impl.dart
index 3fb8274..623797f 100644
--- a/sdk_nnbd/lib/_http/websocket_impl.dart
+++ b/sdk_nnbd/lib/_http/websocket_impl.dart
@@ -602,7 +602,9 @@
     final result = new BytesBuilder();
     List<int> out;
 
-    while ((out = decoder.processed()) != null) {
+    while (true) {
+      final out = decoder.processed();
+      if (out == null) break;
       result.add(out);
     }
 
@@ -633,8 +635,9 @@
 
     encoder.process(buffer, 0, buffer.length);
 
-    List<int> out;
-    while ((out = encoder.processed()) != null) {
+    while (true) {
+      final out = encoder.processed();
+      if (out == null) break;
       result.addAll(out);
     }
 
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
index c8e3bda..9b45b66 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
@@ -43,7 +43,7 @@
           bool errorsAreFatal = true,
           bool? checked,
           Map<String, String>? environment,
-          Uri packageRoot,
+          Uri? packageRoot,
           Uri? packageConfig,
           bool automaticPackageResolution = false,
           String? debugName}) =>
@@ -69,7 +69,7 @@
   void kill({int priority = beforeNextEvent}) => _unsupported();
   @patch
   void ping(SendPort responsePort,
-          {Object response, int priority = immediate}) =>
+          {Object? response, int priority = immediate}) =>
       _unsupported();
 
   @patch
@@ -101,7 +101,7 @@
   StreamSubscription listen(void Function(dynamic)? onData,
           {Function? onError,
           void Function()? onDone,
-          bool cancelOnError = true}) =>
+          bool? cancelOnError = true}) =>
       _unsupported();
 }
 
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart
index 200644c..288f66e 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart
@@ -51,7 +51,8 @@
     JS<double>('!', r'Math.atan2(#, #)', a, b);
 
 @patch
-double exp(num x) => JS<double>('!', r'Math.exp(#)', x);
+@notNull
+double exp(@nullCheck num x) => JS<double>('!', r'Math.exp(#)', x);
 
 @patch
 @notNull
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 8490309..657e152 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
@@ -193,9 +193,22 @@
   }
   // Verify that all required named parameters are provided an argument.
   Iterable requiredNames = getOwnPropertyNames(requiredNamed);
-  for (var name in requiredNames) {
-    if (!JS<bool>('!', '#.hasOwnProperty(#)', namedActuals, name)) {
-      return "Dynamic call with missing required named argument '$name'.";
+  if (requiredNames.length > 0 && namedActuals == null) {
+    if (!JS<bool>('', 'dart.__strictSubtypeChecks')) {
+      _warn("Dynamic call with missing required named arguments.");
+    } else {
+      return "Dynamic call with missing required named arguments.";
+    }
+  }
+  if (JS<bool>('', 'dart.__strictSubtypeChecks')) {
+    for (var name in requiredNames) {
+      if (!JS<bool>('!', '#.hasOwnProperty(#)', namedActuals, name)) {
+        if (!JS<bool>('', 'dart.__strictSubtypeChecks')) {
+          _warn("Dynamic call with missing required named argument '$name'.");
+        } else {
+          return "Dynamic call with missing required named argument '$name'.";
+        }
+      }
     }
   }
   // Now that we know the signature matches, we can perform type checks.
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 e2915e9..b606526 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
@@ -425,6 +425,10 @@
   // type term.
   Object normalizeHelper(a) => unwrapType(wrapType(a));
 
+  // GenericFunctionTypeIdentifiers are implicitly normalized.
+  if (type is GenericFunctionTypeIdentifier) {
+    return wrapType(type, isNormalized: true);
+  }
   if (type is FunctionType) {
     var normReturnType = normalizeHelper(type.returnType);
     var normArgs = type.args.map(normalizeHelper).toList();
@@ -447,6 +451,19 @@
         fnType(normReturnType, normArgs, normNamed, normRequiredNamed);
     return wrapType(normType, isNormalized: true);
   }
+  if (type is 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, isNormalized: true);
+  }
   var args = getGenericArgs(type);
   var normType;
   if (args == null || args.isEmpty) {
@@ -506,6 +523,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;
@@ -524,8 +573,6 @@
 
 // TODO(leafp): This only canonicalizes if the names are emitted
 // in a consistent order.
-// TODO(markzipan): Update this to differentiate named
-// from required named parameters.
 _canonicalizeNamed(named, map) => JS('', '''(() => {
   let key = [];
   let names = $getOwnPropertyNames($named);
@@ -701,7 +748,7 @@
         var typeNameString = typeName(JS('', '#[#[#]]', named, names, i));
         buffer += '$typeNameString ${JS('', '#[#]', names, i)}';
       }
-      if (JS('!', '#.length > 0', requiredNamed)) buffer += ', ';
+      if (JS('!', 'Object.keys(#).length > 0', requiredNamed)) buffer += ', ';
       names = getOwnPropertyNames(requiredNamed);
       JS('', '#.sort()', names);
       for (var i = 0; JS<bool>('!', '# < #.length', i, names); i++) {
@@ -765,6 +812,43 @@
   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 (JS(
+          '!', '# !== # && # !== #', bound, dynamic, bound, nullable(Object))) {
+        s += " extends $bound";
+      }
+    }
+    s += ">" + this.function.toString();
+    return this._stringValue = s;
+  }
+}
+
 class GenericFunctionType extends AbstractFunctionType {
   final _instantiateTypeParts;
   final int formalCount;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
index ffddbac..a32391f 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Patch file for dart:collection classes.
 import 'dart:_foreign_helper' show JS;
 import 'dart:_js_helper'
@@ -30,9 +28,9 @@
 class HashMap<K, V> {
   @patch
   factory HashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(potentialKey)}) {
+      {bool equals(K key1, K key2)?,
+      int hashCode(K key)?,
+      bool isValidKey(potentialKey)?}) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -82,7 +80,7 @@
   // list of all the keys. We cache that on the instance and clear the
   // the cache whenever the key set changes. This is also used to
   // guard against concurrent modifications.
-  List _keys;
+  List? _keys;
 
   _HashMap();
 
@@ -98,7 +96,7 @@
     return new MappedIterable<K, V>(keys, (each) => this[each]);
   }
 
-  bool containsKey(Object key) {
+  bool containsKey(Object? key) {
     if (_isStringKey(key)) {
       var strings = _strings;
       return (strings == null) ? false : _hasTableEntry(strings, key);
@@ -110,14 +108,14 @@
     }
   }
 
-  bool _containsKey(Object key) {
+  bool _containsKey(Object? key) {
     var rest = _rest;
     if (rest == null) return false;
     var bucket = _getBucket(rest, key);
     return _findBucketIndex(bucket, key) >= 0;
   }
 
-  bool containsValue(Object value) {
+  bool containsValue(Object? value) {
     return _computeKeys().any((each) => this[each] == value);
   }
 
@@ -127,7 +125,7 @@
     });
   }
 
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     if (_isStringKey(key)) {
       var strings = _strings;
       return JS('', '#', strings == null ? null : _getTableEntry(strings, key));
@@ -139,7 +137,7 @@
     }
   }
 
-  V _get(Object key) {
+  V? _get(Object? key) {
     var rest = _rest;
     if (rest == null) return null;
     var bucket = _getBucket(rest, key);
@@ -183,13 +181,13 @@
   }
 
   V putIfAbsent(K key, V ifAbsent()) {
-    if (containsKey(key)) return this[key];
+    if (containsKey(key)) return this[key] as V;
     V value = ifAbsent();
     this[key] = value;
     return value;
   }
 
-  V remove(Object key) {
+  V? remove(Object? key) {
     if (_isStringKey(key)) {
       return _removeHashTableEntry(_strings, key);
     } else if (_isNumericKey(key)) {
@@ -199,7 +197,7 @@
     }
   }
 
-  V _remove(Object key) {
+  V? _remove(Object? key) {
     var rest = _rest;
     if (rest == null) return null;
     var hash = _computeHashCode(key);
@@ -228,7 +226,7 @@
     List keys = _computeKeys();
     for (int i = 0, length = keys.length; i < length; i++) {
       var key = JS('var', '#[#]', keys, i);
-      action(key, this[key]);
+      action(key, this[key] as V);
       if (JS('bool', '# !== #', keys, _keys)) {
         throw new ConcurrentModificationError(this);
       }
@@ -236,8 +234,9 @@
   }
 
   List _computeKeys() {
-    if (_keys != null) return _keys;
-    List result = List.filled(_length, null);
+    var result = _keys;
+    if (result != null) return result;
+    result = List.filled(_length, null);
     int index = 0;
 
     // Add all string keys to the list.
@@ -283,7 +282,8 @@
       }
     }
     assert(index == _length);
-    return _keys = result;
+    _keys = result;
+    return result;
   }
 
   void _addHashTableEntry(var table, K key, V value) {
@@ -294,7 +294,7 @@
     _setTableEntry(table, key, value);
   }
 
-  V _removeHashTableEntry(var table, Object key) {
+  V? _removeHashTableEntry(var table, Object? key) {
     if (table != null && _hasTableEntry(table, key)) {
       V value = _getTableEntry(table, key);
       _deleteTableEntry(table, key);
@@ -408,10 +408,10 @@
   final _Hasher<K> _hashCode;
   final _Predicate _validKey;
 
-  _CustomHashMap(this._equals, this._hashCode, bool validKey(potentialKey))
+  _CustomHashMap(this._equals, this._hashCode, bool validKey(potentialKey)?)
       : _validKey = (validKey != null) ? validKey : ((v) => v is K);
 
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     if (!_validKey(key)) return null;
     return super._get(key);
   }
@@ -420,12 +420,12 @@
     super._set(key, value);
   }
 
-  bool containsKey(Object key) {
+  bool containsKey(Object? key) {
     if (!_validKey(key)) return false;
     return super._containsKey(key);
   }
 
-  V remove(Object key) {
+  V? remove(Object? key) {
     if (!_validKey(key)) return null;
     return super._remove(key);
   }
@@ -458,7 +458,7 @@
     return new _HashMapKeyIterator<E>(_map, _map._computeKeys());
   }
 
-  bool contains(Object element) {
+  bool contains(Object? element) {
     return _map.containsKey(element);
   }
 
@@ -477,11 +477,11 @@
   final _map;
   final List _keys;
   int _offset = 0;
-  E _current;
+  E? _current;
 
   _HashMapKeyIterator(this._map, this._keys);
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
     var keys = _keys;
@@ -506,9 +506,9 @@
 class LinkedHashMap<K, V> {
   @patch
   factory LinkedHashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(potentialKey)}) {
+      {bool equals(K key1, K key2)?,
+      int hashCode(K key)?,
+      bool isValidKey(potentialKey)?}) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -613,11 +613,11 @@
 
   Iterable<V> get values => new _Es6MapIterable<V>(this, false);
 
-  bool containsKey(Object key) {
+  bool containsKey(Object? key) {
     return JS('bool', '#.has(#)', _map, key);
   }
 
-  bool containsValue(Object value) {
+  bool containsValue(Object? value) {
     return values.any((each) => each == value);
   }
 
@@ -627,7 +627,7 @@
     });
   }
 
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     return JS('var', '#.get(#)', _map, key);
   }
 
@@ -637,14 +637,14 @@
   }
 
   V putIfAbsent(K key, V ifAbsent()) {
-    if (containsKey(key)) return this[key];
+    if (containsKey(key)) return this[key] as V;
     V value = ifAbsent();
     this[key] = value;
     return value;
   }
 
-  V remove(Object key) {
-    V value = this[key];
+  V? remove(Object? key) {
+    V? value = this[key];
     JS('bool', '#.delete(#)', _map, key);
     _modified();
     return value;
@@ -693,7 +693,7 @@
   Iterator<E> get iterator =>
       new _Es6MapIterator<E>(_map, _map._modifications, _isKeys);
 
-  bool contains(Object element) => _map.containsKey(element);
+  bool contains(Object? element) => _map.containsKey(element);
 
   void forEach(void f(E element)) {
     var jsIterator;
@@ -722,8 +722,8 @@
   final bool _isKeys;
   var _jsIterator;
   var _next;
-  E _current;
-  bool _done;
+  E? _current;
+  bool _done = false;
 
   _Es6MapIterator(this._map, this._modifications, this._isKeys) {
     if (_isKeys) {
@@ -731,10 +731,9 @@
     } else {
       _jsIterator = JS('var', '#.values()', _map._map);
     }
-    _done = false;
   }
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
     if (_modifications != _map._modifications) {
@@ -761,10 +760,10 @@
   final _Predicate _validKey;
 
   _LinkedCustomHashMap(
-      this._equals, this._hashCode, bool validKey(potentialKey))
+      this._equals, this._hashCode, bool validKey(potentialKey)?)
       : _validKey = (validKey != null) ? validKey : ((v) => v is K);
 
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     if (!_validKey(key)) return null;
     return super.internalGet(key);
   }
@@ -773,12 +772,12 @@
     super.internalSet(key, value);
   }
 
-  bool containsKey(Object key) {
+  bool containsKey(Object? key) {
     if (!_validKey(key)) return false;
     return super.internalContainsKey(key);
   }
 
-  V remove(Object key) {
+  V? remove(Object? key) {
     if (!_validKey(key)) return null;
     return super.internalRemove(key);
   }
@@ -805,9 +804,9 @@
 class HashSet<E> {
   @patch
   factory HashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(potentialKey)}) {
+      {bool equals(E e1, E e2)?,
+      int hashCode(E e)?,
+      bool isValidKey(potentialKey)?}) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -858,7 +857,7 @@
   // list of all the elements. We cache that on the instance and clear
   // the cache whenever the set changes. This is also used to
   // guard against concurrent modifications.
-  List _elements;
+  List? _elements;
 
   _HashSet();
 
@@ -874,7 +873,7 @@
   bool get isEmpty => _length == 0;
   bool get isNotEmpty => !isEmpty;
 
-  bool contains(Object object) {
+  bool contains(Object? object) {
     if (_isStringElement(object)) {
       var strings = _strings;
       return (strings == null) ? false : _hasTableEntry(strings, object);
@@ -886,21 +885,21 @@
     }
   }
 
-  bool _contains(Object object) {
+  bool _contains(Object? object) {
     var rest = _rest;
     if (rest == null) return false;
     var bucket = _getBucket(rest, object);
     return _findBucketIndex(bucket, object) >= 0;
   }
 
-  E lookup(Object object) {
+  E? lookup(Object? object) {
     if (_isStringElement(object) || _isNumericElement(object)) {
-      return this.contains(object) ? object : null;
+      return this.contains(object) ? object as E : null;
     }
     return _lookup(object);
   }
 
-  E _lookup(Object object) {
+  E? _lookup(Object? object) {
     var rest = _rest;
     if (rest == null) return null;
     var bucket = _getBucket(rest, object);
@@ -947,7 +946,7 @@
     }
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     if (_isStringElement(object)) {
       return _removeHashTableEntry(_strings, object);
     } else if (_isNumericElement(object)) {
@@ -957,7 +956,7 @@
     }
   }
 
-  bool _remove(Object object) {
+  bool _remove(Object? object) {
     var rest = _rest;
     if (rest == null) return false;
     var hash = _computeHashCode(object);
@@ -985,8 +984,9 @@
   }
 
   List _computeElements() {
-    if (_elements != null) return _elements;
-    List result = List.filled(_length, null);
+    var result = _elements;
+    if (result != null) return result;
+    result = List.filled(_length, null);
     int index = 0;
 
     // Add all string elements to the list.
@@ -1031,7 +1031,8 @@
       }
     }
     assert(index == _length);
-    return _elements = result;
+    _elements = result;
+    return result;
   }
 
   bool _addHashTableEntry(var table, E element) {
@@ -1042,7 +1043,7 @@
     return true;
   }
 
-  bool _removeHashTableEntry(var table, Object element) {
+  bool _removeHashTableEntry(var table, Object? element) {
     if (table != null && _hasTableEntry(table, element)) {
       _deleteTableEntry(table, element);
       _length--;
@@ -1143,7 +1144,7 @@
   _Equality<E> _equality;
   _Hasher<E> _hasher;
   _Predicate _validKey;
-  _CustomHashSet(this._equality, this._hasher, bool validKey(potentialKey))
+  _CustomHashSet(this._equality, this._hasher, bool validKey(potentialKey)?)
       : _validKey = (validKey != null) ? validKey : ((x) => x is E);
 
   Set<E> _newSet() => new _CustomHashSet<E>(_equality, _hasher, _validKey);
@@ -1168,17 +1169,17 @@
 
   bool add(E object) => super._add(object);
 
-  bool contains(Object object) {
+  bool contains(Object? object) {
     if (!_validKey(object)) return false;
     return super._contains(object);
   }
 
-  E lookup(Object object) {
+  E? lookup(Object? object) {
     if (!_validKey(object)) return null;
     return super._lookup(object);
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     if (!_validKey(object)) return false;
     return super._remove(object);
   }
@@ -1189,11 +1190,11 @@
   final _set;
   final List _elements;
   int _offset = 0;
-  E _current;
+  E? _current;
 
   _HashSetIterator(this._set, this._elements);
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
     var elements = _elements;
@@ -1218,9 +1219,9 @@
 class LinkedHashSet<E> {
   @patch
   factory LinkedHashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(potentialKey)}) {
+      {bool equals(E e1, E e2)?,
+      int hashCode(E e)?,
+      bool isValidKey(potentialKey)?}) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -1293,8 +1294,8 @@
 
   // The elements are stored in cells that are linked together
   // to form a double linked list.
-  _LinkedHashSetCell _first;
-  _LinkedHashSetCell _last;
+  _LinkedHashSetCell? _first;
+  _LinkedHashSetCell? _last;
 
   // We track the number of modifications done to the element set to
   // be able to throw when the set is modified while being iterated
@@ -1319,7 +1320,7 @@
   bool get isEmpty => _length == 0;
   bool get isNotEmpty => !isEmpty;
 
-  bool contains(Object object) {
+  bool contains(Object? object) {
     if (_isStringElement(object)) {
       var strings = _strings;
       if (strings == null) return false;
@@ -1335,22 +1336,22 @@
     }
   }
 
-  bool _contains(Object object) {
+  bool _contains(Object? object) {
     var rest = _rest;
     if (rest == null) return false;
     var bucket = _getBucket(rest, object);
     return _findBucketIndex(bucket, object) >= 0;
   }
 
-  E lookup(Object object) {
+  E? lookup(Object? object) {
     if (_isStringElement(object) || _isNumericElement(object)) {
-      return this.contains(object) ? object : null;
+      return this.contains(object) ? object as E : null;
     } else {
       return _lookup(object);
     }
   }
 
-  E _lookup(Object object) {
+  E? _lookup(Object? object) {
     var rest = _rest;
     if (rest == null) return null;
     var bucket = _getBucket(rest, object);
@@ -1360,7 +1361,7 @@
   }
 
   void forEach(void action(E element)) {
-    _LinkedHashSetCell cell = _first;
+    _LinkedHashSetCell? cell = _first;
     int modifications = _modifications;
     while (cell != null) {
       action(cell._element);
@@ -1372,13 +1373,15 @@
   }
 
   E get first {
-    if (_first == null) throw new StateError("No elements");
-    return _first._element;
+    var first = _first;
+    if (first == null) throw new StateError("No elements");
+    return first._element;
   }
 
   E get last {
-    if (_last == null) throw new StateError("No elements");
-    return _last._element;
+    var last = _last;
+    if (last == null) throw new StateError("No elements");
+    return last._element;
   }
 
   // Collection.
@@ -1413,7 +1416,7 @@
     return true;
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     if (_isStringElement(object)) {
       return _removeHashTableEntry(_strings, object);
     } else if (_isNumericElement(object)) {
@@ -1423,7 +1426,7 @@
     }
   }
 
-  bool _remove(Object object) {
+  bool _remove(Object? object) {
     var rest = _rest;
     if (rest == null) return false;
     var hash = _computeHashCode(object);
@@ -1448,10 +1451,10 @@
   }
 
   void _filterWhere(bool test(E element), bool removeMatching) {
-    _LinkedHashSetCell cell = _first;
+    _LinkedHashSetCell? cell = _first;
     while (cell != null) {
       E element = cell._element;
-      _LinkedHashSetCell next = cell._next;
+      _LinkedHashSetCell? next = cell._next;
       int modifications = _modifications;
       bool shouldRemove = (removeMatching == test(element));
       if (modifications != _modifications) {
@@ -1477,7 +1480,7 @@
     return true;
   }
 
-  bool _removeHashTableEntry(var table, Object element) {
+  bool _removeHashTableEntry(var table, Object? element) {
     if (table == null) return false;
     _LinkedHashSetCell cell = _getTableEntry(table, element);
     if (cell == null) return false;
@@ -1499,7 +1502,7 @@
     if (_first == null) {
       _first = _last = cell;
     } else {
-      _LinkedHashSetCell last = _last;
+      _LinkedHashSetCell last = _last!;
       cell._previous = last;
       _last = last._next = cell;
     }
@@ -1510,8 +1513,8 @@
 
   // Unlink the given cell from the linked list of cells.
   void _unlinkCell(_LinkedHashSetCell cell) {
-    _LinkedHashSetCell previous = cell._previous;
-    _LinkedHashSetCell next = cell._next;
+    _LinkedHashSetCell? previous = cell._previous;
+    _LinkedHashSetCell? next = cell._next;
     if (previous == null) {
       assert(cell == _first);
       _first = next;
@@ -1617,7 +1620,7 @@
   _Hasher<E> _hasher;
   _Predicate _validKey;
   _LinkedCustomHashSet(
-      this._equality, this._hasher, bool validKey(potentialKey))
+      this._equality, this._hasher, bool validKey(potentialKey)?)
       : _validKey = (validKey != null) ? validKey : ((x) => x is E);
 
   Set<E> _newSet() =>
@@ -1644,30 +1647,30 @@
 
   bool add(E element) => super._add(element);
 
-  bool contains(Object object) {
+  bool contains(Object? object) {
     if (!_validKey(object)) return false;
     return super._contains(object);
   }
 
-  E lookup(Object object) {
+  E? lookup(Object? object) {
     if (!_validKey(object)) return null;
     return super._lookup(object);
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     if (!_validKey(object)) return false;
     return super._remove(object);
   }
 
-  bool containsAll(Iterable<Object> elements) {
-    for (Object element in elements) {
+  bool containsAll(Iterable<Object?> elements) {
+    for (Object? element in elements) {
       if (!_validKey(element) || !this.contains(element)) return false;
     }
     return true;
   }
 
-  void removeAll(Iterable<Object> elements) {
-    for (Object element in elements) {
+  void removeAll(Iterable<Object?> elements) {
+    for (Object? element in elements) {
       if (_validKey(element)) {
         super._remove(element);
       }
@@ -1678,8 +1681,8 @@
 class _LinkedHashSetCell {
   final _element;
 
-  _LinkedHashSetCell _next;
-  _LinkedHashSetCell _previous;
+  _LinkedHashSetCell? _next;
+  _LinkedHashSetCell? _previous;
 
   _LinkedHashSetCell(this._element);
 }
@@ -1688,24 +1691,25 @@
 class _LinkedHashSetIterator<E> implements Iterator<E> {
   final _set;
   final int _modifications;
-  _LinkedHashSetCell _cell;
-  E _current;
+  _LinkedHashSetCell? _cell;
+  E? _current;
 
   _LinkedHashSetIterator(this._set, this._modifications) {
     _cell = _set._first;
   }
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
+    var cell = _cell;
     if (_modifications != _set._modifications) {
       throw new ConcurrentModificationError(_set);
-    } else if (_cell == null) {
+    } else if (cell == null) {
       _current = null;
       return false;
     } else {
-      _current = _cell._element;
-      _cell = _cell._next;
+      _current = cell._element;
+      _cell = cell._next;
       return true;
     }
   }
@@ -1717,7 +1721,7 @@
   Node _splayMin(Node node) {
     Node current = node;
     while (current.left != null) {
-      Node left = current.left;
+      Node left = current.left as Node;
       current.left = left.right;
       left.right = current;
       current = left;
@@ -1729,7 +1733,7 @@
   Node _splayMax(Node node) {
     Node current = node;
     while (current.right != null) {
-      Node right = current.right;
+      Node right = current.right as Node;
       current.right = right.left;
       right.left = current;
       current = right;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
index 369045e..585f4c5 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Patch file for dart:math library.
 import 'dart:_foreign_helper' show JS;
 import 'dart:_js_helper' show patch, checkNum;
@@ -65,10 +63,10 @@
 
 @patch
 class Random {
-  static Random _secureRandom;
+  static Random? _secureRandom;
 
   @patch
-  factory Random([int seed]) =>
+  factory Random([int? seed]) =>
       (seed == null) ? const _JSRandom() : new _Random(seed);
 
   @patch
@@ -226,7 +224,7 @@
     do {
       _nextState();
       rnd32 = _lo;
-      result = rnd32.remainder(max); // % max;
+      result = rnd32.remainder(max) as int; // % max;
     } while ((rnd32 - result + max) >= _POW2_32);
     return result;
   }
@@ -308,7 +306,7 @@
     }
     _buffer.setUint32(0, 0);
     int start = 4 - byteCount;
-    int randomLimit = pow(256, byteCount);
+    int randomLimit = pow(256, byteCount) as int;
     while (true) {
       _getRandomBytes(start, byteCount);
       // The getUint32 method is big-endian as default.
@@ -317,7 +315,7 @@
         // Max is power of 2.
         return random & (max - 1);
       }
-      int result = random.remainder(max);
+      int result = random.remainder(max) as int;
       // Ensure results have equal probability by rejecting values in the
       // last range of k*max .. 256**byteCount.
       // TODO: Consider picking a higher byte count if the last range is a
diff --git a/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart
index 49592e7..b87668b 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart
@@ -507,12 +507,12 @@
       _NativeSocket exitHandler) native "Process_Wait";
 
   Stream<List<int>> get stdout =>
-      _stdout ?? (throw StateError("Process is detached"));
+      _stdout ?? (throw StateError("stdio is not connected"));
 
   Stream<List<int>> get stderr =>
-      _stdout ?? (throw StateError("Process is detached"));
+      _stderr ?? (throw StateError("stdio is not connected"));
 
-  IOSink get stdin => _stdin ?? (throw StateError("Process is detached"));
+  IOSink get stdin => _stdin ?? (throw StateError("stdio is not connected"));
 
   Future<int> get exitCode =>
       _exitCode?.future ?? (throw StateError("Process is detached"));
@@ -571,11 +571,13 @@
     Future foldStream(Stream<List<int>> stream, Encoding? encoding) {
       if (encoding == null) {
         return stream
-            .fold(new BytesBuilder(), (builder, data) => builder..add(data))
+            .fold<BytesBuilder>(
+                new BytesBuilder(), (builder, data) => builder..add(data))
             .then((builder) => builder.takeBytes());
       } else {
-        return stream.transform(encoding.decoder).fold(new StringBuffer(),
-            (buf, data) {
+        return stream
+            .transform(encoding.decoder)
+            .fold<StringBuffer>(new StringBuffer(), (buf, data) {
           buf.write(data);
           return buf;
         }).then((sb) => sb.toString());
diff --git a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
index a66984b..30c2ccc 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
@@ -1311,7 +1311,7 @@
         controller.add(_RawSocket(socket));
         if (controller.isPaused) return;
       }
-    }), error: zone.bindBinaryCallbackGuarded((e, st) {
+    }), error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
       controller.addError(e, st);
       controller.close();
     }), destroyed: () {
@@ -1425,7 +1425,7 @@
           _controller.add(RawSocketEvent.closed);
           _controller.close();
         },
-        error: zone.bindBinaryCallbackGuarded((e, st) {
+        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
           _controller.addError(e, st);
           _socket.close();
         }));
@@ -1978,7 +1978,7 @@
           _controller.add(RawSocketEvent.closed);
           _controller.close();
         },
-        error: zone.bindBinaryCallbackGuarded((e, st) {
+        error: zone.bindBinaryCallbackGuarded((Object e, StackTrace st) {
           _controller.addError(e, st);
           _socket.close();
         }));
diff --git a/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart b/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
index c6717ee..353472c 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
@@ -182,10 +182,9 @@
   return result;
 }
 
-Future<Uri> serverInformationCallback() async =>
-    await _lazyServerBoot().serverAddress!;
+Uri? serverInformationCallback() => _lazyServerBoot().serverAddress;
 
-Future<Uri> webServerControlCallback(bool enable) async {
+Future<Uri?> webServerControlCallback(bool enable) async {
   final _server = _lazyServerBoot();
   if (_server.running != enable) {
     if (enable) {
@@ -194,7 +193,7 @@
       await _server.shutdown(true);
     }
   }
-  return _server.serverAddress!;
+  return _server.serverAddress;
 }
 
 void _clearFuture(_) {
diff --git a/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart b/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
index 1ae04a3..ca9154b 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
@@ -276,7 +276,7 @@
       // PUT requests are forwarded to DevFS for processing.
 
       List fsNameList;
-      List fsPathList;
+      List? fsPathList;
       List? fsPathBase64List;
       List? fsUriBase64List;
       Object? fsName;
@@ -297,12 +297,12 @@
 
         // Fallback to path encoding.
         if (fsUri == null) {
-          fsPathList = request.headers['dev_fs_path']!;
+          fsPathList = request.headers['dev_fs_path'];
           fsPathBase64List = request.headers['dev_fs_path_b64'];
           // If the 'dev_fs_path_b64' header field was sent, use that instead.
-          if ((fsPathBase64List != null) && (fsPathBase64List.length > 0)) {
+          if ((fsPathBase64List != null) && fsPathBase64List.isNotEmpty) {
             fsPath = utf8.decode(base64.decode(fsPathBase64List[0]));
-          } else {
+          } else if (fsPathList != null && fsPathList.isNotEmpty) {
             fsPath = fsPathList[0];
           }
         }
diff --git a/sdk_nnbd/lib/_internal/vm/lib/double.dart b/sdk_nnbd/lib/_internal/vm/lib/double.dart
index c5472c9..83b3262 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/double.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/double.dart
@@ -286,6 +286,9 @@
   String toStringAsPrecision(int precision) {
     // See ECMAScript-262, 15.7.4.7 for details.
 
+    if (precision == null) {
+      throw new ArgumentError.notNull("precision");
+    }
     // The EcmaScript specification checks for NaN and Infinity before looking
     // at the fractionDigits. In Dart we are consistent with toStringAsFixed and
     // look at the fractionDigits first.
diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
index 0bee1e5..4ce85be 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
@@ -468,14 +468,15 @@
     bool argsMismatch = _existingArgumentNames != null;
     String argsMessage = argsMismatch ? " with matching arguments" : "";
 
-    assert(type >= 0 && type < 5);
-    final String typeStr = (const [
-      "method",
-      "getter",
-      "setter",
-      "getter or setter",
-      "variable"
-    ])[type];
+    final String typeStr = (type >= 0 && type < 5)
+        ? (const [
+            "method",
+            "getter",
+            "setter",
+            "getter or setter",
+            "variable"
+          ])[type]
+        : "";
 
     StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
     bool isTypeCall = false;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart
index 0caf7ed..b4d3daa 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart
@@ -17,12 +17,12 @@
         (positionalArguments != null ? positionalArguments.length : 0);
     int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
     int numArguments = numPositionalArguments + numNamedArguments;
-    List arguments = new List.filled(numArguments, null);
+    List arguments = new List<dynamic>.filled(numArguments, null);
     arguments[0] = function;
     if (positionalArguments != null) {
       arguments.setRange(1, numPositionalArguments, positionalArguments);
     }
-    List names = new List.filled(numNamedArguments, null);
+    List names = new List<dynamic>.filled(numNamedArguments, null);
     int argumentIndex = numPositionalArguments;
     int nameIndex = 0;
     if (numNamedArguments > 0) {
diff --git a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
index 9b66fad..9e2d4ac 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
@@ -116,10 +116,8 @@
     int old_capacity = _capacity;
     int new_capacity = new_length;
     if (new_capacity > old_capacity) {
-      if (null is! T) {
-        throw UnsupportedError(
-            "Cannot grow array with non-nullable element type");
-      }
+      // Verify that element type is nullable.
+      null as T;
       _grow(new_capacity);
       _setLength(new_length);
       return;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart
index e65d3d6..da4a441 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart
@@ -60,7 +60,9 @@
 
   Symbol _setMemberNameAndType() {
     final funcName = _functionName!;
-    _type = _METHOD;
+    if (_type == _UNINITIALIZED) {
+      _type = 0;
+    }
     if (funcName.startsWith("get:")) {
       _type |= _GETTER;
       _memberName = new internal.Symbol.unvalidated(funcName.substring(4));
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index 73ea82c..ee2ec48 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -82,6 +82,7 @@
 class _MirrorSystem extends MirrorSystem {
   final TypeMirror dynamicType = new _SpecialTypeMirror._('dynamic');
   final TypeMirror voidType = new _SpecialTypeMirror._('void');
+  final TypeMirror neverType = new _SpecialTypeMirror._('Never');
 
   var _libraries;
   Map<Uri, LibraryMirror> get libraries {
@@ -226,9 +227,9 @@
     int numPositionalArguments = positionalArguments.length;
     int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
-    List arguments = new List.filled(numArguments, null);
+    List arguments = new List<dynamic>.filled(numArguments, null);
     arguments.setRange(0, numPositionalArguments, positionalArguments);
-    List names = new List.filled(numNamedArguments, null);
+    List names = new List<dynamic>.filled(numNamedArguments, null);
     int argumentIndex = numPositionalArguments;
     int nameIndex = 0;
     if (numNamedArguments > 0) {
@@ -316,10 +317,10 @@
     int numPositionalArguments = positionalArguments.length + 1; // Receiver.
     int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
-    List arguments = new List.filled(numArguments, null);
+    List arguments = new List<dynamic>.filled(numArguments, null);
     arguments[0] = _reflectee; // Receiver.
     arguments.setRange(1, numPositionalArguments, positionalArguments);
-    List names = new List.filled(numNamedArguments, null);
+    List names = new List<dynamic>.filled(numNamedArguments, null);
     int argumentIndex = numPositionalArguments;
     int nameIndex = 0;
     if (numNamedArguments > 0) {
@@ -651,9 +652,9 @@
     int numPositionalArguments = positionalArguments.length;
     int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
-    List arguments = new List.filled(numArguments, null);
+    List arguments = new List<dynamic>.filled(numArguments, null);
     arguments.setRange(0, numPositionalArguments, positionalArguments);
-    List names = new List.filled(numNamedArguments, null);
+    List names = new List<dynamic>.filled(numNamedArguments, null);
     int argumentIndex = numPositionalArguments;
     int nameIndex = 0;
     if (numNamedArguments > 0) {
@@ -682,13 +683,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
@@ -890,13 +893,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
@@ -992,13 +997,15 @@
 
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return false;
+    if (other == currentMirrorSystem().voidType) return true;
+    if (other == currentMirrorSystem().neverType) return false;
     final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
diff --git a/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
index 1ed5de4..eea3b01 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
@@ -378,7 +378,9 @@
   }
 
   void fillRange(int start, int end, [int? fillValue]) {
-    if (fillValue == null) throw ArgumentError.notNull("fillValue");
+    if (fillValue == null && start < end) {
+      throw ArgumentError.notNull("fillValue");
+    }
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -734,7 +736,9 @@
 
   void fillRange(int start, int end, [double? fillValue]) {
     // TODO(eernst): Could use zero as default and not throw; issue .
-    if (fillValue == null) throw ArgumentError.notNull("fillValue");
+    if (fillValue == null && start < end) {
+      throw ArgumentError.notNull("fillValue");
+    }
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1170,7 +1174,9 @@
   }
 
   void fillRange(int start, int end, [Float32x4? fillValue]) {
-    if (fillValue == null) throw ArgumentError.notNull("fillValue");
+    if (fillValue == null && start < end) {
+      throw ArgumentError.notNull("fillValue");
+    }
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1526,7 +1532,9 @@
   }
 
   void fillRange(int start, int end, [Int32x4? fillValue]) {
-    if (fillValue == null) throw ArgumentError.notNull("fillValue");
+    if (fillValue == null && start < end) {
+      throw ArgumentError.notNull("fillValue");
+    }
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1883,7 +1891,9 @@
   }
 
   void fillRange(int start, int end, [Float64x2? fillValue]) {
-    if (fillValue == null) throw ArgumentError.notNull("fillValue");
+    if (fillValue == null && start < end) {
+      throw ArgumentError.notNull("fillValue");
+    }
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
diff --git a/sdk_nnbd/lib/async/future_impl.dart b/sdk_nnbd/lib/async/future_impl.dart
index 7ad4ff1..c012e53 100644
--- a/sdk_nnbd/lib/async/future_impl.dart
+++ b/sdk_nnbd/lib/async/future_impl.dart
@@ -393,7 +393,7 @@
   void _prependListeners(_FutureListener? listeners) {
     if (listeners == null) return;
     if (_mayAddListener) {
-      _FutureListener existingListeners = _resultOrListeners;
+      _FutureListener? existingListeners = _resultOrListeners;
       _resultOrListeners = listeners;
       if (existingListeners != null) {
         _FutureListener cursor = listeners;
diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart
index 1619fc3..e958a7b 100644
--- a/sdk_nnbd/lib/collection/list.dart
+++ b/sdk_nnbd/lib/collection/list.dart
@@ -371,12 +371,7 @@
     if (end == null) throw "!"; // TODO(38493): The `??=` should promote.
 
     RangeError.checkValidRange(start, end, listLength);
-    int length = end - start;
-    List<E> result = <E>[]..length = length;
-    for (int i = 0; i < length; i++) {
-      result[i] = this[start + i];
-    }
-    return result;
+    return List.from(getRange(start, end));
   }
 
   Iterable<E> getRange(int start, int end) {
diff --git a/sdk_nnbd/lib/collection/queue.dart b/sdk_nnbd/lib/collection/queue.dart
index 217b2d3..9daafb1 100644
--- a/sdk_nnbd/lib/collection/queue.dart
+++ b/sdk_nnbd/lib/collection/queue.dart
@@ -412,25 +412,29 @@
   /// The entry object of the first element in the queue.
   ///
   /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
-  /// Returns the entry object corresponding to the first element of the queue.
+  ///
+  /// Returns the entry object corresponding to the first element of the queue,
+  /// or `null` if the queue is empty.
   ///
   /// The entry objects can also be accessed using [lastEntry],
-  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-  /// [DoubleLinkedQueueEntry.previousEntry()].
-  DoubleLinkedQueueEntry<E> firstEntry() {
-    return _sentinel.nextEntry()!;
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and
+  /// [DoubleLinkedQueueEntry.previousEntry].
+  DoubleLinkedQueueEntry<E>? firstEntry() {
+    return _sentinel.nextEntry();
   }
 
   /// The entry object of the last element in the queue.
   ///
   /// Each element of the queue has an associated [DoubleLinkedQueueEntry].
-  /// Returns the entry object corresponding to the last element of the queue.
+  ///
+  /// Returns the entry object corresponding to the last element of the queue,
+  /// or `null` if the queue is empty.
   ///
   /// The entry objects can also be accessed using [firstEntry],
-  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry()] and
-  /// [DoubleLinkedQueueEntry.previousEntry()].
-  DoubleLinkedQueueEntry<E> lastEntry() {
-    return _sentinel.previousEntry()!;
+  /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and
+  /// [DoubleLinkedQueueEntry.previousEntry].
+  DoubleLinkedQueueEntry<E>? lastEntry() {
+    return _sentinel.previousEntry();
   }
 
   bool get isEmpty {
diff --git a/sdk_nnbd/lib/ffi/ffi.dart b/sdk_nnbd/lib/ffi/ffi.dart
index dbfbb3a..bf7f6e4 100644
--- a/sdk_nnbd/lib/ffi/ffi.dart
+++ b/sdk_nnbd/lib/ffi/ffi.dart
@@ -28,7 +28,7 @@
 
 /// Represents a pointer into the native C memory corresponding to "NULL", e.g.
 /// a pointer with address 0.
-final Pointer<Null> nullptr = Pointer.fromAddress(0);
+final Pointer<Never> nullptr = Pointer.fromAddress(0);
 
 /// Represents a pointer into the native C memory. Cannot be extended.
 @pragma("vm:entry-point")
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index 2bc2ee8..d97670a 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -96,7 +96,7 @@
 /// On a successful result the native JS result will be converted to a Dart Map.
 /// See [convertNativeToDart_Dictionary]. On a rejected promise the error is
 /// forwarded without change.
-Future<Map<String, dynamic>> promiseToFutureAsMap(jsPromise) =>
+Future<Map<String, dynamic>?> promiseToFutureAsMap(jsPromise) =>
     promiseToFuture(jsPromise).then(convertNativeToDart_Dictionary);
 
 // Workaround for tags like <cite> that lack their own Element subclass --
@@ -115,7 +115,11 @@
   HtmlElement.created() : super.created();
 
   // From NoncedElement
-  String nonce;
+  String get nonce => JS("String", "#.nonce", this);
+
+  set nonce(String value) {
+    JS("void", "#.nonce = #", this, value);
+  }
 }
 
 /**
@@ -216,11 +220,11 @@
   static Accelerometer _create_2() =>
       JS('Accelerometer', 'new Accelerometer()');
 
-  final num x;
+  num? get x => JS("num", "#.x", this);
 
-  final num y;
+  num? get y => JS("num", "#.y", this);
 
-  final num z;
+  num? get z => JS("num", "#.z", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -401,7 +405,7 @@
 
   void add(AccessibleNode node, AccessibleNode? before) native;
 
-  AccessibleNode item(int index) native;
+  AccessibleNode? item(int index) native;
 
   void remove(int index) native;
 }
@@ -428,7 +432,7 @@
   static AmbientLightSensor _create_2() =>
       JS('AmbientLightSensor', 'new AmbientLightSensor()');
 
-  final num illuminance;
+  num? get illuminance => JS("num", "#.illuminance", this);
 }
 // 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
@@ -599,7 +603,8 @@
 
   AnimationEffectReadOnly? effect;
 
-  Future get finished => JS("Future", "#.finished", this);
+  Future<Animation> get finished =>
+      promiseToFuture<Animation>(JS("", "#.finished", this));
 
   String get id => JS("String", "#.id", this);
 
@@ -615,11 +620,13 @@
     JS("void", "#.playbackRate = #", this, value);
   }
 
-  Future get ready => JS("Future", "#.ready", this);
+  Future<Animation> get ready =>
+      promiseToFuture<Animation>(JS("", "#.ready", this));
 
   num? startTime;
 
-  final AnimationTimeline? timeline;
+  AnimationTimeline? get timeline =>
+      JS("AnimationTimeline", "#.timeline", this);
 
   void cancel() native;
 
@@ -650,7 +657,7 @@
       JS("AnimationEffectTimingReadOnly", "#.timing", this);
 
   Map getComputedTiming() {
-    return convertNativeToDart_Dictionary(_getComputedTiming_1());
+    return convertNativeToDart_Dictionary(_getComputedTiming_1())!;
   }
 
   @JSName('getComputedTiming')
@@ -685,9 +692,9 @@
 
   // Shadowing definition.
 
-  Object get duration => JS("Object", "#.duration", this);
+  Object? get duration => JS("Object", "#.duration", this);
 
-  set duration(Object value) {
+  set duration(Object? value) {
     JS("void", "#.duration = #", this, value);
   }
 
@@ -746,7 +753,7 @@
 
   String get direction => JS("String", "#.direction", this);
 
-  Object get duration => JS("Object", "#.duration", this);
+  Object? get duration => JS("Object", "#.duration", this);
 
   String get easing => JS("String", "#.easing", this);
 
@@ -811,9 +818,9 @@
   static AnimationPlaybackEvent _create_2(type) =>
       JS('AnimationPlaybackEvent', 'new AnimationPlaybackEvent(#)', type);
 
-  final num currentTime;
+  num? get currentTime => JS("num", "#.currentTime", this);
 
-  final num timelineTime;
+  num? get timelineTime => JS("num", "#.timelineTime", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -826,7 +833,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final num currentTime;
+  num? get currentTime => JS("num", "#.currentTime", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -1176,7 +1183,7 @@
    */
   AudioElement.created() : super.created();
 
-  factory AudioElement([String src]) => new AudioElement._(src);
+  factory AudioElement([String? src]) => new AudioElement._(src);
 }
 // 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
@@ -1400,7 +1407,7 @@
       request,
       response);
 
-  final _Response? response;
+  _Response? get response => JS("_Response", "#.response", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -1543,7 +1550,8 @@
 
   List<String> get platforms => JS("List<String>", "#.platforms", this);
 
-  Future get userChoice => JS("Future", "#.userChoice", this);
+  Future<Map<String, dynamic>?> get userChoice =>
+      promiseToFutureAsMap(JS("", "#.userChoice", this));
 
   Future prompt() => promiseToFuture(JS("", "#.prompt()", this));
 }
@@ -1583,7 +1591,7 @@
 
   Blob slice([int? start, int? end, String? contentType]) native;
 
-  factory Blob(List blobParts, [String type, String endings]) {
+  factory Blob(List blobParts, [String? type, String? endings]) {
     // TODO: validate that blobParts is a JS Array and convert if not.
     // TODO: any coercions on the elements of blobParts, e.g. coerce a typed
     // array to ArrayBuffer if it is a total view.
@@ -1649,7 +1657,7 @@
 
   String get uuid => JS("String", "#.uuid", this);
 
-  final ByteData? value;
+  ByteData? get value => JS("ByteData", "#.value", this);
 
   Future readValue() => promiseToFuture(JS("", "#.readValue()", this));
 
@@ -1930,7 +1938,7 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   String get formAction => JS("String", "#.formAction", this);
 
@@ -1963,7 +1971,7 @@
   }
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -2138,8 +2146,6 @@
 
   int get height => JS("int", "#.height", this);
 
-  /// The height of this canvas element in CSS pixels.
-
   set height(int value) {
     JS("void", "#.height = #", this, value);
   }
@@ -2148,8 +2154,6 @@
 
   int get width => JS("int", "#.width", this);
 
-  /// The width of this canvas element in CSS pixels.
-
   set width(int value) {
     JS("void", "#.width = #", this, value);
   }
@@ -2158,7 +2162,7 @@
 
   @Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')
   @Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')
-  Object getContext(String contextId, [Map? attributes]) {
+  Object? getContext(String contextId, [Map? attributes]) {
     if (attributes != null) {
       var attributes_1 = convertDartToNative_Dictionary(attributes);
       return _getContext_1(contextId, attributes_1);
@@ -2169,14 +2173,14 @@
   @JSName('getContext')
   @Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')
   @Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')
-  Object _getContext_1(contextId, attributes) native;
+  Object? _getContext_1(contextId, attributes) native;
   @JSName('getContext')
   @Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')
   @Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')
-  Object _getContext_2(contextId) native;
+  Object? _getContext_2(contextId) native;
 
   @JSName('toDataURL')
-  String _toDataUrl(String type, [arguments_OR_quality]) native;
+  String _toDataUrl(String? type, [arguments_OR_quality]) native;
 
   OffscreenCanvas transferControlToOffscreen() native;
 
@@ -2222,7 +2226,7 @@
     if (context == null) {
       context = getContext('experimental-webgl', options);
     }
-    return context;
+    return context as gl.RenderingContext;
   }
 
   /**
@@ -2266,7 +2270,7 @@
    *
    * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.
    */
-  String toDataUrl([String type = 'image/png', num quality]) =>
+  String toDataUrl([String type = 'image/png', num? quality]) =>
       _toDataUrl(type, quality);
 
   @JSName('toBlob')
@@ -2405,13 +2409,7 @@
 
   @Creates('String|CanvasGradient|CanvasPattern')
   @Returns('String|CanvasGradient|CanvasPattern')
-  Object get fillStyle => JS("Object", "#.fillStyle", this);
-
-  @Creates('String|CanvasGradient|CanvasPattern')
-  @Returns('String|CanvasGradient|CanvasPattern')
-  set fillStyle(Object value) {
-    JS("void", "#.fillStyle = #", this, value);
-  }
+  Object? fillStyle;
 
   String get filter => JS("String", "#.filter", this);
 
@@ -2451,17 +2449,6 @@
 
   bool get imageSmoothingEnabled => JS("bool", "#.imageSmoothingEnabled", this);
 
-  /**
-   * Whether images and patterns on this canvas will be smoothed when this
-   * canvas is scaled.
-   *
-   * ## Other resources
-   *
-   * * [Image
-   *   smoothing](https://html.spec.whatwg.org/multipage/scripting.html#image-smoothing)
-   *   from WHATWG.
-   */
-
   set imageSmoothingEnabled(bool value) {
     JS("void", "#.imageSmoothingEnabled = #", this, value);
   }
@@ -2523,13 +2510,7 @@
 
   @Creates('String|CanvasGradient|CanvasPattern')
   @Returns('String|CanvasGradient|CanvasPattern')
-  Object get strokeStyle => JS("Object", "#.strokeStyle", this);
-
-  @Creates('String|CanvasGradient|CanvasPattern')
-  @Returns('String|CanvasGradient|CanvasPattern')
-  set strokeStyle(Object value) {
-    JS("void", "#.strokeStyle = #", this, value);
-  }
+  Object? strokeStyle;
 
   String get textAlign => JS("String", "#.textAlign", this);
 
@@ -2627,14 +2608,14 @@
   _createImageData_3(int sw, sh, imageDataColorSettings) native;
   @JSName('createImageData')
   @Creates('ImageData|=Object')
-  _createImageData_4(data, sw, int sh) native;
+  _createImageData_4(data, sw, int? sh) native;
   @JSName('createImageData')
   @Creates('ImageData|=Object')
-  _createImageData_5(data, sw, int sh, imageDataColorSettings) native;
+  _createImageData_5(data, sw, int? sh, imageDataColorSettings) native;
 
   CanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) native;
 
-  CanvasPattern createPattern(Object image, String repetitionType) native;
+  CanvasPattern? createPattern(Object image, String repetitionType) native;
 
   CanvasGradient createRadialGradient(
       num x0, num y0, num r0, num x1, num y1, num r1) native;
@@ -2646,7 +2627,7 @@
   void fillRect(num x, num y, num width, num height) native;
 
   Map getContextAttributes() {
-    return convertNativeToDart_Dictionary(_getContextAttributes_1());
+    return convertNativeToDart_Dictionary(_getContextAttributes_1())!;
   }
 
   @JSName('getContextAttributes')
@@ -2731,7 +2712,7 @@
 
   @JSName('arc')
   void _arc(num x, num y, num radius, num startAngle, num endAngle,
-      bool anticlockwise) native;
+      bool? anticlockwise) native;
 
   void arcTo(num x1, num y1, num x2, num y2, num radius) native;
 
@@ -2741,7 +2722,7 @@
   void closePath() native;
 
   void ellipse(num x, num y, num radiusX, num radiusY, num rotation,
-      num startAngle, num endAngle, bool anticlockwise) native;
+      num startAngle, num endAngle, bool? anticlockwise) native;
 
   void lineTo(num x, num y) native;
 
@@ -2842,7 +2823,7 @@
    * from the WHATWG.
    */
   void drawImageToRect(CanvasImageSource source, Rectangle destRect,
-      {Rectangle sourceRect}) {
+      {Rectangle? sourceRect}) {
     if (sourceRect == null) {
       drawImageScaled(
           source, destRect.left, destRect.top, destRect.width, destRect.height);
@@ -3032,7 +3013,7 @@
    * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
    * drawn text.
    */
-  void fillText(String text, num x, num y, [num maxWidth]) {
+  void fillText(String text, num x, num y, [num? maxWidth]) {
     if (maxWidth != null) {
       JS('void', '#.fillText(#, #, #, #)', this, text, x, y, maxWidth);
     } else {
@@ -3082,9 +3063,11 @@
 
   // From NonDocumentTypeChildNode
 
-  final Element? nextElementSibling;
+  Element? get nextElementSibling =>
+      JS("Element", "#.nextElementSibling", this);
 
-  final Element? previousElementSibling;
+  Element? get previousElementSibling =>
+      JS("Element", "#.previousElementSibling", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3173,7 +3156,8 @@
   static ClipboardEvent _create_2(type) =>
       JS('ClipboardEvent', 'new ClipboardEvent(#)', type);
 
-  final DataTransfer? clipboardData;
+  DataTransfer? get clipboardData =>
+      JS("DataTransfer", "#.clipboardData", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3210,7 +3194,7 @@
 
 @Native("Comment")
 class Comment extends CharacterData {
-  factory Comment([String data]) {
+  factory Comment([String? data]) {
     return JS('returns:Comment;depends:none;effects:none;new:true',
         '#.createComment(#)', document, data == null ? "" : data);
   }
@@ -3230,13 +3214,14 @@
   factory CompositionEvent(String type,
       {bool canBubble: false,
       bool cancelable: false,
-      Window view,
-      String data,
-      String locale}) {
+      Window? view,
+      String? data,
+      String? locale}) {
     if (view == null) {
       view = window;
     }
-    CompositionEvent e = document._createEvent("CompositionEvent");
+    CompositionEvent e =
+        document._createEvent("CompositionEvent") as CompositionEvent;
 
     if (Device.isFirefox) {
       // Firefox requires the locale parameter that isn't supported elsewhere.
@@ -3264,8 +3249,8 @@
   String get data => JS("String", "#.data", this);
 
   @JSName('initCompositionEvent')
-  void _initCompositionEvent(String type, bool bubbles, bool cancelable,
-      Window? view, String data) native;
+  void _initCompositionEvent(String? type, bool? bubbles, bool? cancelable,
+      Window? view, String? data) native;
 }
 // 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
@@ -3297,7 +3282,7 @@
     JS("void", "#.select = #", this, value);
   }
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getDistributedNodes() native;
 }
@@ -3342,17 +3327,17 @@
 
   num get accuracy => JS("num", "#.accuracy", this);
 
-  final num altitude;
+  num? get altitude => JS("num", "#.altitude", this);
 
-  final num altitudeAccuracy;
+  num? get altitudeAccuracy => JS("num", "#.altitudeAccuracy", this);
 
-  final num heading;
+  num? get heading => JS("num", "#.heading", this);
 
   num get latitude => JS("num", "#.latitude", this);
 
   num get longitude => JS("num", "#.longitude", this);
 
-  final num speed;
+  num? get speed => JS("num", "#.speed", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3609,7 +3594,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  @Returns('_CssRuleList|Null')
+  @Returns('_CssRuleList')
   @Creates('_CssRuleList')
   List<CssRule> get cssRules => JS("_CssRuleList", "#.cssRules", this);
 
@@ -3628,11 +3613,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final num intrinsicHeight;
+  num? get intrinsicHeight => JS("num", "#.intrinsicHeight", this);
 
-  final num intrinsicRatio;
+  num? get intrinsicRatio => JS("num", "#.intrinsicRatio", this);
 
-  final num intrinsicWidth;
+  num? get intrinsicWidth => JS("num", "#.intrinsicWidth", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3681,7 +3666,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  @Returns('_CssRuleList|Null')
+  @Returns('_CssRuleList')
   @Creates('_CssRuleList')
   List<CssRule> get cssRules => JS("_CssRuleList", "#.cssRules", this);
 
@@ -3697,7 +3682,7 @@
 
   void deleteRule(String select) native;
 
-  CssKeyframeRule findRule(String select) native;
+  CssKeyframeRule? findRule(String select) native;
 }
 // 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
@@ -3982,9 +3967,10 @@
     JS("void", "#.cssText = #", this, value);
   }
 
-  final CssRule? parentRule;
+  CssRule? get parentRule => JS("CssRule", "#.parentRule", this);
 
-  final CssStyleSheet? parentStyleSheet;
+  CssStyleSheet? get parentStyleSheet =>
+      JS("CssStyleSheet", "#.parentStyleSheet", this);
 
   int get type => JS("int", "#.type", this);
 }
@@ -4110,7 +4096,7 @@
     return JS('bool', '# in #', propertyName, this);
   }
 
-  void setProperty(String propertyName, String value, [String priority]) {
+  void setProperty(String propertyName, String value, [String? priority]) {
     return _setPropertyHelper(
         _browserPropertyName(propertyName), value, priority);
   }
@@ -4184,7 +4170,7 @@
 
   int get length => JS("int", "#.length", this);
 
-  final CssRule? parentRule;
+  CssRule? get parentRule => JS("CssRule", "#.parentRule", this);
 
   String getPropertyPriority(String property) native;
 
@@ -5278,7 +5264,7 @@
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
   final Iterable<Element> _elementIterable;
-  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+  Iterable<CssStyleDeclaration>? _elementCssStyleDeclarationSetIterable;
 
   _CssStyleDeclarationSet(this._elementIterable) {
     _elementCssStyleDeclarationSetIterable =
@@ -5286,11 +5272,11 @@
   }
 
   String getPropertyValue(String propertyName) =>
-      _elementCssStyleDeclarationSetIterable.first
+      _elementCssStyleDeclarationSetIterable!.first
           .getPropertyValue(propertyName);
 
-  void setProperty(String propertyName, String value, [String priority]) {
-    _elementCssStyleDeclarationSetIterable
+  void setProperty(String propertyName, String value, [String? priority]) {
+    _elementCssStyleDeclarationSetIterable!
         .forEach((e) => e.setProperty(propertyName, value, priority));
   }
 
@@ -5760,7 +5746,7 @@
 
 abstract class CssStyleDeclarationBase {
   String getPropertyValue(String propertyName);
-  void setProperty(String propertyName, String value, [String priority]);
+  void setProperty(String propertyName, String value, [String? priority]);
 
   /** Gets the value of "align-content" */
   String get alignContent => getPropertyValue('align-content');
@@ -8549,23 +8535,23 @@
     throw new UnsupportedError("Not supported");
   }
 
-  @Returns('_CssRuleList|Null')
+  @Returns('_CssRuleList')
   @Creates('_CssRuleList')
   List<CssRule> get cssRules => JS("_CssRuleList", "#.cssRules", this);
 
-  final CssRule? ownerRule;
+  CssRule? get ownerRule => JS("CssRule", "#.ownerRule", this);
 
-  @Returns('_CssRuleList|Null')
+  @Returns('_CssRuleList')
   @Creates('_CssRuleList')
   List<CssRule> get rules => JS("_CssRuleList", "#.rules", this);
 
-  int addRule(String selector, String style, [int? index]) native;
+  int addRule(String? selector, String? style, [int? index]) native;
 
   void deleteRule(int index) native;
 
   int insertRule(String rule, [int? index]) native;
 
-  void removeRule(int index) native;
+  void removeRule(int? index) native;
 }
 // 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
@@ -8578,7 +8564,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  static Object parse(String property, String cssText) native;
+  static Object? parse(String property, String cssText) native;
 }
 // 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
@@ -8732,7 +8718,7 @@
 
   int get length => JS("int", "#.length", this);
 
-  Object fragmentAtIndex(int index) native;
+  Object? fragmentAtIndex(int index) native;
 }
 // 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
@@ -8816,7 +8802,7 @@
   @JSName('define')
   void _define_2(name, constructor) native;
 
-  Object get(String name) native;
+  Object? get(String name) native;
 
   Future whenDefined(String name) =>
       promiseToFuture(JS("", "#.whenDefined(#)", this, name));
@@ -8833,8 +8819,8 @@
   var _dartDetail;
 
   factory CustomEvent(String type,
-      {bool canBubble: true, bool cancelable: true, Object detail}) {
-    final CustomEvent e = document._createEvent('CustomEvent');
+      {bool canBubble: true, bool cancelable: true, Object? detail}) {
+    final CustomEvent e = document._createEvent('CustomEvent') as CustomEvent;
 
     e._dartDetail = detail;
 
@@ -8877,7 +8863,7 @@
       convertNativeToDart_SerializedScriptValue(this._get__detail);
   @JSName('detail')
   @Creates('Null')
-  final dynamic _get__detail;
+  dynamic get _get__detail => JS("", "#.detail", this);
 
   @JSName('initCustomEvent')
   void _initCustomEvent(String type,
@@ -8956,7 +8942,7 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('datalist');
 
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get options => JS("HtmlCollection", "#.options", this);
 }
@@ -8988,7 +8974,7 @@
     JS("void", "#.effectAllowed = #", this, value);
   }
 
-  @Returns('FileList|Null')
+  @Returns('FileList')
   @Creates('FileList')
   List<File> get files => JS("FileList", "#.files", this);
 
@@ -9011,7 +8997,7 @@
 @Native("DataTransferItem")
 class DataTransferItem extends Interceptor {
   Entry getAsEntry() {
-    Entry entry = _webkitGetAsEntry();
+    Entry entry = _webkitGetAsEntry() as Entry;
 
     if (entry.isFile)
       applyExtension('FileEntry', entry);
@@ -9032,12 +9018,12 @@
 
   String get type => JS("String", "#.type", this);
 
-  File getAsFile() native;
+  File? getAsFile() native;
 
   @JSName('webkitGetAsEntry')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
-  Entry _webkitGetAsEntry() native;
+  Entry? _webkitGetAsEntry() native;
 }
 // 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
@@ -9052,13 +9038,13 @@
 
   int get length => JS("int", "#.length", this);
 
-  DataTransferItem add(data_OR_file, [String? type]) native;
+  DataTransferItem? add(data_OR_file, [String? type]) native;
 
   @JSName('add')
-  DataTransferItem addData(String data, String type) native;
+  DataTransferItem? addData(String data, String type) native;
 
   @JSName('add')
-  DataTransferItem addFile(File file) native;
+  DataTransferItem? addFile(File file) native;
 
   void clear() native;
 
@@ -9330,11 +9316,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final num x;
+  num? get x => JS("num", "#.x", this);
 
-  final num y;
+  num? get y => JS("num", "#.y", this);
 
-  final num z;
+  num? get z => JS("num", "#.z", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -9359,13 +9345,16 @@
   static DeviceMotionEvent _create_2(type) =>
       JS('DeviceMotionEvent', 'new DeviceMotionEvent(#)', type);
 
-  final DeviceAcceleration? acceleration;
+  DeviceAcceleration? get acceleration =>
+      JS("DeviceAcceleration", "#.acceleration", this);
 
-  final DeviceAcceleration? accelerationIncludingGravity;
+  DeviceAcceleration? get accelerationIncludingGravity =>
+      JS("DeviceAcceleration", "#.accelerationIncludingGravity", this);
 
   num get interval => JS("num", "#.interval", this);
 
-  final DeviceRotationRate? rotationRate;
+  DeviceRotationRate? get rotationRate =>
+      JS("DeviceRotationRate", "#.rotationRate", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -9395,11 +9384,11 @@
 
   bool get absolute => JS("bool", "#.absolute", this);
 
-  final num alpha;
+  num? get alpha => JS("num", "#.alpha", this);
 
-  final num beta;
+  num? get beta => JS("num", "#.beta", this);
 
-  final num gamma;
+  num? get gamma => JS("num", "#.gamma", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -9412,11 +9401,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final num alpha;
+  num? get alpha => JS("num", "#.alpha", this);
 
-  final num beta;
+  num? get beta => JS("num", "#.beta", this);
 
-  final num gamma;
+  num? get gamma => JS("num", "#.gamma", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -9535,10 +9524,10 @@
   }
 
   @JSName('getDirectory')
-  void __getDirectory_1(path, options, _EntryCallback successCallback,
-      _ErrorCallback errorCallback) native;
+  void __getDirectory_1(path, options, _EntryCallback? successCallback,
+      _ErrorCallback? errorCallback) native;
   @JSName('getDirectory')
-  void __getDirectory_2(path, options, _EntryCallback successCallback) native;
+  void __getDirectory_2(path, options, _EntryCallback? successCallback) native;
   @JSName('getDirectory')
   void __getDirectory_3(path, options) native;
   @JSName('getDirectory')
@@ -9579,10 +9568,10 @@
   }
 
   @JSName('getFile')
-  void __getFile_1(path, options, _EntryCallback successCallback,
-      _ErrorCallback errorCallback) native;
+  void __getFile_1(path, options, _EntryCallback? successCallback,
+      _ErrorCallback? errorCallback) native;
   @JSName('getFile')
-  void __getFile_2(path, options, _EntryCallback successCallback) native;
+  void __getFile_2(path, options, _EntryCallback? successCallback) native;
   @JSName('getFile')
   void __getFile_3(path, options) native;
   @JSName('getFile')
@@ -9766,7 +9755,8 @@
     JS("void", "#.cookie = #", this, value);
   }
 
-  final ScriptElement? currentScript;
+  ScriptElement? get currentScript =>
+      JS("ScriptElement", "#.currentScript", this);
 
   WindowBase? get window => _convertNativeToDart_Window(this._get_window);
   @JSName('defaultView')
@@ -9774,16 +9764,16 @@
   @Returns('Window|=Object')
   @Creates('Window|=Object|Null')
   @Returns('Window|=Object|Null')
-  final dynamic _get_window;
+  dynamic get _get_window => JS("", "#.defaultView", this);
 
-  final Element? documentElement;
+  Element? get documentElement => JS("Element", "#.documentElement", this);
 
   String get domain => JS("String", "#.domain", this);
 
   bool get fullscreenEnabled => JS("bool", "#.fullscreenEnabled", this);
 
   @JSName('head')
-  final HeadElement? _head;
+  HeadElement? get _head => JS("HeadElement", "#.head", this);
 
   bool get hidden => JS("bool", "#.hidden", this);
 
@@ -9796,7 +9786,8 @@
   String get origin => JS("String", "#.origin", this);
 
   @JSName('preferredStylesheetSet')
-  final String? _preferredStylesheetSet;
+  String? get _preferredStylesheetSet =>
+      JS("String", "#.preferredStylesheetSet", this);
 
   String get readyState => JS("String", "#.readyState", this);
 
@@ -9807,7 +9798,7 @@
 
   Element? rootScroller;
 
-  final Element? scrollingElement;
+  Element? get scrollingElement => JS("Element", "#.scrollingElement", this);
 
   @JSName('selectedStylesheetSet')
   String? _selectedStylesheetSet;
@@ -9853,7 +9844,7 @@
   Node adoptNode(Node node) native;
 
   @JSName('caretRangeFromPoint')
-  Range _caretRangeFromPoint(int x, int y) native;
+  Range _caretRangeFromPoint(int? x, int? y) native;
 
   DocumentFragment createDocumentFragment() native;
 
@@ -9972,24 +9963,25 @@
 
   // From NonElementParentNode
 
-  Element getElementById(String elementId) native;
+  Element? getElementById(String elementId) native;
 
   // From DocumentOrShadowRoot
 
-  final Element? activeElement;
+  Element? get activeElement => JS("Element", "#.activeElement", this);
 
-  final Element? fullscreenElement;
+  Element? get fullscreenElement => JS("Element", "#.fullscreenElement", this);
 
-  final Element? pointerLockElement;
+  Element? get pointerLockElement =>
+      JS("Element", "#.pointerLockElement", this);
 
   @JSName('styleSheets')
-  @Returns('_StyleSheetList|Null')
+  @Returns('_StyleSheetList')
   @Creates('_StyleSheetList')
   List<StyleSheet> get _styleSheets =>
       JS("_StyleSheetList", "#.styleSheets", this);
 
   @JSName('elementFromPoint')
-  Element _elementFromPoint(int x, int y) native;
+  Element? _elementFromPoint(int x, int y) native;
 
   List<Element> elementsFromPoint(int x, int y) native;
 
@@ -10003,15 +9995,15 @@
   int get _childElementCount => JS("int", "#.childElementCount", this);
 
   @JSName('children')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _children => JS("HtmlCollection", "#.children", this);
 
   @JSName('firstElementChild')
-  final Element? _firstElementChild;
+  Element? get _firstElementChild => JS("Element", "#.firstElementChild", this);
 
   @JSName('lastElementChild')
-  final Element? _lastElementChild;
+  Element? get _lastElementChild => JS("Element", "#.lastElementChild", this);
 
   /**
    * Finds the first descendant element of this document that matches the
@@ -10030,7 +10022,7 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  Element querySelector(String selectors) native;
+  Element? querySelector(String selectors) native;
 
   @JSName('querySelectorAll')
   @Creates('NodeList')
@@ -10272,13 +10264,13 @@
   bool get supportsRegister => supportsRegisterElement;
 
   void registerElement(String tag, Type customElementClass,
-      {String extendsTag}) {
+      {String? extendsTag}) {
     registerElement2(
         tag, {'prototype': customElementClass, 'extends': extendsTag});
   }
 
   @pragma('dart2js:tryInline') // Almost all call sites have one argument.
-  Element createElement(String tagName, [String typeExtension]) {
+  Element createElement(String tagName, [String? typeExtension]) {
     return (typeExtension == null)
         ? _createElement_2(tagName)
         : _createElement(tagName, typeExtension);
@@ -10295,19 +10287,19 @@
       'Element', '#.createElementNS(#, #)', this, namespaceURI, qualifiedName);
 
   Element createElementNS(String namespaceURI, String qualifiedName,
-      [String typeExtension]) {
+      [String? typeExtension]) {
     return (typeExtension == null)
         ? _createElementNS_2(namespaceURI, qualifiedName)
         : _createElementNS(namespaceURI, qualifiedName, typeExtension);
   }
 
   NodeIterator _createNodeIterator(Node root,
-          [int whatToShow, NodeFilter filter]) =>
+          [int? whatToShow, NodeFilter? filter]) =>
       JS('NodeIterator', '#.createNodeIterator(#, #, #, false)', this, root,
           whatToShow, filter);
 
   TreeWalker _createTreeWalker(Node root,
-          [int whatToShow, NodeFilter filter]) =>
+          [int? whatToShow, NodeFilter? filter]) =>
       JS('TreeWalker', '#.createTreeWalker(#, #, #, false)', this, root,
           whatToShow, filter);
 
@@ -10333,13 +10325,13 @@
   factory DocumentFragment() => document.createDocumentFragment();
 
   factory DocumentFragment.html(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     return document.body.createFragment(html,
         validator: validator, treeSanitizer: treeSanitizer);
   }
 
   factory DocumentFragment.svg(String svgContent,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     return new svg.SvgSvgElement().createFragment(svgContent,
         validator: validator, treeSanitizer: treeSanitizer);
   }
@@ -10392,7 +10384,7 @@
   }
 
   void setInnerHtml(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     this.nodes.clear();
     append(document.body.createFragment(html,
         validator: validator, treeSanitizer: treeSanitizer));
@@ -10411,7 +10403,7 @@
    * last child of this document fragment.
    */
   void appendHtml(String text,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     this.append(new DocumentFragment.html(text,
         validator: validator, treeSanitizer: treeSanitizer));
   }
@@ -10423,7 +10415,7 @@
 
   // From NonElementParentNode
 
-  Element getElementById(String elementId) native;
+  Element? getElementById(String elementId) native;
 
   // From ParentNode
 
@@ -10431,10 +10423,10 @@
   int get _childElementCount => JS("int", "#.childElementCount", this);
 
   @JSName('firstElementChild')
-  final Element? _firstElementChild;
+  Element? get _firstElementChild => JS("Element", "#.firstElementChild", this);
 
   @JSName('lastElementChild')
-  final Element? _lastElementChild;
+  Element? get _lastElementChild => JS("Element", "#.lastElementChild", this);
 
   /**
    * Finds the first descendant element of this document fragment that matches
@@ -10448,7 +10440,7 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  Element querySelector(String selectors) native;
+  Element? querySelector(String selectors) native;
 
   @JSName('querySelectorAll')
   @Creates('NodeList')
@@ -10466,22 +10458,23 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final Element? activeElement;
+  Element? get activeElement => JS("Element", "#.activeElement", this);
 
-  final Element? fullscreenElement;
+  Element? get fullscreenElement => JS("Element", "#.fullscreenElement", this);
 
-  final Element? pointerLockElement;
+  Element? get pointerLockElement =>
+      JS("Element", "#.pointerLockElement", this);
 
-  @Returns('_StyleSheetList|Null')
+  @Returns('_StyleSheetList')
   @Creates('_StyleSheetList')
   List<StyleSheet> get styleSheets =>
       JS("_StyleSheetList", "#.styleSheets", this);
 
-  Element elementFromPoint(int x, int y) native;
+  Element? elementFromPoint(int x, int y) native;
 
   List<Element> elementsFromPoint(int x, int y) native;
 
-  Selection getSelection() native;
+  Selection? getSelection() native;
 }
 // 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
@@ -10579,7 +10572,7 @@
     // Chrome release still uses old string, remove this line when Chrome stable
     // also prints out SyntaxError.
     if (Device.isWebKit && errorName == 'SYNTAX_ERR') return 'SyntaxError';
-    return errorName;
+    return errorName as String;
   }
 
   // To suppress missing implicit constructor warnings.
@@ -10624,7 +10617,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Object next([Object? value]) native;
+  Object? next([Object? value]) native;
 }
 // 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
@@ -11348,7 +11341,7 @@
   Rectangle elementAt(int index) => this[index];
   // -- end List<Rectangle> mixins.
 
-  Rectangle item(int index) native;
+  Rectangle? item(int index) native;
 }
 // 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
@@ -11380,7 +11373,7 @@
    * Returns the intersection of this and `other`, or null if they don't
    * intersect.
    */
-  Rectangle intersection(Rectangle other) {
+  Rectangle? intersection(Rectangle other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
@@ -11563,7 +11556,7 @@
   String elementAt(int index) => this[index];
   // -- end List<String> mixins.
 
-  String item(int index) native;
+  String? item(int index) native;
 }
 // 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
@@ -11605,7 +11598,7 @@
 
   bool contains(String token) native;
 
-  String item(int index) native;
+  String? item(int index) native;
 
   void remove(String tokens) native;
 
@@ -11626,7 +11619,7 @@
   final HtmlCollection _childElements;
 
   _ChildrenElementList._wrap(Element element)
-      : _childElements = element._children,
+      : _childElements = element._children as HtmlCollection,
         _element = element;
 
   bool contains(Object? element) => _childElements.contains(element);
@@ -11640,7 +11633,7 @@
   }
 
   Element operator [](int index) {
-    return _childElements[index];
+    return _childElements[index] as Element;
   }
 
   void operator []=(int index, Element value) {
@@ -11759,13 +11752,13 @@
   }
 
   Element get first {
-    Element result = _element._firstElementChild;
+    Element? result = _element._firstElementChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
 
   Element get last {
-    Element result = _element._lastElementChild;
+    Element? result = _element._lastElementChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
@@ -12171,7 +12164,7 @@
 
   int get length => _nodeList.length;
 
-  E operator [](int index) => _nodeList[index];
+  E operator [](int index) => _nodeList[index] as E;
 
   void operator []=(int index, E value) {
     throw new UnsupportedError('Cannot modify list');
@@ -12189,11 +12182,11 @@
     throw new UnsupportedError('Cannot shuffle list');
   }
 
-  E get first => _nodeList.first;
+  E get first => _nodeList.first as E;
 
-  E get last => _nodeList.last;
+  E get last => _nodeList.last as E;
 
-  E get single => _nodeList.single;
+  E get single => _nodeList.single as E;
 
   CssClassSet get classes => new _MultiElementCssClassSet(this);
 
@@ -12601,11 +12594,11 @@
    *
    */
   factory Element.html(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     var fragment = document.body.createFragment(html,
         validator: validator, treeSanitizer: treeSanitizer);
 
-    return fragment.nodes.where((e) => e is Element).single;
+    return fragment.nodes.where((e) => e is Element).single as Element;
   }
 
   /**
@@ -12650,8 +12643,8 @@
    *
    * * [isTagSupported]
    */
-  factory Element.tag(String tag, [String typeExtention]) =>
-      _ElementFactoryProvider.createElement_tag(tag, typeExtention);
+  factory Element.tag(String tag, [String? typeExtension]) =>
+      _ElementFactoryProvider.createElement_tag(tag, typeExtension);
 
   /// Creates a new `<a>` element.
   ///
@@ -12814,67 +12807,57 @@
     Map<String, String> attributes = this.attributes;
     attributes.clear();
     for (String key in value.keys) {
-      attributes[key] = value[key];
+      attributes[key] = value[key]!;
     }
   }
 
   @pragma('dart2js:tryInline')
-  String getAttribute(String name) {
+  String? getAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
-    assert(name != null, 'Attribute name cannot be null');
     return _getAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  String getAttributeNS(String namespaceURI, String name) {
+  String? getAttributeNS(String? namespaceURI, String name) {
     // 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');
     return _getAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   bool hasAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
-    assert(name != null, 'Attribute name cannot be null');
     return _hasAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  bool hasAttributeNS(String namespaceURI, String name) {
+  bool hasAttributeNS(String? namespaceURI, String name) {
     // 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');
     return _hasAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   void removeAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
-    assert(name != null, 'Attribute name cannot be null');
     _removeAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  void removeAttributeNS(String namespaceURI, String name) {
+  void removeAttributeNS(String? namespaceURI, String name) {
     // Protect [name] against string conversion to "null" or "undefined".
-    assert(name != null, 'Attribute name cannot be null');
     _removeAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   void setAttribute(String name, String value) {
     // 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.');
     _setAttribute(name, value);
   }
 
   @pragma('dart2js:tryInline')
-  void setAttributeNS(String namespaceURI, String name, String value) {
+  void setAttributeNS(String? namespaceURI, String name, String value) {
     // 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.');
     _setAttributeNS(namespaceURI, name, value);
   }
 
@@ -12988,7 +12971,7 @@
     final data = this.dataset;
     data.clear();
     for (String key in value.keys) {
-      data[key] = value[key];
+      data[key] = value[key]!;
     }
   }
 
@@ -13052,7 +13035,7 @@
    * last child of this element.
    */
   void appendHtml(String text,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     this.insertAdjacentHtml('beforeend', text,
         validator: validator, treeSanitizer: treeSanitizer);
   }
@@ -13177,7 +13160,7 @@
    * * [Node.namespaceURI](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSname)
    *   from W3C.
    */
-  String get namespaceUri => _namespaceUri;
+  String? get namespaceUri => _namespaceUri;
 
   /**
    * The string representation of this element.
@@ -13205,7 +13188,7 @@
    * * [scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
    *   from MDN.
    */
-  void scrollIntoView([ScrollAlignment alignment]) {
+  void scrollIntoView([ScrollAlignment? alignment]) {
     var hasScrollIntoViewIfNeeded = true;
     hasScrollIntoViewIfNeeded =
         JS('bool', '!!(#.scrollIntoViewIfNeeded)', this);
@@ -13300,7 +13283,7 @@
    * * [insertAdjacentElement]
    */
   void insertAdjacentHtml(String where, String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
       _insertAdjacentHtml(where, html);
     } else {
@@ -13339,7 +13322,7 @@
   void _insertAdjacentNode(String where, Node node) {
     switch (where.toLowerCase()) {
       case 'beforebegin':
-        this.parentNode.insertBefore(node, this);
+        this.parentNode!.insertBefore(node, this);
         break;
       case 'afterbegin':
         var first = this.nodes.length > 0 ? this.nodes[0] : null;
@@ -13349,7 +13332,7 @@
         this.append(node);
         break;
       case 'afterend':
-        this.parentNode.insertBefore(node, this.nextNode);
+        this.parentNode!.insertBefore(node, this.nextNode);
         break;
       default:
         throw new ArgumentError("Invalid position ${where}");
@@ -13377,9 +13360,9 @@
 
   /** Checks if this element or any of its parents match the CSS selectors. */
   bool matchesWithAncestors(String selectors) {
-    var elem = this;
+    var elem = this as Element?;
     do {
-      if (elem.matches(selectors)) return true;
+      if (elem!.matches(selectors)) return true;
       elem = elem.parent;
     } while (elem != null);
     return false;
@@ -13495,7 +13478,7 @@
    * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
-  Point get documentOffset => offsetTo(document.documentElement);
+  Point get documentOffset => offsetTo(document.documentElement!);
 
   /**
    * Provides the offset of this element's [borderEdge] relative to the
@@ -13529,10 +13512,10 @@
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
 
-  static HtmlDocument _parseDocument;
-  static Range _parseRange;
-  static NodeValidatorBuilder _defaultValidator;
-  static _ValidatingTreeSanitizer _defaultSanitizer;
+  static HtmlDocument? _parseDocument;
+  static Range? _parseRange;
+  static NodeValidatorBuilder? _defaultValidator;
+  static _ValidatingTreeSanitizer? _defaultSanitizer;
 
   /**
    * Create a DocumentFragment from the HTML fragment and ensure that it follows
@@ -13555,7 +13538,7 @@
    * * [NodeTreeSanitizer]
    */
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (treeSanitizer == null) {
       if (validator == null) {
         if (_defaultValidator == null) {
@@ -13564,9 +13547,9 @@
         validator = _defaultValidator;
       }
       if (_defaultSanitizer == null) {
-        _defaultSanitizer = new _ValidatingTreeSanitizer(validator);
+        _defaultSanitizer = new _ValidatingTreeSanitizer(validator!);
       } else {
-        _defaultSanitizer.validator = validator;
+        _defaultSanitizer!.validator = validator!;
       }
       treeSanitizer = _defaultSanitizer;
     } else if (validator != null) {
@@ -13576,45 +13559,46 @@
 
     if (_parseDocument == null) {
       _parseDocument = document.implementation.createHtmlDocument('');
-      _parseRange = _parseDocument.createRange();
+      _parseRange = _parseDocument!.createRange();
 
       // Workaround for Safari bug. Was also previously Chrome bug 229142
       // - URIs are not resolved in new doc.
-      BaseElement base = _parseDocument.createElement('base') as BaseElement;
+      BaseElement base = _parseDocument!.createElement('base') as BaseElement;
       base.href = document.baseUri;
-      _parseDocument.head.append(base);
+      _parseDocument!.head!.append(base);
     }
 
     // TODO(terry): Fixes Chromium 50 change no body after createHtmlDocument()
-    if (_parseDocument.body == null) {
-      _parseDocument.body = _parseDocument.createElement("body");
+    if (_parseDocument!.body == null) {
+      _parseDocument!.body =
+          _parseDocument!.createElement("body") as BodyElement;
     }
 
     var contextElement;
     if (this is BodyElement) {
-      contextElement = _parseDocument.body;
+      contextElement = _parseDocument!.body;
     } else {
-      contextElement = _parseDocument.createElement(tagName);
-      _parseDocument.body.append(contextElement);
+      contextElement = _parseDocument!.createElement(tagName);
+      _parseDocument!.body.append(contextElement);
     }
     var fragment;
     if (Range.supportsCreateContextualFragment &&
         _canBeUsedToCreateContextualFragment) {
-      _parseRange.selectNodeContents(contextElement);
-      fragment = _parseRange.createContextualFragment(html);
+      _parseRange!.selectNodeContents(contextElement);
+      fragment = _parseRange!.createContextualFragment(html);
     } else {
       contextElement._innerHtml = html;
 
-      fragment = _parseDocument.createDocumentFragment();
+      fragment = _parseDocument!.createDocumentFragment();
       while (contextElement.firstChild != null) {
         fragment.append(contextElement.firstChild);
       }
     }
-    if (contextElement != _parseDocument.body) {
+    if (contextElement != _parseDocument!.body) {
       contextElement.remove();
     }
 
-    treeSanitizer.sanitizeTree(fragment);
+    treeSanitizer!.sanitizeTree(fragment);
     // Copy the fragment over to the main document (fix for 14184)
     document.adoptNode(fragment);
 
@@ -13690,7 +13674,7 @@
    * * [NodeTreeSanitizer]
    */
   void setInnerHtml(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     text = null;
     if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
       _innerHtml = html;
@@ -13703,7 +13687,7 @@
   String get innerHtml => _innerHtml;
 
   @JSName('innerText')
-  String innerText;
+  String? innerText;
 
   /**
    * This is an ease-of-use accessor for event streams which should only be
@@ -13774,7 +13758,7 @@
     return result;
   }
 
-  final Element offsetParent;
+  Element get offsetParent => JS("Element", "#.offsetParent", this);
 
   int get offsetHeight => JS<num>('num', '#.offsetHeight', this).round();
 
@@ -14387,20 +14371,6 @@
 
   bool get draggable => JS("bool", "#.draggable", this);
 
-  /**
-   * Indicates whether the element can be dragged and dropped.
-   *
-   * ## Other resources
-   *
-   * * [Drag and drop
-   *   sample](https://github.com/dart-lang/dart-samples/tree/master/html5/web/dnd/basics)
-   *   based on [the tutorial](http://www.html5rocks.com/en/tutorials/dnd/basics/)
-   *   from HTML5Rocks.
-   * * [Drag and drop
-   *   specification](https://html.spec.whatwg.org/multipage/interaction.html#dnd)
-   *   from WHATWG.
-   */
-
   set draggable(bool value) {
     JS("void", "#.draggable = #", this, value);
   }
@@ -14417,16 +14387,6 @@
 
   bool get hidden => JS("bool", "#.hidden", this);
 
-  /**
-   * Indicates whether the element is not relevant to the page's current state.
-   *
-   * ## Other resources
-   *
-   * * [Hidden attribute
-   *   specification](https://html.spec.whatwg.org/multipage/interaction.html#the-hidden-attribute)
-   *   from WHATWG.
-   */
-
   set hidden(bool value) {
     JS("void", "#.hidden = #", this, value);
   }
@@ -14486,17 +14446,6 @@
 
   bool get translate => JS("bool", "#.translate", this);
 
-  /**
-   * Specifies whether this element's text content changes when the page is
-   * localized.
-   *
-   * ## Other resources
-   *
-   * * [The translate
-   *   attribute](https://html.spec.whatwg.org/multipage/dom.html#the-translate-attribute)
-   *   from WHATWG.
-   */
-
   set translate(bool value) {
     JS("void", "#.translate = #", this, value);
   }
@@ -14507,9 +14456,10 @@
 
   void focus() native;
 
-  final AccessibleNode? accessibleNode;
+  AccessibleNode? get accessibleNode =>
+      JS("AccessibleNode", "#.accessibleNode", this);
 
-  final SlotElement? assignedSlot;
+  SlotElement? get assignedSlot => JS("SlotElement", "#.assignedSlot", this);
 
   @JSName('attributes')
   _NamedNodeMap get _attributes => JS("_NamedNodeMap", "#.attributes", this);
@@ -14528,9 +14478,9 @@
 
   int get clientWidth => JS("int", "#.clientWidth", this);
 
-  final String? computedName;
+  String? get computedName => JS("String", "#.computedName", this);
 
-  final String? computedRole;
+  String? get computedRole => JS("String", "#.computedRole", this);
 
   String get id => JS("String", "#.id", this);
 
@@ -14550,7 +14500,7 @@
   String get _localName => JS("String", "#.localName", this);
 
   @JSName('namespaceURI')
-  final String? _namespaceUri;
+  String? get _namespaceUri => JS("String", "#.namespaceURI", this);
 
   // Using property as subclass shadows.
 
@@ -14597,15 +14547,15 @@
   @JSName('attachShadow')
   ShadowRoot _attachShadow_1(shadowRootInitDict) native;
 
-  Element closest(String selectors) native;
+  Element? closest(String selectors) native;
 
   List<Animation> getAnimations() native;
 
   @JSName('getAttribute')
-  String _getAttribute(String name) native;
+  String? _getAttribute(String name) native;
 
   @JSName('getAttributeNS')
-  String _getAttributeNS(String? namespaceURI, String localName) native;
+  String? _getAttributeNS(String? namespaceURI, String localName) native;
 
   List<String> getAttributeNames() native;
 
@@ -14652,7 +14602,7 @@
    *   specification](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html)
    *   from W3C.
    */
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getDestinationInsertionPoints() native;
 
@@ -14714,7 +14664,7 @@
   @JSName('scroll')
   void _scroll_2(options) native;
   @JSName('scroll')
-  void _scroll_3(num x, y) native;
+  void _scroll_3(num? x, y) native;
 
   void scrollBy([options_OR_x, num? y]) {
     if (options_OR_x == null && y == null) {
@@ -14738,7 +14688,7 @@
   @JSName('scrollBy')
   void _scrollBy_2(options) native;
   @JSName('scrollBy')
-  void _scrollBy_3(num x, y) native;
+  void _scrollBy_3(num? x, y) native;
 
   @JSName('scrollIntoView')
   void _scrollIntoView([Object? arg]) native;
@@ -14768,7 +14718,7 @@
   @JSName('scrollTo')
   void _scrollTo_2(options) native;
   @JSName('scrollTo')
-  void _scrollTo_3(num x, y) native;
+  void _scrollTo_3(num? x, y) native;
 
   @JSName('setAttribute')
   void _setAttribute(String name, String value) native;
@@ -14801,9 +14751,11 @@
 
   // From NonDocumentTypeChildNode
 
-  final Element? nextElementSibling;
+  Element? get nextElementSibling =>
+      JS("Element", "#.nextElementSibling", this);
 
-  final Element? previousElementSibling;
+  Element? get previousElementSibling =>
+      JS("Element", "#.previousElementSibling", this);
 
   // From ParentNode
 
@@ -14811,15 +14763,15 @@
   int get _childElementCount => JS("int", "#.childElementCount", this);
 
   @JSName('children')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _children => JS("HtmlCollection", "#.children", this);
 
   @JSName('firstElementChild')
-  final Element? _firstElementChild;
+  Element? get _firstElementChild => JS("Element", "#.firstElementChild", this);
 
   @JSName('lastElementChild')
-  final Element? _lastElementChild;
+  Element? get _lastElementChild => JS("Element", "#.lastElementChild", this);
 
   /**
    * Finds the first descendant element of this element that matches the
@@ -14837,7 +14789,7 @@
    * For details about CSS selector syntax, see the
    * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
    */
-  Element querySelector(String selectors) native;
+  Element? querySelector(String selectors) native;
 
   @JSName('querySelectorAll')
   @Creates('NodeList')
@@ -15151,7 +15103,7 @@
 class _ElementFactoryProvider {
   // Optimization to improve performance until the dart2js compiler inlines this
   // method.
-  static dynamic createElement_tag(String tag, String typeExtension) {
+  static dynamic createElement_tag(String tag, String? typeExtension) {
     // Firefox may return a JS function for some types (Embed, Object).
     if (typeExtension != null) {
       return JS('Element|=Object', 'document.createElement(#, #)', tag,
@@ -15395,7 +15347,7 @@
   int get colno => JS("int", "#.colno", this);
 
   @Creates('Null')
-  Object get error => JS("Object", "#.error", this);
+  Object? get error => JS("Object", "#.error", this);
 
   String get filename => JS("String", "#.filename", this);
 
@@ -15438,7 +15390,7 @@
   }
 
   /** The CSS selector involved with event delegation. */
-  String _selector;
+  String? _selector;
 
   /**
    * A pointer to the element whose CSS selector matched within which an event
@@ -15450,18 +15402,18 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    Element currentTarget = this.currentTarget;
-    Element target = this.target;
+    Element? currentTarget = this.currentTarget as Element?;
+    Element? target = this.target as Element?;
     var matchedTarget;
     do {
-      if (target.matches(_selector)) return target;
+      if (target!.matches(_selector!)) return target;
       target = target.parent;
-    } while (target != null && target != currentTarget.parent);
+    } while (target != null && target != currentTarget!.parent);
     throw new StateError('No selector matched for populating matchedTarget.');
   }
 
   List<EventTarget> get path =>
-      JS('bool', '!!#.composedPath', this) ? composedPath() : [];
+      JS<bool>('bool', '!!#.composedPath', this) ? composedPath() : [];
 
   factory Event._(String type, [Map? eventInitDict]) {
     if (eventInitDict != null) {
@@ -15516,7 +15468,7 @@
   @JSName('currentTarget')
   @Creates('Null')
   @Returns('EventTarget|=Object|Null')
-  final dynamic _get_currentTarget;
+  dynamic get _get_currentTarget => JS("", "#.currentTarget", this);
 
   bool get defaultPrevented => JS("bool", "#.defaultPrevented", this);
 
@@ -15528,7 +15480,7 @@
   @JSName('target')
   @Creates('Node')
   @Returns('EventTarget|=Object')
-  final dynamic _get_target;
+  dynamic get _get_target => JS("", "#.target", this);
 
   num get timeStamp => JS("num", "#.timeStamp", this);
 
@@ -15726,8 +15678,8 @@
    */
   Events get on => new Events(this);
 
-  void addEventListener(String type, EventListener listener,
-      [bool useCapture]) {
+  void addEventListener(String type, EventListener? listener,
+      [bool? useCapture]) {
     // TODO(leafp): This check is avoid a bug in our dispatch code when
     // listener is null.  The browser treats this call as a no-op in this
     // case, so it's fine to short-circuit it, but we should not have to.
@@ -15736,8 +15688,8 @@
     }
   }
 
-  void removeEventListener(String type, EventListener listener,
-      [bool useCapture]) {
+  void removeEventListener(String type, EventListener? listener,
+      [bool? useCapture]) {
     // TODO(leafp): This check is avoid a bug in our dispatch code when
     // listener is null.  The browser treats this call as a no-op in this
     // case, so it's fine to short-circuit it, but we should not have to.
@@ -15799,7 +15751,7 @@
 
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  Object get data => JS("Object", "#.data", this);
+  Object? get data => JS("Object", "#.data", this);
 
   String get lastEventId => JS("String", "#.lastEventId", this);
 
@@ -15809,7 +15761,7 @@
 
   @Creates('Client|ServiceWorker|MessagePort')
   @Returns('Client|ServiceWorker|MessagePort|Null')
-  final Object? source;
+  Object? get source => JS("Object", "#.source", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -15870,7 +15822,7 @@
   static FederatedCredential _create_1(data) =>
       JS('FederatedCredential', 'new FederatedCredential(#)', data);
 
-  final String? protocol;
+  String? get protocol => JS("String", "#.protocol", this);
 
   String get provider => JS("String", "#.provider", this);
 
@@ -15899,11 +15851,12 @@
   static FetchEvent _create_1(type, eventInitDict) =>
       JS('FetchEvent', 'new FetchEvent(#,#)', type, eventInitDict);
 
-  final String? clientId;
+  String? get clientId => JS("String", "#.clientId", this);
 
   bool get isReload => JS("bool", "#.isReload", this);
 
-  Future get preloadResponse => JS("Future", "#.preloadResponse", this);
+  Future get preloadResponse =>
+      promiseToFuture(JS("", "#.preloadResponse", this));
 
   _Request get request => JS("_Request", "#.request", this);
 
@@ -15939,11 +15892,11 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get elements => JS("HtmlCollection", "#.elements", this);
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   String get name => JS("String", "#.name", this);
 
@@ -15994,7 +15947,7 @@
       convertNativeToDart_DateTime(this._get_lastModifiedDate);
   @JSName('lastModifiedDate')
   @Creates('Null')
-  final dynamic _get_lastModifiedDate;
+  dynamic get _get_lastModifiedDate => JS("", "#.lastModifiedDate", this);
 
   String get name => JS("String", "#.name", this);
 
@@ -16111,7 +16064,7 @@
   File elementAt(int index) => this[index];
   // -- end List<File> mixins.
 
-  File item(int index) native;
+  File? item(int index) native;
 }
 // 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
@@ -16119,7 +16072,7 @@
 
 @Native("FileReader")
 class FileReader extends EventTarget {
-  Object get result {
+  Object? get result {
     var res = JS('Null|String|NativeByteBuffer', '#.result', this);
     if (res is ByteBuffer) {
       return new Uint8List.view(res);
@@ -16197,7 +16150,7 @@
 
   static const int LOADING = 1;
 
-  final DomException? error;
+  DomException? get error => JS("DomException", "#.error", this);
 
   int get readyState => JS("int", "#.readyState", this);
 
@@ -16325,7 +16278,7 @@
 
   static const int WRITING = 1;
 
-  final DomException? error;
+  DomException? get error => JS("DomException", "#.error", this);
 
   int get length => JS("int", "#.length", this);
 
@@ -16393,7 +16346,7 @@
       _convertNativeToDart_EventTarget(this._get_relatedTarget);
   @JSName('relatedTarget')
   @Creates('Null')
-  final dynamic _get_relatedTarget;
+  dynamic get _get_relatedTarget => JS("", "#.relatedTarget", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -16436,7 +16389,8 @@
     JS("void", "#.featureSettings = #", this, value);
   }
 
-  Future get loaded => JS("Future", "#.loaded", this);
+  Future<FontFace> get loaded =>
+      promiseToFuture<FontFace>(JS("", "#.loaded", this));
 
   String get status => JS("String", "#.status", this);
 
@@ -16614,7 +16568,7 @@
 
   void delete(String name) native;
 
-  Object get(String name) native;
+  Object? get(String name) native;
 
   List<Object> getAll(String name) native;
 
@@ -16701,7 +16655,7 @@
     JS("void", "#.target = #", this, value);
   }
 
-  Object __getter__(String name) native;
+  Object? __getter__(String name) native;
 
   bool checkValidity() native;
 
@@ -16709,7 +16663,7 @@
 
   bool reportValidity() native;
 
-  void requestAutocomplete(Map details) {
+  void requestAutocomplete(Map? details) {
     var details_1 = convertDartToNative_Dictionary(details);
     _requestAutocomplete_1(details_1);
     return;
@@ -16766,7 +16720,7 @@
 
   String get mapping => JS("String", "#.mapping", this);
 
-  final GamepadPose? pose;
+  GamepadPose? get pose => JS("GamepadPose", "#.pose", this);
 
   int get timestamp => JS("int", "#.timestamp", this);
 }
@@ -16823,21 +16777,25 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final Float32List? angularAcceleration;
+  Float32List? get angularAcceleration =>
+      JS("Float32List", "#.angularAcceleration", this);
 
-  final Float32List? angularVelocity;
+  Float32List? get angularVelocity =>
+      JS("Float32List", "#.angularVelocity", this);
 
   bool get hasOrientation => JS("bool", "#.hasOrientation", this);
 
   bool get hasPosition => JS("bool", "#.hasPosition", this);
 
-  final Float32List? linearAcceleration;
+  Float32List? get linearAcceleration =>
+      JS("Float32List", "#.linearAcceleration", this);
 
-  final Float32List? linearVelocity;
+  Float32List? get linearVelocity =>
+      JS("Float32List", "#.linearVelocity", this);
 
-  final Float32List? orientation;
+  Float32List? get orientation => JS("Float32List", "#.orientation", this);
 
-  final Float32List? position;
+  Float32List? get position => JS("Float32List", "#.position", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -16884,25 +16842,22 @@
       options['maximumAge'] = maximumAge.inMilliseconds;
     }
 
-    int watchId;
-    // TODO(jacobr): it seems like a bug that we have to specifiy the static
-    // type here for controller.stream to have the right type.
-    // dartbug.com/26278
-    StreamController<Geoposition> controller;
-    controller = new StreamController<Geoposition>(
-        sync: true,
-        onListen: () {
-          assert(watchId == null);
-          watchId = _watchPosition((position) {
-            controller.add(_ensurePosition(position));
-          }, (error) {
-            controller.addError(error);
-          }, options);
-        },
-        onCancel: () {
-          assert(watchId != null);
-          _clearWatch(watchId);
-        });
+    int? watchId;
+    StreamController<Geoposition> controller =
+        new StreamController<Geoposition>(
+            sync: true,
+            onCancel: () {
+              assert(watchId != null);
+              _clearWatch(watchId!);
+            });
+    controller.onListen = () {
+      assert(watchId == null);
+      watchId = _watchPosition((position) {
+        controller.add(_ensurePosition(position));
+      }, (error) {
+        controller.addError(error);
+      }, options);
+    };
 
     return controller.stream;
   }
@@ -16945,10 +16900,10 @@
 
   @JSName('getCurrentPosition')
   void _getCurrentPosition_1(
-      successCallback, _PositionErrorCallback errorCallback, options) native;
+      successCallback, _PositionErrorCallback? errorCallback, options) native;
   @JSName('getCurrentPosition')
   void _getCurrentPosition_2(
-      successCallback, _PositionErrorCallback errorCallback) native;
+      successCallback, _PositionErrorCallback? errorCallback) native;
   @JSName('getCurrentPosition')
   void _getCurrentPosition_3(successCallback) native;
 
@@ -16969,9 +16924,9 @@
 
   @JSName('watchPosition')
   int _watchPosition_1(
-      successCallback, _PositionErrorCallback errorCallback, options) native;
+      successCallback, _PositionErrorCallback? errorCallback, options) native;
   @JSName('watchPosition')
-  int _watchPosition_2(successCallback, _PositionErrorCallback errorCallback)
+  int _watchPosition_2(successCallback, _PositionErrorCallback? errorCallback)
       native;
   @JSName('watchPosition')
   int _watchPosition_3(successCallback) native;
@@ -17012,11 +16967,11 @@
 // convince the scripts to make our instance methods abstract, and the bodies that
 // get generated require `this` to be an EventTarget.
 abstract class GlobalEventHandlers implements EventTarget {
-  void addEventListener(String type, dynamic listener(Event event),
-      [bool useCapture]);
+  void addEventListener(String type, dynamic listener(Event event)?,
+      [bool? useCapture]);
   bool dispatchEvent(Event event);
-  void removeEventListener(String type, dynamic listener(Event event),
-      [bool useCapture]);
+  void removeEventListener(String type, dynamic listener(Event event)?,
+      [bool? useCapture]);
   Events get on;
 
   // To suppress missing implicit constructor warnings.
@@ -17333,11 +17288,11 @@
       JS('Gyroscope', 'new Gyroscope(#)', sensorOptions);
   static Gyroscope _create_2() => JS('Gyroscope', 'new Gyroscope()');
 
-  final num x;
+  num? get x => JS("num", "#.x", this);
 
-  final num y;
+  num? get y => JS("num", "#.y", this);
 
-  final num z;
+  num? get z => JS("num", "#.z", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -17386,8 +17341,8 @@
   factory HashChangeEvent(String type,
       {bool canBubble: true,
       bool cancelable: true,
-      String oldUrl,
-      String newUrl}) {
+      String? oldUrl,
+      String? newUrl}) {
     var options = {
       'canBubble': canBubble,
       'cancelable': cancelable,
@@ -17549,7 +17504,7 @@
   @JSName('state')
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _get_state;
+  dynamic get _get_state => JS("", "#.state", this);
 
   void back() native;
 
@@ -17649,9 +17604,9 @@
   Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
-  Node item(int index) native;
+  Node? item(int? index) native;
 
-  Object namedItem(String name) native;
+  Object? namedItem(String name) native;
 }
 // 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
@@ -17674,20 +17629,20 @@
     return _caretRangeFromPoint(x, y);
   }
 
-  Element elementFromPoint(int x, int y) {
+  Element? elementFromPoint(int x, int y) {
     return _elementFromPoint(x, y);
   }
 
-  HeadElement get head => _head;
+  HeadElement? get head => _head;
 
   String get lastModified => _lastModified;
 
-  String get preferredStylesheetSet => _preferredStylesheetSet;
+  String? get preferredStylesheetSet => _preferredStylesheetSet;
 
   String get referrer => _referrer;
 
-  String get selectedStylesheetSet => _selectedStylesheetSet;
-  set selectedStylesheetSet(String value) {
+  String? get selectedStylesheetSet => _selectedStylesheetSet;
+  set selectedStylesheetSet(String? value) {
     _selectedStylesheetSet = value;
   }
 
@@ -17758,13 +17713,13 @@
    * `<input is="x-bar"></input>`
    *
    */
-  Function registerElement2(String tag, [Map options]) {
+  Function registerElement2(String tag, [Map? options]) {
     return _registerCustomElement(JS('', 'window'), this, tag, options);
   }
 
   /** *Deprecated*: use [registerElement] instead. */
   @deprecated
-  void register(String tag, Type customElementClass, {String extendsTag}) {
+  void register(String tag, Type customElementClass, {String? extendsTag}) {
     return registerElement(tag, customElementClass, extendsTag: extendsTag);
   }
 
@@ -17808,7 +17763,7 @@
   ///
   /// If the type is not a direct subclass of HtmlElement then the extendsTag
   /// parameter must be provided.
-  ElementUpgrader createElementUpgrader(Type type, {String extendsTag}) {
+  ElementUpgrader createElementUpgrader(Type type, {String? extendsTag}) {
     return new _JSElementUpgrader(this, type, extendsTag);
   }
 }
@@ -17823,9 +17778,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Node item(int index) native;
-
-  Object namedItem(String name) native;
+  Object? namedItem(String name) native;
 }
 // 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
@@ -17935,7 +17888,7 @@
   }
 
   @JSName('item')
-  Element _item(int index) native;
+  Element? _item(int index) native;
 }
 // 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
@@ -18042,10 +17995,10 @@
    * * [request]
    */
   static Future<HttpRequest> postFormData(String url, Map<String, String> data,
-      {bool withCredentials,
-      String responseType,
-      Map<String, String> requestHeaders,
-      void onProgress(ProgressEvent e)}) {
+      {bool? withCredentials,
+      String? responseType,
+      Map<String, String>? requestHeaders,
+      void onProgress(ProgressEvent e)?}) {
     var parts = [];
     data.forEach((key, value) {
       parts.add('${Uri.encodeQueryComponent(key)}='
@@ -18123,13 +18076,13 @@
    * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
    */
   static Future<HttpRequest> request(String url,
-      {String method,
-      bool withCredentials,
-      String responseType,
-      String mimeType,
-      Map<String, String> requestHeaders,
+      {String? method,
+      bool? withCredentials,
+      String? responseType,
+      String? mimeType,
+      Map<String, String>? requestHeaders,
       sendData,
-      void onProgress(ProgressEvent e)}) {
+      void onProgress(ProgressEvent e)?}) {
     var completer = new Completer<HttpRequest>();
 
     var xhr = new HttpRequest();
@@ -18233,7 +18186,7 @@
    * cross-origin support is not required then [request] should be used instead.
    */
   static Future<String> requestCrossOrigin(String url,
-      {String method, String sendData}) {
+      {String? method, String? sendData}) {
     if (supportsCrossOrigin) {
       return request(url, method: method, sendData: sendData).then((xhr) {
         return xhr.responseText;
@@ -18251,7 +18204,7 @@
         xhr,
         convertDartClosureToJS((e) {
           var response = JS('String', '#.responseText', xhr);
-          completer.complete(response);
+          completer.complete(response as FutureOr<String>?);
         }, 1));
     JS(
         '',
@@ -18329,7 +18282,7 @@
    * finer-grained control is needed.
    */
   void open(String method, String url,
-      {bool async, String user, String password}) native;
+      {bool? async, String? user, String? password}) native;
 
   // To suppress missing implicit constructor warnings.
   factory HttpRequest._() {
@@ -18437,7 +18390,7 @@
   @SupportedBrowser(SupportedBrowser.SAFARI)
   @Creates(
       'NativeByteBuffer|Blob|Document|=Object|JSExtendableArray|String|num')
-  final dynamic _get_response;
+  dynamic get _get_response => JS("", "#.response", this);
 
   /**
    * The response in String form or empty String on failure.
@@ -18459,18 +18412,6 @@
 
   String get responseType => JS("String", "#.responseType", this);
 
-  /**
-   * [String] telling the server the desired response format.
-   *
-   * Default is `String`.
-   * Other options are one of 'arraybuffer', 'blob', 'document', 'json',
-   * 'text'. Some newer browsers will throw NS_ERROR_DOM_INVALID_ACCESS_ERR if
-   * `responseType` is set while performing a synchronous request.
-   *
-   * See also: [MDN
-   * responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype)
-   */
-
   set responseType(String value) {
     JS("void", "#.responseType = #", this, value);
   }
@@ -18479,6 +18420,7 @@
   String get responseUrl => JS("String", "#.responseURL", this);
 
   @JSName('responseXML')
+
   /**
    * The request response, or null on failure.
    *
@@ -18486,7 +18428,8 @@
    * `text/xml` stream, unless responseType = 'document' and the request is
    * synchronous.
    */
-  final Document? responseXml;
+
+  Document? get responseXml => JS("Document", "#.responseXML", this);
 
   /**
    * The HTTP result code from the request (200, 404, etc).
@@ -18520,22 +18463,6 @@
 
   int get timeout => JS("int", "#.timeout", this);
 
-  /**
-   * Length of time in milliseconds before a request is automatically
-   * terminated.
-   *
-   * When the time has passed, a [TimeoutEvent] is dispatched.
-   *
-   * If [timeout] is set to 0, then the request will not time out.
-   *
-   * ## Other resources
-   *
-   * * [XMLHttpRequest.timeout](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-timeout)
-   *   from MDN.
-   * * [The timeout attribute](http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute)
-   *   from W3C.
-   */
-
   set timeout(int value) {
     JS("void", "#.timeout = #", this, value);
   }
@@ -18556,13 +18483,6 @@
 
   bool get withCredentials => JS("bool", "#.withCredentials", this);
 
-  /**
-   * True if cross-site requests should use credentials such as cookies
-   * or authorization headers; false otherwise.
-   *
-   * This value is ignored for same-site requests.
-   */
-
   set withCredentials(bool value) {
     JS("void", "#.withCredentials = #", this, value);
   }
@@ -18598,7 +18518,7 @@
    * for a list of common response headers.
    */
   @Unstable()
-  String getResponseHeader(String name) native;
+  String? getResponseHeader(String name) native;
 
   /**
    * Specify a particular MIME type (such as `text/xml`) desired for the
@@ -18813,7 +18733,7 @@
   @JSName('contentWindow')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_contentWindow;
+  dynamic get _get_contentWindow => JS("", "#.contentWindow", this);
 
   String get csp => JS("String", "#.csp", this);
 
@@ -18936,7 +18856,7 @@
       promiseToFuture<PhotoCapabilities>(
           JS("", "#.getPhotoCapabilities()", this));
 
-  Future<Map<String, dynamic>> getPhotoSettings() =>
+  Future<Map<String, dynamic>?> getPhotoSettings() =>
       promiseToFutureAsMap(JS("", "#.getPhotoSettings()", this));
 
   Future<ImageBitmap> grabFrame() =>
@@ -19151,7 +19071,7 @@
         ResetButtonInputElement,
         ButtonInputElement {
   factory InputElement({String? type}) {
-    InputElement e = document.createElement("input");
+    InputElement e = document.createElement("input") as InputElement;
     if (type != null) {
       try {
         // IE throws an exception for unknown types.
@@ -19242,7 +19162,7 @@
   @Creates('FileList')
   List<File>? files;
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   String get formAction => JS("String", "#.formAction", this);
 
@@ -19292,11 +19212,11 @@
     JS("void", "#.indeterminate = #", this, value);
   }
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
-  final HtmlElement? list;
+  HtmlElement? get list => JS("HtmlElement", "#.list", this);
 
   String get max => JS("String", "#.max", this);
 
@@ -19402,13 +19322,13 @@
       convertNativeToDart_DateTime(this._get_valueAsDate);
   @JSName('valueAsDate')
   @Creates('Null')
-  final dynamic _get_valueAsDate;
+  dynamic get _get_valueAsDate => JS("", "#.valueAsDate", this);
 
-  set valueAsDate(DateTime value) {
-    this._set_valueAsDate = convertDartToNative_DateTime(value);
+  set valueAsDate(DateTime? value) {
+    this._set_valueAsDate = convertDartToNative_DateTime(value!);
   }
 
-  set _set_valueAsDate(/*dynamic?*/ value) {
+  set _set_valueAsDate(/*dynamic*/ value) {
     JS("void", "#.valueAsDate = #", this, value);
   }
 
@@ -19429,8 +19349,6 @@
   bool get directory => JS("bool", "#.webkitdirectory", this);
 
   @JSName('webkitdirectory')
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
   set directory(bool value) {
     JS("void", "#.webkitdirectory = #", this, value);
   }
@@ -19469,24 +19387,32 @@
  * Exposes the functionality common between all InputElement types.
  */
 abstract class InputElementBase implements Element {
-  bool autofocus;
+  // These fields here and below are overridden by generated code and therefore
+  // can't be nullable. Opted to translate these fields to getters/setters.
+  bool get autofocus;
+  set autofocus(bool value);
 
-  bool disabled;
+  bool get disabled;
+  set disabled(bool value);
 
-  bool incremental;
+  bool get incremental;
+  set incremental(bool value);
 
-  bool indeterminate;
+  bool get indeterminate;
+  set indeterminate(bool value);
+
+  String get name;
+  set name(String value);
+
+  String get value;
+  set value(String value);
 
   List<Node> get labels;
 
-  String name;
-
   String get validationMessage;
 
   ValidityState get validity;
 
-  String value;
-
   bool get willValidate;
 
   bool checkValidity();
@@ -19505,29 +19431,36 @@
  * Base interface for all inputs which involve text editing.
  */
 abstract class TextInputElementBase implements InputElementBase {
-  String autocomplete;
+  String get autocomplete;
+  set autocomplete(String value);
 
-  int maxLength;
+  int get maxLength;
+  set maxLength(int value);
 
-  String pattern;
+  String get pattern;
+  set pattern(String value);
 
-  String placeholder;
+  String get placeholder;
+  set placeholder(String value);
 
-  bool readOnly;
+  bool get readOnly;
+  set readOnly(bool value);
 
-  bool required;
+  bool get required;
+  set required(bool value);
 
-  int size;
+  int get size;
+  set size(int value);
 
   void select();
 
-  String selectionDirection;
+  String? selectionDirection;
 
-  int selectionEnd;
+  int? selectionEnd;
 
-  int selectionStart;
+  int? selectionStart;
 
-  void setSelectionRange(int start, int end, [String direction]);
+  void setSelectionRange(int start, int end, [String? direction]);
 }
 
 /**
@@ -19658,17 +19591,21 @@
 abstract class RangeInputElementBase implements InputElementBase {
   Element? get list;
 
-  String max;
+  String get max;
+  set max(String value);
 
-  String min;
+  String get min;
+  set min(String value);
 
-  String step;
+  String get step;
+  set step(String value);
 
-  num valueAsNumber;
+  num get valueAsNumber;
+  set valueAsNumber(num value);
 
-  void stepDown([int n]);
+  void stepDown([int? n]);
 
-  void stepUp([int n]);
+  void stepUp([int? n]);
 }
 
 /**
@@ -19859,7 +19796,7 @@
 
   bool required;
 
-  List<File> files;
+  List<File>? files;
 }
 
 /**
@@ -19979,7 +19916,7 @@
   static IntersectionObserver _create_2(callback) =>
       JS('IntersectionObserver', 'new IntersectionObserver(#)', callback);
 
-  final Element? root;
+  Element? get root => JS("Element", "#.root", this);
 
   String get rootMargin => JS("String", "#.rootMargin", this);
 
@@ -20022,7 +19959,8 @@
 
   bool get isIntersecting => JS("bool", "#.isIntersecting", this);
 
-  final DomRectReadOnly? rootBounds;
+  DomRectReadOnly? get rootBounds =>
+      JS("DomRectReadOnly", "#.rootBounds", this);
 
   Element get target => JS("Element", "#.target", this);
 
@@ -20071,11 +20009,11 @@
    * Event [KeyEvent].
    */
   factory KeyboardEvent(String type,
-      {Window view,
+      {Window? view,
       bool canBubble: true,
       bool cancelable: true,
-      int location,
-      int keyLocation, // Legacy alias for location
+      int? location,
+      int? keyLocation, // Legacy alias for location
       bool ctrlKey: false,
       bool altKey: false,
       bool shiftKey: false,
@@ -20084,7 +20022,7 @@
       view = window;
     }
     location ??= keyLocation ?? 1;
-    KeyboardEvent e = document._createEvent("KeyboardEvent");
+    KeyboardEvent e = document._createEvent("KeyboardEvent") as KeyboardEvent;
     e._initKeyboardEvent(type, canBubble, cancelable, view, "", location,
         ctrlKey, altKey, shiftKey, metaKey);
     return e;
@@ -20094,9 +20032,9 @@
       String type,
       bool canBubble,
       bool cancelable,
-      Window view,
+      Window? view,
       String keyIdentifier,
-      int location,
+      int? location,
       bool ctrlKey,
       bool altKey,
       bool shiftKey,
@@ -20283,9 +20221,9 @@
    */
   LabelElement.created() : super.created();
 
-  final HtmlElement? control;
+  HtmlElement? get control => JS("HtmlElement", "#.control", this);
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   String get htmlFor => JS("String", "#.htmlFor", this);
 
@@ -20316,7 +20254,7 @@
    */
   LegendElement.created() : super.created();
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -20392,7 +20330,7 @@
     JS("void", "#.hreflang = #", this, value);
   }
 
-  final Document? import;
+  Document? get import => JS("Document", "#.import", this);
 
   String get integrity => JS("String", "#.integrity", this);
 
@@ -20426,7 +20364,7 @@
     JS("void", "#.scope = #", this, value);
   }
 
-  final StyleSheet? sheet;
+  StyleSheet? get sheet => JS("StyleSheet", "#.sheet", this);
 
   DomTokenList get sizes => JS("DomTokenList", "#.sizes", this);
 
@@ -20452,7 +20390,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  @Returns('DomStringList|Null')
+  @Returns('DomStringList')
   @Creates('DomStringList')
   List<String> get ancestorOrigins =>
       JS("DomStringList", "#.ancestorOrigins", this);
@@ -20515,7 +20453,7 @@
 
   void reload() native;
 
-  void replace(String url) native;
+  void replace(String? url) native;
 
   String get origin {
     if (JS('bool', '("origin" in #)', this)) {
@@ -20548,11 +20486,11 @@
       JS('Magnetometer', 'new Magnetometer(#)', sensorOptions);
   static Magnetometer _create_2() => JS('Magnetometer', 'new Magnetometer()');
 
-  final num x;
+  num? get x => JS("num", "#.x", this);
 
-  final num y;
+  num? get y => JS("num", "#.y", this);
 
-  final num z;
+  num? get z => JS("num", "#.z", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -20577,7 +20515,7 @@
    */
   MapElement.created() : super.created();
 
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get areas => JS("HtmlCollection", "#.areas", this);
 
@@ -20661,7 +20599,7 @@
       promiseToFuture<List<dynamic>>(JS("", "#.enumerateDevices()", this));
 
   Map getSupportedConstraints() {
-    return convertNativeToDart_Dictionary(_getSupportedConstraints_1());
+    return convertNativeToDart_Dictionary(_getSupportedConstraints_1())!;
   }
 
   @JSName('getSupportedConstraints')
@@ -20753,7 +20691,7 @@
 
   bool get ended => JS("bool", "#.ended", this);
 
-  final MediaError? error;
+  MediaError? get error => JS("MediaError", "#.error", this);
 
   bool get loop => JS("bool", "#.loop", this);
 
@@ -20834,7 +20772,7 @@
   TextTrack addTextTrack(String kind, [String? label, String? language]) native;
 
   @Unstable()
-  String canPlayType(String type, [String? keySystem]) native;
+  String canPlayType(String? type, [String? keySystem]) native;
 
   MediaStream captureStream() native;
 
@@ -20876,7 +20814,7 @@
   static MediaEncryptedEvent _create_2(type) =>
       JS('MediaEncryptedEvent', 'new MediaEncryptedEvent(#)', type);
 
-  final ByteBuffer? initData;
+  ByteBuffer? get initData => JS("ByteBuffer", "#.initData", this);
 
   String get initDataType => JS("String", "#.initDataType", this);
 }
@@ -20943,7 +20881,7 @@
   static const EventStreamProvider<MessageEvent> messageEvent =
       const EventStreamProvider<MessageEvent>('message');
 
-  Future get closed => JS("Future", "#.closed", this);
+  Future<void> get closed => promiseToFuture<void>(JS("", "#.closed", this));
 
   num get expiration => JS("num", "#.expiration", this);
 
@@ -20981,7 +20919,7 @@
 
   int get size => JS("int", "#.size", this);
 
-  Object get(/*BufferSource*/ keyId) native;
+  Object? get(/*BufferSource*/ keyId) native;
 
   bool has(/*BufferSource*/ keyId) native;
 }
@@ -21002,7 +20940,7 @@
       promiseToFuture(JS("", "#.createMediaKeys()", this));
 
   Map getConfiguration() {
-    return convertNativeToDart_Dictionary(_getConfiguration_1());
+    return convertNativeToDart_Dictionary(_getConfiguration_1())!;
   }
 
   @JSName('getConfiguration')
@@ -21069,7 +21007,7 @@
 
   void deleteMedium(String medium) native;
 
-  String item(int index) native;
+  String? item(int index) native;
 }
 // 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
@@ -21381,7 +21319,7 @@
   @Returns('JSExtendableArray')
   List<MediaStreamTrack> getAudioTracks() native;
 
-  MediaStreamTrack getTrackById(String trackId) native;
+  MediaStreamTrack? getTrackById(String trackId) native;
 
   List<MediaStreamTrack> getTracks() native;
 
@@ -21440,7 +21378,7 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Device.isEventTypeSupported('MediaStreamEvent');
 
-  final MediaStream? stream;
+  MediaStream? get stream => JS("MediaStream", "#.stream", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -21515,21 +21453,21 @@
   MediaStreamTrack clone() native;
 
   Map getCapabilities() {
-    return convertNativeToDart_Dictionary(_getCapabilities_1());
+    return convertNativeToDart_Dictionary(_getCapabilities_1())!;
   }
 
   @JSName('getCapabilities')
   _getCapabilities_1() native;
 
   Map getConstraints() {
-    return convertNativeToDart_Dictionary(_getConstraints_1());
+    return convertNativeToDart_Dictionary(_getConstraints_1())!;
   }
 
   @JSName('getConstraints')
   _getConstraints_1() native;
 
   Map getSettings() {
-    return convertNativeToDart_Dictionary(_getSettings_1());
+    return convertNativeToDart_Dictionary(_getSettings_1())!;
   }
 
   @JSName('getSettings')
@@ -21664,10 +21602,10 @@
   factory MessageEvent(String type,
       {bool canBubble: false,
       bool cancelable: false,
-      Object data,
-      String origin,
-      String lastEventId,
-      Window source,
+      Object? data,
+      String? origin,
+      String? lastEventId,
+      Window? source,
       List<MessagePort> messagePorts: const []}) {
     if (source == null) {
       source = window;
@@ -21687,7 +21625,7 @@
           source,
           messagePorts);
     }
-    MessageEvent event = document._createEvent("MessageEvent");
+    MessageEvent event = document._createEvent("MessageEvent") as MessageEvent;
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
@@ -21728,19 +21666,19 @@
   @JSName('source')
   @Creates('Null')
   @Returns('EventTarget|=Object')
-  final dynamic _get_source;
+  dynamic get _get_source => JS("", "#.source", this);
 
   String get suborigin => JS("String", "#.suborigin", this);
 
   void _initMessageEvent(
-      String typeArg,
-      bool canBubbleArg,
-      bool cancelableArg,
-      Object dataArg,
-      String originArg,
-      String lastEventIdArg,
-      EventTarget sourceArg,
-      List<MessagePort> portsArg) {
+      String? typeArg,
+      bool? canBubbleArg,
+      bool? cancelableArg,
+      Object? dataArg,
+      String? originArg,
+      String? lastEventIdArg,
+      EventTarget? sourceArg,
+      List<MessagePort>? portsArg) {
     var sourceArg_1 = _convertDartToNative_EventTarget(sourceArg);
     _initMessageEvent_1(typeArg, canBubbleArg, cancelableArg, dataArg,
         originArg, lastEventIdArg, sourceArg_1, portsArg);
@@ -21749,7 +21687,7 @@
 
   @JSName('initMessageEvent')
   void _initMessageEvent_1(typeArg, canBubbleArg, cancelableArg, dataArg,
-      originArg, lastEventIdArg, sourceArg, List<MessagePort> portsArg) native;
+      originArg, lastEventIdArg, sourceArg, List<MessagePort>? portsArg) native;
 }
 // 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
@@ -21760,8 +21698,8 @@
 @Unstable()
 @Native("MessagePort")
 class MessagePort extends EventTarget {
-  void addEventListener(String type, EventListener listener,
-      [bool useCapture]) {
+  void addEventListener(String type, EventListener? listener,
+      [bool? useCapture]) {
     // Messages posted to ports are initially paused, allowing listeners to be
     // setup, start() needs to be explicitly invoked to begin handling messages.
     if (type == 'message') {
@@ -21866,7 +21804,7 @@
       convertNativeToDart_DateTime(this._get_modificationTime);
   @JSName('modificationTime')
   @Creates('Null')
-  final dynamic _get_modificationTime;
+  dynamic get _get_modificationTime => JS("", "#.modificationTime", this);
 
   int get size => JS("int", "#.size", this);
 }
@@ -21910,7 +21848,7 @@
   }
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -22024,7 +21962,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Map _getItem(String key) =>
+  Map? _getItem(String key) =>
       convertNativeToDart_Dictionary(JS('', '#.get(#)', this, key));
 
   void addAll(Map<String, dynamic> other) {
@@ -22035,7 +21973,7 @@
 
   bool containsKey(dynamic key) => _getItem(key) != null;
 
-  Map operator [](dynamic key) => _getItem(key);
+  Map? operator [](dynamic key) => _getItem(key);
 
   void forEach(void f(String key, dynamic value)) {
     var entries = JS('', '#.entries()', this);
@@ -22130,7 +22068,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Map _getItem(String key) =>
+  Map? _getItem(String key) =>
       convertNativeToDart_Dictionary(JS('', '#.get(#)', this, key));
 
   void addAll(Map<String, dynamic> other) {
@@ -22141,7 +22079,7 @@
 
   bool containsKey(dynamic key) => _getItem(key) != null;
 
-  Map operator [](dynamic key) => _getItem(key);
+  Map? operator [](dynamic key) => _getItem(key);
 
   void forEach(void f(String key, dynamic value)) {
     var entries = JS('', '#.entries()', this);
@@ -22293,9 +22231,9 @@
   MimeType elementAt(int index) => this[index];
   // -- end List<MimeType> mixins.
 
-  MimeType item(int index) native;
+  MimeType? item(int index) native;
 
-  MimeType namedItem(String name) native;
+  MimeType? namedItem(String name) native;
 }
 // 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
@@ -22341,7 +22279,7 @@
 @Native("MouseEvent,DragEvent")
 class MouseEvent extends UIEvent {
   factory MouseEvent(String type,
-      {Window view,
+      {Window? view,
       int detail: 0,
       int screenX: 0,
       int screenY: 0,
@@ -22354,11 +22292,11 @@
       bool altKey: false,
       bool shiftKey: false,
       bool metaKey: false,
-      EventTarget relatedTarget}) {
+      EventTarget? relatedTarget}) {
     if (view == null) {
       view = window;
     }
-    MouseEvent event = document._createEvent('MouseEvent');
+    MouseEvent event = document._createEvent('MouseEvent') as MouseEvent;
     event._initMouseEvent(
         type,
         canBubble,
@@ -22434,14 +22372,14 @@
   @JSName('pageY')
   num get _pageY => JS("num", "#.pageY", this);
 
-  final String? region;
+  String? get region => JS("String", "#.region", this);
 
   EventTarget? get relatedTarget =>
       _convertNativeToDart_EventTarget(this._get_relatedTarget);
   @JSName('relatedTarget')
   @Creates('Node')
   @Returns('EventTarget|=Object|Null')
-  final dynamic _get_relatedTarget;
+  dynamic get _get_relatedTarget => JS("", "#.relatedTarget", this);
 
   @JSName('screenX')
   num get _screenX => JS("num", "#.screenX", this);
@@ -22464,20 +22402,20 @@
   bool getModifierState(String keyArg) native;
 
   void _initMouseEvent(
-      String type,
-      bool bubbles,
-      bool cancelable,
+      String? type,
+      bool? bubbles,
+      bool? cancelable,
       Window? view,
-      int detail,
-      int screenX,
-      int screenY,
-      int clientX,
-      int clientY,
-      bool ctrlKey,
-      bool altKey,
-      bool shiftKey,
-      bool metaKey,
-      int button,
+      int? detail,
+      int? screenX,
+      int? screenY,
+      int? clientX,
+      int? clientY,
+      bool? ctrlKey,
+      bool? altKey,
+      bool? shiftKey,
+      bool? metaKey,
+      int? button,
       EventTarget? relatedTarget) {
     var relatedTarget_1 = _convertDartToNative_EventTarget(relatedTarget);
     _initMouseEvent_1(
@@ -22534,13 +22472,13 @@
     if (JS('bool', '!!#.offsetX', this)) {
       var x = JS('int', '#.offsetX', this);
       var y = JS('int', '#.offsetY', this);
-      return new Point(x, y);
+      return new Point(x as num, y as num);
     } else {
       // Firefox does not support offsetX.
       if (!(this.target is Element)) {
         throw new UnsupportedError('offsetX is only supported on elements');
       }
-      Element target = this.target;
+      Element target = this.target as Element;
       var point = (this.client - target.getBoundingClientRect().topLeft);
       return new Point(point.x.toInt(), point.y.toInt());
     }
@@ -22589,17 +22527,17 @@
 
   String get prevValue => JS("String", "#.prevValue", this);
 
-  final Node? relatedNode;
+  Node? get relatedNode => JS("Node", "#.relatedNode", this);
 
   void initMutationEvent(
-      String type,
-      bool bubbles,
-      bool cancelable,
+      String? type,
+      bool? bubbles,
+      bool? cancelable,
       Node? relatedNode,
-      String prevValue,
-      String newValue,
-      String attrName,
-      int attrChange) native;
+      String? prevValue,
+      String? newValue,
+      String? attrName,
+      int? attrChange) native;
 }
 // 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
@@ -22649,12 +22587,12 @@
    * * If characterDataOldValue is true then characterData must be true.
    */
   void observe(Node target,
-      {bool childList,
-      bool attributes,
-      bool characterData,
-      bool subtree,
-      bool attributeOldValue,
-      bool characterDataOldValue,
+      {bool? childList,
+      bool? attributes,
+      bool? characterData,
+      bool? subtree,
+      bool? attributeOldValue,
+      bool? characterDataOldValue,
       List<String>? attributeFilter}) {
     // Parse options into map of known type.
     var parsedOptions = _createDict();
@@ -22720,21 +22658,21 @@
     throw new UnsupportedError("Not supported");
   }
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get addedNodes => JS("NodeList", "#.addedNodes", this);
 
-  final String? attributeName;
+  String? get attributeName => JS("String", "#.attributeName", this);
 
-  final String? attributeNamespace;
+  String? get attributeNamespace => JS("String", "#.attributeNamespace", this);
 
-  final Node? nextSibling;
+  Node? get nextSibling => JS("Node", "#.nextSibling", this);
 
-  final String? oldValue;
+  String? get oldValue => JS("String", "#.oldValue", this);
 
-  final Node? previousSibling;
+  Node? get previousSibling => JS("Node", "#.previousSibling", this);
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get removedNodes => JS("NodeList", "#.removedNodes", this);
 
@@ -22757,7 +22695,7 @@
 
   Future enable() => promiseToFuture(JS("", "#.enable()", this));
 
-  Future<Map<String, dynamic>> getState() =>
+  Future<Map<String, dynamic>?> getState() =>
       promiseToFutureAsMap(JS("", "#.getState()", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -22873,7 +22811,7 @@
 
   num get deviceMemory => JS("num", "#.deviceMemory", this);
 
-  final String? doNotTrack;
+  String? get doNotTrack => JS("String", "#.doNotTrack", this);
 
   @Unstable()
   Geolocation get geolocation => JS("Geolocation", "#.geolocation", this);
@@ -22928,7 +22866,7 @@
   Future getBattery() => promiseToFuture(JS("", "#.getBattery()", this));
 
   @JSName('getGamepads')
-  @Returns('_GamepadList|Null')
+  @Returns('_GamepadList')
   @Creates('_GamepadList')
   List<Gamepad> _getGamepads() native;
 
@@ -23065,19 +23003,19 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final String appCodeName;
+  String get appCodeName => JS("String", "#.appCodeName", this);
 
-  final String appName;
+  String get appName => JS("String", "#.appName", this);
 
-  final String appVersion;
+  String get appVersion => JS("String", "#.appVersion", this);
 
-  final bool dartEnabled;
+  bool get dartEnabled => JS("bool", "#.dartEnabled", this);
 
-  final String platform;
+  String get platform => JS("String", "#.platform", this);
 
-  final String product;
+  String get product => JS("String", "#.product", this);
 
-  final String userAgent;
+  String get userAgent => JS("String", "#.userAgent", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -23089,9 +23027,9 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final String language;
+  String get language => JS("String", "#.language", this);
 
-  final List<String> languages;
+  List<String> get languages => JS("List<String>", "#.languages", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -23103,7 +23041,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final bool onLine;
+  bool get onLine => JS("bool", "#.onLine", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -23205,7 +23143,7 @@
       if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
         for (var i = 0, len = otherList.length; i < len; ++i) {
-          _this.append(otherList._this.firstChild);
+          _this.append(otherList._this.firstChild!);
         }
       }
       return;
@@ -23267,9 +23205,9 @@
     // This implementation of removeWhere/retainWhere is more efficient
     // than the default in ListBase. Child nodes can be removed in constant
     // time.
-    Node child = _this.firstChild;
+    Node? child = _this.firstChild;
     while (child != null) {
-      Node nextChild = child.nextNode;
+      Node? nextChild = child.nextNode;
       if (test(child) == removeMatching) {
         _this._removeChild(child);
       }
@@ -23364,8 +23302,8 @@
     // TODO(jacobr): should we throw an exception if parent is already null?
     // TODO(vsm): Use the native remove when available.
     if (this.parentNode != null) {
-      final Node parent = this.parentNode;
-      parentNode._removeChild(this);
+      final Node parent = this.parentNode!;
+      parent._removeChild(this);
     }
   }
 
@@ -23374,10 +23312,9 @@
    */
   Node replaceWith(Node otherNode) {
     try {
-      final Node parent = this.parentNode;
+      final Node parent = this.parentNode!;
       parent._replaceChild(otherNode, this);
     } catch (e) {}
-    ;
     return this;
   }
 
@@ -23397,7 +23334,7 @@
 
       // Optimized route for copying between nodes.
       for (var i = 0, len = otherList.length; i < len; ++i) {
-        this.insertBefore(otherList._this.firstChild, refChild);
+        this.insertBefore(otherList._this.firstChild!, refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -23408,7 +23345,7 @@
 
   void _clearChildren() {
     while (firstChild != null) {
-      _removeChild(firstChild);
+      _removeChild(firstChild!);
     }
   }
 
@@ -23416,7 +23353,7 @@
    * Print out a String representation of this Node.
    */
   String toString() {
-    String value = nodeValue; // Fetch DOM Node property once.
+    String? value = nodeValue; // Fetch DOM Node property once.
     return value == null ? super.toString() : value;
   }
 
@@ -23430,7 +23367,7 @@
    */
   @Returns('NodeList')
   @Creates('NodeList')
-  final List<Node> childNodes;
+  List<Node> get childNodes => JS("NodeList", "#.childNodes", this);
 
   // To suppress missing implicit constructor warnings.
   factory Node._() {
@@ -23472,7 +23409,8 @@
    * * [Node.firstChild](https://developer.mozilla.org/en-US/docs/Web/API/Node.firstChild)
    *   from MDN.
    */
-  final Node? firstChild;
+
+  Node? get firstChild => JS("Node", "#.firstChild", this);
 
   bool get isConnected => JS("bool", "#.isConnected", this);
 
@@ -23484,9 +23422,11 @@
    * * [Node.lastChild](https://developer.mozilla.org/en-US/docs/Web/API/Node.lastChild)
    *   from MDN.
    */
-  final Node? lastChild;
+
+  Node? get lastChild => JS("Node", "#.lastChild", this);
 
   @JSName('nextSibling')
+
   /**
    * The next sibling node.
    *
@@ -23495,7 +23435,8 @@
    * * [Node.nextSibling](https://developer.mozilla.org/en-US/docs/Web/API/Node.nextSibling)
    *   from MDN.
    */
-  final Node? nextNode;
+
+  Node? get nextNode => JS("Node", "#.nextSibling", this);
 
   /**
    * The name of this node.
@@ -23548,7 +23489,8 @@
    *   from MDN. This page contains a table of [nodeValue] values for each
    *   [nodeType].
    */
-  final String? nodeValue;
+
+  String? get nodeValue => JS("String", "#.nodeValue", this);
 
   /**
    * The document this node belongs to.
@@ -23560,9 +23502,11 @@
    * * [Node.ownerDocument](https://developer.mozilla.org/en-US/docs/Web/API/Node.ownerDocument)
    *   from MDN.
    */
-  final Document? ownerDocument;
+
+  Document? get ownerDocument => JS("Document", "#.ownerDocument", this);
 
   @JSName('parentElement')
+
   /**
    * The parent element of this node.
    *
@@ -23574,7 +23518,8 @@
    * * [Node.parentElement](https://developer.mozilla.org/en-US/docs/Web/API/Node.parentElement)
    *   from W3C.
    */
-  final Element? parent;
+
+  Element? get parent => JS("Element", "#.parentElement", this);
 
   /**
    * The parent node of this node.
@@ -23584,9 +23529,11 @@
    * * [Node.parentNode](https://developer.mozilla.org/en-US/docs/Web/API/Node.parentNode)
    *   from MDN.
    */
-  final Node? parentNode;
+
+  Node? get parentNode => JS("Node", "#.parentNode", this);
 
   @JSName('previousSibling')
+
   /**
    * The previous sibling node.
    *
@@ -23595,7 +23542,8 @@
    * * [Node.previousSibling](https://developer.mozilla.org/en-US/docs/Web/API/Node.previousSibling)
    *   from MDN.
    */
-  final Node? previousNode;
+
+  Node? get previousNode => JS("Node", "#.previousSibling", this);
 
   @JSName('textContent')
   /**
@@ -23632,7 +23580,7 @@
    * * [Node.cloneNode](https://developer.mozilla.org/en-US/docs/Web/API/Node.cloneNode)
    *   from MDN.
    */
-  Node clone(bool deep) native;
+  Node clone(bool? deep) native;
 
   /**
    * Returns true if this node contains the specified node.
@@ -23743,9 +23691,9 @@
 
   void detach() native;
 
-  Node nextNode() native;
+  Node? nextNode() native;
 
-  Node previousNode() native;
+  Node? previousNode() native;
 }
 // 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
@@ -23806,7 +23754,7 @@
   // -- end List<Node> mixins.
 
   @JSName('item')
-  Node _item(int index) native;
+  Node? _item(int index) native;
 }
 // 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
@@ -23819,9 +23767,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final Element? nextElementSibling;
+  Element? get nextElementSibling =>
+      JS("Element", "#.nextElementSibling", this);
 
-  final Element? previousElementSibling;
+  Element? get previousElementSibling =>
+      JS("Element", "#.previousElementSibling", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -23834,7 +23784,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Element getElementById(String elementId) native;
+  Element? getElementById(String elementId) native;
 }
 // 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
@@ -23860,11 +23810,7 @@
 @Native("Notification")
 class Notification extends EventTarget {
   factory Notification(String title,
-      {String dir: null,
-      String body: null,
-      String lang: null,
-      String tag: null,
-      String icon: null}) {
+      {String? dir, String? body, String? lang, String? tag, String? icon}) {
     var parsedOptions = {};
     if (dir != null) parsedOptions['dir'] = dir;
     if (body != null) parsedOptions['body'] = body;
@@ -23938,7 +23884,7 @@
 
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  Object get data => JS("Object", "#.data", this);
+  Object? get data => JS("Object", "#.data", this);
 
   String get dir => JS("String", "#.dir", this);
 
@@ -24015,7 +23961,7 @@
 
   Notification get notification => JS("Notification", "#.notification", this);
 
-  final String? reply;
+  String? get reply => JS("String", "#.reply", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -24096,7 +24042,7 @@
   @JSName('contentWindow')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_contentWindow;
+  dynamic get _get_contentWindow => JS("", "#.contentWindow", this);
 
   String get data => JS("String", "#.data", this);
 
@@ -24104,7 +24050,7 @@
     JS("void", "#.data = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   String get height => JS("String", "#.height", this);
 
@@ -24190,7 +24136,7 @@
         JS("", "#.convertToBlob(#)", this, options_dict));
   }
 
-  Object getContext(String contextType, [Map? attributes]) {
+  Object? getContext(String contextType, [Map? attributes]) {
     if (attributes != null) {
       var attributes_1 = convertDartToNative_Dictionary(attributes);
       return _getContext_1(contextType, attributes_1);
@@ -24199,9 +24145,9 @@
   }
 
   @JSName('getContext')
-  Object _getContext_1(contextType, attributes) native;
+  Object? _getContext_1(contextType, attributes) native;
   @JSName('getContext')
-  Object _getContext_2(contextType) native;
+  Object? _getContext_2(contextType) native;
 
   ImageBitmap transferToImageBitmap() native;
 }
@@ -24225,11 +24171,7 @@
     JS("void", "#.direction = #", this, value);
   }
 
-  Object get fillStyle => JS("Object", "#.fillStyle", this);
-
-  set fillStyle(Object value) {
-    JS("void", "#.fillStyle = #", this, value);
-  }
+  Object? fillStyle;
 
   String get filter => JS("String", "#.filter", this);
 
@@ -24323,11 +24265,7 @@
     JS("void", "#.shadowOffsetY = #", this, value);
   }
 
-  Object get strokeStyle => JS("Object", "#.strokeStyle", this);
-
-  set strokeStyle(Object value) {
-    JS("void", "#.strokeStyle = #", this, value);
-  }
+  Object? strokeStyle;
 
   String get textAlign => JS("String", "#.textAlign", this);
 
@@ -24398,11 +24336,11 @@
   @JSName('createImageData')
   _createImageData_3(int sw, sh, imageDataColorSettings) native;
   @JSName('createImageData')
-  _createImageData_4(data, sw, int sh, imageDataColorSettings) native;
+  _createImageData_4(data, sw, int? sh, imageDataColorSettings) native;
 
   CanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) native;
 
-  CanvasPattern createPattern(
+  CanvasPattern? createPattern(
       /*CanvasImageSource*/ image, String repetitionType) native;
 
   CanvasGradient createRadialGradient(
@@ -24493,7 +24431,7 @@
   // From CanvasPath
 
   void arc(num x, num y, num radius, num startAngle, num endAngle,
-      bool anticlockwise) native;
+      bool? anticlockwise) native;
 
   void arcTo(num x1, num y1, num x2, num y2, num radius) native;
 
@@ -24503,7 +24441,7 @@
   void closePath() native;
 
   void ellipse(num x, num y, num radiusX, num radiusY, num rotation,
-      num startAngle, num endAngle, bool anticlockwise) native;
+      num startAngle, num endAngle, bool? anticlockwise) native;
 
   void lineTo(num x, num y) native;
 
@@ -24608,7 +24546,7 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   int get index => JS("int", "#.index", this);
 
@@ -24641,7 +24579,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final List<num>? quaternion;
+  List<num>? get quaternion => JS("List<num>", "#.quaternion", this);
 
   void populateMatrix(Object targetBuffer) native;
 }
@@ -24676,12 +24614,12 @@
     JS("void", "#.defaultValue = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   DomTokenList get htmlFor => JS("DomTokenList", "#.htmlFor", this);
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -24731,9 +24669,9 @@
       constraint,
       message);
 
-  final String? constraint;
+  String? get constraint => JS("String", "#.constraint", this);
 
-  final String? message;
+  String? get message => JS("String", "#.message", this);
 
   String get name => JS("String", "#.name", this);
 }
@@ -24782,11 +24720,7 @@
     JS("void", "#.currentTransform = #", this, value);
   }
 
-  Object get fillStyle => JS("Object", "#.fillStyle", this);
-
-  set fillStyle(Object value) {
-    JS("void", "#.fillStyle = #", this, value);
-  }
+  Object? fillStyle;
 
   String get filter => JS("String", "#.filter", this);
 
@@ -24874,11 +24808,7 @@
     JS("void", "#.shadowOffsetY = #", this, value);
   }
 
-  Object get strokeStyle => JS("Object", "#.strokeStyle", this);
-
-  set strokeStyle(Object value) {
-    JS("void", "#.strokeStyle = #", this, value);
-  }
+  Object? strokeStyle;
 
   void beginPath() native;
 
@@ -24888,7 +24818,7 @@
 
   CanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) native;
 
-  CanvasPattern createPattern(
+  CanvasPattern? createPattern(
       /*CanvasImageSource*/ image, String repetitionType) native;
 
   CanvasGradient createRadialGradient(
@@ -24938,7 +24868,7 @@
   // From CanvasPath
 
   void arc(num x, num y, num radius, num startAngle, num endAngle,
-      bool anticlockwise) native;
+      bool? anticlockwise) native;
 
   void arcTo(num x1, num y1, num x2, num y2, num radius) native;
 
@@ -24948,7 +24878,7 @@
   void closePath() native;
 
   void ellipse(num x, num y, num radiusX, num radiusY, num rotation,
-      num startAngle, num endAngle, bool anticlockwise) native;
+      num startAngle, num endAngle, bool? anticlockwise) native;
 
   void lineTo(num x, num y) native;
 
@@ -25057,15 +24987,15 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final int _childElementCount;
+  int get _childElementCount => JS("int", "#.childElementCount", this);
 
-  final List<Node> _children;
+  List<Node> get _children => JS("HtmlCollection", "#.children", this);
 
-  final Element _firstElementChild;
+  Element? get _firstElementChild => JS("Element", "#.firstElementChild", this);
 
-  final Element _lastElementChild;
+  Element? get _lastElementChild => JS("Element", "#.lastElementChild", this);
 
-  Element querySelector(String selectors);
+  Element? querySelector(String selectors);
 
   List<Node> _querySelectorAll(String selectors);
 }
@@ -25152,7 +25082,7 @@
   // From CanvasPath
 
   void arc(num x, num y, num radius, num startAngle, num endAngle,
-      bool anticlockwise) native;
+      bool? anticlockwise) native;
 
   void arcTo(num x1, num y1, num x2, num y2, num radius) native;
 
@@ -25162,7 +25092,7 @@
   void closePath() native;
 
   void ellipse(num x, num y, num radiusX, num radiusY, num rotation,
-      num startAngle, num endAngle, bool anticlockwise) native;
+      num startAngle, num endAngle, bool? anticlockwise) native;
 
   void lineTo(num x, num y) native;
 
@@ -25221,7 +25151,7 @@
   Future<bool> delete(String instrumentKey) =>
       promiseToFuture<bool>(JS("", "#.delete(#)", this, instrumentKey));
 
-  Future<Map<String, dynamic>> get(String instrumentKey) =>
+  Future<Map<String, dynamic>?> get(String instrumentKey) =>
       promiseToFutureAsMap(JS("", "#.get(#)", this, instrumentKey));
 
   Future has(String instrumentKey) =>
@@ -25262,7 +25192,7 @@
 
 @Native("PaymentRequest")
 class PaymentRequest extends EventTarget {
-  factory PaymentRequest(List<Map> methodData, Map details, [Map options]) {
+  factory PaymentRequest(List<Map> methodData, Map details, [Map? options]) {
     var methodData_1 = [];
     for (var i in methodData) {
       methodData_1.add(convertDartToNative_Dictionary(i));
@@ -25292,11 +25222,12 @@
 
   String get id => JS("String", "#.id", this);
 
-  final PaymentAddress? shippingAddress;
+  PaymentAddress? get shippingAddress =>
+      JS("PaymentAddress", "#.shippingAddress", this);
 
-  final String? shippingOption;
+  String? get shippingOption => JS("String", "#.shippingOption", this);
 
-  final String? shippingType;
+  String? get shippingType => JS("String", "#.shippingType", this);
 
   Future abort() => promiseToFuture(JS("", "#.abort()", this));
 
@@ -25391,17 +25322,18 @@
 
   String get methodName => JS("String", "#.methodName", this);
 
-  final String? payerEmail;
+  String? get payerEmail => JS("String", "#.payerEmail", this);
 
-  final String? payerName;
+  String? get payerName => JS("String", "#.payerName", this);
 
-  final String? payerPhone;
+  String? get payerPhone => JS("String", "#.payerPhone", this);
 
   String get requestId => JS("String", "#.requestId", this);
 
-  final PaymentAddress? shippingAddress;
+  PaymentAddress? get shippingAddress =>
+      JS("PaymentAddress", "#.shippingAddress", this);
 
-  final String? shippingOption;
+  String? get shippingOption => JS("String", "#.shippingOption", this);
 
   Future complete([String? paymentResult]) =>
       promiseToFuture(JS("", "#.complete(#)", this, paymentResult));
@@ -25432,21 +25364,22 @@
 
   PerformanceTiming get timing => JS("PerformanceTiming", "#.timing", this);
 
-  void clearMarks(String markName) native;
+  void clearMarks(String? markName) native;
 
-  void clearMeasures(String measureName) native;
+  void clearMeasures(String? measureName) native;
 
   void clearResourceTimings() native;
 
   List<PerformanceEntry> getEntries() native;
 
-  List<PerformanceEntry> getEntriesByName(String name, String entryType) native;
+  List<PerformanceEntry> getEntriesByName(String name, String? entryType)
+      native;
 
   List<PerformanceEntry> getEntriesByType(String entryType) native;
 
   void mark(String markName) native;
 
-  void measure(String measureName, String startMark, String endMark) native;
+  void measure(String measureName, String? startMark, String? endMark) native;
 
   double now() native;
 
@@ -25614,7 +25547,8 @@
 
   List<PerformanceEntry> getEntries() native;
 
-  List<PerformanceEntry> getEntriesByName(String name, String entryType) native;
+  List<PerformanceEntry> getEntriesByName(String name, String? entryType)
+      native;
 
   List<PerformanceEntry> getEntriesByType(String entryType) native;
 }
@@ -25858,9 +25792,9 @@
 
   String get name => JS("String", "#.name", this);
 
-  MimeType item(int index) native;
+  MimeType? item(int index) native;
 
-  MimeType namedItem(String name) native;
+  MimeType? namedItem(String name) native;
 }
 // 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
@@ -25920,11 +25854,11 @@
   Plugin elementAt(int index) => this[index];
   // -- end List<Plugin> mixins.
 
-  Plugin item(int index) native;
+  Plugin? item(int index) native;
 
-  Plugin namedItem(String name) native;
+  Plugin? namedItem(String name) native;
 
-  void refresh(bool reload) native;
+  void refresh(bool? reload) native;
 }
 // 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
@@ -26016,7 +25950,7 @@
   @JSName('state')
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _get_state;
+  dynamic get _get_state => JS("", "#.state", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26092,7 +26026,8 @@
 
   PresentationRequest? defaultRequest;
 
-  final PresentationReceiver? receiver;
+  PresentationReceiver? get receiver =>
+      JS("PresentationReceiver", "#.receiver", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26219,7 +26154,9 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Future get connectionList => JS("Future", "#.connectionList", this);
+  Future<PresentationConnectionList> get connectionList =>
+      promiseToFuture<PresentationConnectionList>(
+          JS("", "#.connectionList", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26270,7 +26207,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final StyleSheet? sheet;
+  StyleSheet? get sheet => JS("StyleSheet", "#.sheet", this);
 
   String get target => JS("String", "#.target", this);
 }
@@ -26302,7 +26239,7 @@
   static bool get supported => Element.isTagSupported('progress');
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -26370,9 +26307,9 @@
       type,
       eventInitDict);
 
-  Future get promise => JS("Future", "#.promise", this);
+  Future get promise => promiseToFuture(JS("", "#.promise", this));
 
-  Object get reason => JS("Object", "#.reason", this);
+  Object? get reason => JS("Object", "#.reason", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26412,7 +26349,7 @@
       JS('PushEvent', 'new PushEvent(#,#)', type, eventInitDict);
   static PushEvent _create_2(type) => JS('PushEvent', 'new PushEvent(#)', type);
 
-  final PushMessageData? data;
+  PushMessageData? get data => JS("PushMessageData", "#.data", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26485,7 +26422,7 @@
   PushSubscriptionOptions get options =>
       JS("PushSubscriptionOptions", "#.options", this);
 
-  ByteBuffer getKey(String name) native;
+  ByteBuffer? getKey(String name) native;
 
   Future<bool> unsubscribe() =>
       promiseToFuture<bool>(JS("", "#.unsubscribe()", this));
@@ -26501,7 +26438,8 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final ByteBuffer? applicationServerKey;
+  ByteBuffer? get applicationServerKey =>
+      JS("ByteBuffer", "#.applicationServerKey", this);
 
   bool get userVisibleOnly => JS("bool", "#.userVisibleOnly", this);
 }
@@ -26567,7 +26505,7 @@
   factory Range() => document.createRange();
 
   factory Range.fromPoint(Point point) =>
-      document._caretRangeFromPoint(point.x, point.y);
+      document._caretRangeFromPoint(point.x.toInt(), point.y.toInt());
   // To suppress missing implicit constructor warnings.
   factory Range._() {
     throw new UnsupportedError("Not supported");
@@ -26610,14 +26548,14 @@
 
   void detach() native;
 
-  void expand(String unit) native;
+  void expand(String? unit) native;
 
   DocumentFragment extractContents() native;
 
   Rectangle getBoundingClientRect() native;
 
   @JSName('getClientRects')
-  @Returns('DomRectList|Null')
+  @Returns('DomRectList')
   @Creates('DomRectList')
   List<Rectangle> _getClientRects() native;
 
@@ -27089,7 +27027,7 @@
 
   DateTime get timestamp => convertNativeToDart_DateTime(this._get_timestamp);
   @JSName('timestamp')
-  final dynamic _get_timestamp;
+  dynamic get _get_timestamp => JS("", "#.timestamp", this);
 
   String get type => JS("String", "#.type", this);
 
@@ -27104,7 +27042,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Native("RTCPeerConnection,webkitRTCPeerConnection,mozRTCPeerConnection")
 class RtcPeerConnection extends EventTarget {
-  factory RtcPeerConnection(Map rtcIceServers, [Map mediaConstraints]) {
+  factory RtcPeerConnection(Map rtcIceServers, [Map? mediaConstraints]) {
     var constructorName =
         JS('RtcPeerConnection', 'window[#]', 'RTCPeerConnection');
     if (mediaConstraints != null) {
@@ -27146,7 +27084,7 @@
   * Temporarily exposes _getStats and old getStats as getLegacyStats until Chrome fully supports
   * new getStats API.
   */
-  Future<RtcStatsResponse> getLegacyStats([MediaStreamTrack selector]) {
+  Future<RtcStatsResponse> getLegacyStats([MediaStreamTrack? selector]) {
     var completer = new Completer<RtcStatsResponse>();
     _getStats((value) {
       completer.complete(value);
@@ -27156,7 +27094,7 @@
 
   @JSName('getStats')
   Future _getStats(
-      [RtcStatsCallback successCallback, MediaStreamTrack selector]) native;
+      [RtcStatsCallback? successCallback, MediaStreamTrack? selector]) native;
 
   static Future generateCertificate(/*AlgorithmIdentifier*/ keygenAlgorithm) =>
       JS('dynamic', 'generateCertificate(#)', keygenAlgorithm);
@@ -27234,9 +27172,11 @@
 
   String get iceGatheringState => JS("String", "#.iceGatheringState", this);
 
-  final RtcSessionDescription? localDescription;
+  RtcSessionDescription? get localDescription =>
+      JS("RtcSessionDescription", "#.localDescription", this);
 
-  final RtcSessionDescription? remoteDescription;
+  RtcSessionDescription? get remoteDescription =>
+      JS("RtcSessionDescription", "#.remoteDescription", this);
 
   String get signalingState => JS("String", "#.signalingState", this);
 
@@ -27388,7 +27328,7 @@
   static RtcPeerConnectionIceEvent _create_2(type) =>
       JS('RtcPeerConnectionIceEvent', 'new RTCPeerConnectionIceEvent(#)', type);
 
-  final RtcIceCandidate? candidate;
+  RtcIceCandidate? get candidate => JS("RtcIceCandidate", "#.candidate", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -27431,7 +27371,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final MediaStreamTrack? track;
+  MediaStreamTrack? get track => JS("MediaStreamTrack", "#.track", this);
 }
 // 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
@@ -27465,7 +27405,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Map _getItem(String key) =>
+  Map? _getItem(String key) =>
       convertNativeToDart_Dictionary(JS('', '#.get(#)', this, key));
 
   void addAll(Map<String, dynamic> other) {
@@ -27476,7 +27416,7 @@
 
   bool containsKey(dynamic key) => _getItem(key) != null;
 
-  Map operator [](dynamic key) => _getItem(key);
+  Map? operator [](dynamic key) => _getItem(key);
 
   void forEach(void f(String key, dynamic value)) {
     var entries = JS('', '#.entries()', this);
@@ -27533,7 +27473,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  RtcLegacyStatsReport namedItem(String name) native;
+  RtcLegacyStatsReport namedItem(String? name) native;
 
   List<RtcLegacyStatsReport> result() native;
 }
@@ -27777,9 +27717,9 @@
 
   String get orientation => JS("String", "#.orientation", this);
 
-  final Element? scrollSource;
+  Element? get scrollSource => JS("Element", "#.scrollSource", this);
 
-  Object get timeRange => JS("Object", "#.timeRange", this);
+  Object? get timeRange => JS("Object", "#.timeRange", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -27870,10 +27810,10 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -27933,9 +27873,9 @@
 
   bool checkValidity() native;
 
-  Element item(int index) native;
+  Element? item(int index) native;
 
-  OptionElement namedItem(String name) native;
+  OptionElement? namedItem(String name) native;
 
   bool reportValidity() native;
 
@@ -27969,19 +27909,19 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final Node? anchorNode;
+  Node? get anchorNode => JS("Node", "#.anchorNode", this);
 
   int get anchorOffset => JS("int", "#.anchorOffset", this);
 
-  final Node? baseNode;
+  Node? get baseNode => JS("Node", "#.baseNode", this);
 
   int get baseOffset => JS("int", "#.baseOffset", this);
 
-  final Node? extentNode;
+  Node? get extentNode => JS("Node", "#.extentNode", this);
 
   int get extentOffset => JS("int", "#.extentOffset", this);
 
-  final Node? focusNode;
+  Node? get focusNode => JS("Node", "#.focusNode", this);
 
   int get focusOffset => JS("int", "#.focusOffset", this);
 
@@ -28009,7 +27949,7 @@
 
   Range getRangeAt(int index) native;
 
-  void modify(String alter, String direction, String granularity) native;
+  void modify(String? alter, String? direction, String? granularity) native;
 
   void removeAllRanges() native;
 
@@ -28099,7 +28039,7 @@
   }
 
   @JSName('postMessage')
-  void _postMessage_1(message, List<Object> transfer) native;
+  void _postMessage_1(message, List<Object>? transfer) native;
   @JSName('postMessage')
   void _postMessage_2(message) native;
 
@@ -28119,9 +28059,10 @@
   static const EventStreamProvider<MessageEvent> messageEvent =
       const EventStreamProvider<MessageEvent>('message');
 
-  final ServiceWorker? controller;
+  ServiceWorker? get controller => JS("ServiceWorker", "#.controller", this);
 
-  Future get ready => JS("Future", "#.ready", this);
+  Future<ServiceWorkerRegistration> get ready =>
+      promiseToFuture<ServiceWorkerRegistration>(JS("", "#.ready", this));
 
   Future<ServiceWorkerRegistration> getRegistration([String? documentURL]) =>
       promiseToFuture<ServiceWorkerRegistration>(
@@ -28201,12 +28142,12 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final ServiceWorker? active;
+  ServiceWorker? get active => JS("ServiceWorker", "#.active", this);
 
   BackgroundFetchManager get backgroundFetch =>
       JS("BackgroundFetchManager", "#.backgroundFetch", this);
 
-  final ServiceWorker? installing;
+  ServiceWorker? get installing => JS("ServiceWorker", "#.installing", this);
 
   NavigationPreloadManager get navigationPreload =>
       JS("NavigationPreloadManager", "#.navigationPreload", this);
@@ -28220,7 +28161,7 @@
 
   SyncManager get sync => JS("SyncManager", "#.sync", this);
 
-  final ServiceWorker? waiting;
+  ServiceWorker? get waiting => JS("ServiceWorker", "#.waiting", this);
 
   Future<List<dynamic>> getNotifications([Map? filter]) {
     var filter_dict = null;
@@ -28268,7 +28209,7 @@
   /// Checks if this type is supported on the current platform.
   static bool get supported => Element.isTagSupported('shadow');
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getDistributedNodes() native;
 }
@@ -28300,26 +28241,28 @@
 
   String get mode => JS("String", "#.mode", this);
 
-  final ShadowRoot? olderShadowRoot;
+  ShadowRoot? get olderShadowRoot =>
+      JS("ShadowRoot", "#.olderShadowRoot", this);
 
   // From DocumentOrShadowRoot
 
-  final Element? activeElement;
+  Element? get activeElement => JS("Element", "#.activeElement", this);
 
-  final Element? fullscreenElement;
+  Element? get fullscreenElement => JS("Element", "#.fullscreenElement", this);
 
-  final Element? pointerLockElement;
+  Element? get pointerLockElement =>
+      JS("Element", "#.pointerLockElement", this);
 
-  @Returns('_StyleSheetList|Null')
+  @Returns('_StyleSheetList')
   @Creates('_StyleSheetList')
   List<StyleSheet> get styleSheets =>
       JS("_StyleSheetList", "#.styleSheets", this);
 
-  Element elementFromPoint(int x, int y) native;
+  Element? elementFromPoint(int x, int y) native;
 
   List<Element> elementsFromPoint(int x, int y) native;
 
-  Selection getSelection() native;
+  Selection? getSelection() native;
 
   static bool get supported => JS(
       'bool',
@@ -29068,15 +29011,16 @@
   static SpeechRecognitionEvent _create_2(type) =>
       JS('SpeechRecognitionEvent', 'new SpeechRecognitionEvent(#)', type);
 
-  final Document? emma;
+  Document? get emma => JS("Document", "#.emma", this);
 
-  final Document? interpretation;
+  Document? get interpretation => JS("Document", "#.interpretation", this);
 
   int get resultIndex => JS("int", "#.resultIndex", this);
 
   @Returns('_SpeechRecognitionResultList|Null')
   @Creates('_SpeechRecognitionResultList')
-  final List<SpeechRecognitionResult>? results;
+  List<SpeechRecognitionResult>? get results =>
+      JS("_SpeechRecognitionResultList", "#.results", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -29373,7 +29317,7 @@
   // TODO(nweiz): update this when maps support lazy iteration
   bool containsValue(Object? value) => values.any((e) => e == value);
 
-  bool containsKey(Object? key) => _getItem(key) != null;
+  bool containsKey(Object? key) => _getItem(key as String) != null;
 
   String? operator [](Object? key) => _getItem(key as String);
 
@@ -29383,12 +29327,12 @@
 
   String putIfAbsent(String key, String ifAbsent()) {
     if (!containsKey(key)) this[key] = ifAbsent();
-    return this[key];
+    return this[key] as String;
   }
 
   String? remove(Object? key) {
     final value = this[key];
-    _removeItem(key);
+    _removeItem(key as String);
     return value;
   }
 
@@ -29399,7 +29343,7 @@
       final key = _key(i);
       if (key == null) return;
 
-      f(key, this[key]);
+      f(key, this[key]!);
     }
   }
 
@@ -29432,10 +29376,10 @@
   void _clear() native;
 
   @JSName('getItem')
-  String _getItem(String key) native;
+  String? _getItem(String key) native;
 
   @JSName('key')
-  String _key(int index) native;
+  String? _key(int index) native;
 
   @JSName('removeItem')
   void _removeItem(String key) native;
@@ -29462,12 +29406,12 @@
   factory StorageEvent(String type,
       {bool canBubble: false,
       bool cancelable: false,
-      String key,
-      String oldValue,
-      String newValue,
-      String url,
-      Storage storageArea}) {
-    StorageEvent e = document._createEvent("StorageEvent");
+      String? key,
+      String? oldValue,
+      String? newValue,
+      String? url,
+      Storage? storageArea}) {
+    StorageEvent e = document._createEvent("StorageEvent") as StorageEvent;
     e._initStorageEvent(
         type, canBubble, cancelable, key, oldValue, newValue, url, storageArea);
     return e;
@@ -29485,26 +29429,26 @@
   static StorageEvent _create_2(type) =>
       JS('StorageEvent', 'new StorageEvent(#)', type);
 
-  final String? key;
+  String? get key => JS("String", "#.key", this);
 
-  final String? newValue;
+  String? get newValue => JS("String", "#.newValue", this);
 
-  final String? oldValue;
+  String? get oldValue => JS("String", "#.oldValue", this);
 
-  final Storage? storageArea;
+  Storage? get storageArea => JS("Storage", "#.storageArea", this);
 
   String get url => JS("String", "#.url", this);
 
   @JSName('initStorageEvent')
   void _initStorageEvent(
-      String typeArg,
-      bool canBubbleArg,
-      bool cancelableArg,
-      String keyArg,
+      String? typeArg,
+      bool? canBubbleArg,
+      bool? cancelableArg,
+      String? keyArg,
       String? oldValueArg,
       String? newValueArg,
-      String urlArg,
-      Storage storageAreaArg) native;
+      String? urlArg,
+      Storage? storageAreaArg) native;
 }
 // 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
@@ -29517,7 +29461,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Future<Map<String, dynamic>> estimate() =>
+  Future<Map<String, dynamic>?> estimate() =>
       promiseToFutureAsMap(JS("", "#.estimate()", this));
 
   Future<bool> persist() => promiseToFuture<bool>(JS("", "#.persist()", this));
@@ -29575,7 +29519,7 @@
     JS("void", "#.media = #", this, value);
   }
 
-  final StyleSheet? sheet;
+  StyleSheet? get sheet => JS("StyleSheet", "#.sheet", this);
 
   String get type => JS("String", "#.type", this);
 
@@ -29596,7 +29540,7 @@
 
   String get type => JS("String", "#.type", this);
 
-  bool matchMedium(String mediaquery) native;
+  bool matchMedium(String? mediaquery) native;
 }
 // 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
@@ -29626,7 +29570,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  CssStyleValue get(String property) native;
+  CssStyleValue? get(String property) native;
 
   List<CssStyleValue> getAll(String property) native;
 
@@ -29651,15 +29595,16 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  final String? href;
+  String? get href => JS("String", "#.href", this);
 
   MediaList get media => JS("MediaList", "#.media", this);
 
-  final Node? ownerNode;
+  Node? get ownerNode => JS("Node", "#.ownerNode", this);
 
-  final StyleSheet? parentStyleSheet;
+  StyleSheet? get parentStyleSheet =>
+      JS("StyleSheet", "#.parentStyleSheet", this);
 
-  final String? title;
+  String? get title => JS("String", "#.title", this);
 
   String get type => JS("String", "#.type", this);
 }
@@ -29825,14 +29770,14 @@
     }
     var tbody = new Element.tag('tbody');
     this.children.add(tbody);
-    return tbody;
+    return tbody as TableSectionElement;
   }
 
   @JSName('createTBody')
   TableSectionElement _nativeCreateTBody() native;
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(html,
           validator: validator, treeSanitizer: treeSanitizer);
@@ -29867,12 +29812,12 @@
   TableCaptionElement? caption;
 
   @JSName('rows')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _rows => JS("HtmlCollection", "#.rows", this);
 
   @JSName('tBodies')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _tBodies => JS("HtmlCollection", "#.tBodies", this);
 
@@ -29913,10 +29858,11 @@
     return insertCell(-1);
   }
 
-  TableCellElement insertCell(int index) => _insertCell(index);
+  TableCellElement insertCell(int index) =>
+      _insertCell(index) as TableCellElement;
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(html,
           validator: validator, treeSanitizer: treeSanitizer);
@@ -29951,7 +29897,7 @@
   TableRowElement.created() : super.created();
 
   @JSName('cells')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _cells => JS("HtmlCollection", "#.cells", this);
 
@@ -29976,10 +29922,10 @@
     return insertRow(-1);
   }
 
-  TableRowElement insertRow(int index) => _insertRow(index);
+  TableRowElement insertRow(int index) => _insertRow(index) as TableRowElement;
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(html,
           validator: validator, treeSanitizer: treeSanitizer);
@@ -30007,7 +29953,7 @@
   TableSectionElement.created() : super.created();
 
   @JSName('rows')
-  @Returns('HtmlCollection|Null')
+  @Returns('HtmlCollection')
   @Creates('HtmlCollection')
   List<Node> get _rows => JS("HtmlCollection", "#.rows", this);
 
@@ -30074,7 +30020,7 @@
    * * <https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin>
    */
   void setInnerHtml(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     text = null;
     content.nodes.clear();
     var fragment = createFragment(html,
@@ -30101,11 +30047,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final SlotElement? assignedSlot;
+  SlotElement? get assignedSlot => JS("SlotElement", "#.assignedSlot", this);
 
   String get wholeText => JS("String", "#.wholeText", this);
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getDestinationInsertionPoints() native;
 
@@ -30170,10 +30116,10 @@
     JS("void", "#.disabled = #", this, value);
   }
 
-  final FormElement? form;
+  FormElement? get form => JS("FormElement", "#.form", this);
 
   @Unstable()
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> get labels => JS("NodeList", "#.labels", this);
 
@@ -30303,12 +30249,12 @@
   factory TextEvent(String type,
       {bool canBubble: false,
       bool cancelable: false,
-      Window view,
-      String data}) {
+      Window? view,
+      String? data}) {
     if (view == null) {
       view = window;
     }
-    TextEvent e = document._createEvent("TextEvent");
+    TextEvent e = document._createEvent("TextEvent") as TextEvent;
     e._initTextEvent(type, canBubble, cancelable, view, data);
     return e;
   }
@@ -30320,8 +30266,8 @@
   String get data => JS("String", "#.data", this);
 
   @JSName('initTextEvent')
-  void _initTextEvent(String type, bool bubbles, bool cancelable, Window? view,
-      String data) native;
+  void _initTextEvent(String? type, bool? bubbles, bool? cancelable,
+      Window? view, String? data) native;
 }
 // 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
@@ -30380,9 +30326,10 @@
   static const EventStreamProvider<Event> cueChangeEvent =
       const EventStreamProvider<Event>('cuechange');
 
-  final TextTrackCueList? activeCues;
+  TextTrackCueList? get activeCues =>
+      JS("TextTrackCueList", "#.activeCues", this);
 
-  final TextTrackCueList? cues;
+  TextTrackCueList? get cues => JS("TextTrackCueList", "#.cues", this);
 
   String get id => JS("String", "#.id", this);
 
@@ -30458,7 +30405,7 @@
     JS("void", "#.startTime = #", this, value);
   }
 
-  final TextTrack? track;
+  TextTrack? get track => JS("TextTrack", "#.track", this);
 
   /// Stream of `enter` events handled by this [TextTrackCue].
   Stream<Event> get onEnter => enterEvent.forTarget(this);
@@ -30526,7 +30473,7 @@
 
   TextTrackCue __getter__(int index) native;
 
-  TextTrackCue getCueById(String id) native;
+  TextTrackCue? getCueById(String id) native;
 }
 // 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
@@ -30600,7 +30547,7 @@
 
   TextTrack __getter__(int index) native;
 
-  TextTrack getTrackById(String id) native;
+  TextTrack? getTrackById(String id) native;
 
   /// Stream of `addtrack` events handled by this [TextTrackList].
   Stream<TrackEvent> get onAddTrack => addTrackEvent.forTarget(this);
@@ -30717,7 +30664,7 @@
   @JSName('radiusY')
   num get _radiusY => JS("num", "#.radiusY", this);
 
-  final String? region;
+  String? get region => JS("String", "#.region", this);
 
   num get rotationAngle => JS("num", "#.rotationAngle", this);
 
@@ -30731,7 +30678,7 @@
   @JSName('target')
   @Creates('Element|Document')
   @Returns('Element|Document')
-  final dynamic _get_target;
+  dynamic get _get_target => JS("", "#.target", this);
 
 // As of Chrome 37, these all changed from long to double.  This code
 // preserves backwards compatibility for the time being.
@@ -30812,17 +30759,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 @Native("TouchList")
 class TouchList extends Interceptor
     with ListMixin<Touch>, ImmutableListMixin<Touch>
     implements JavaScriptIndexingBehavior<Touch>, List<Touch> {
-  /// NB: This constructor likely does not work as you might expect it to! This
-  /// constructor will simply fail (returning null) if you are not on a device
-  /// with touch enabled. See dartbug.com/8314.
-  // TODO(5760): createTouchList now uses varargs.
-  factory TouchList() => null; //document._createTouchList();
   // To suppress missing implicit constructor warnings.
   factory TouchList._() {
     throw new UnsupportedError("Not supported");
@@ -30876,7 +30816,7 @@
   Touch elementAt(int index) => this[index];
   // -- end List<Touch> mixins.
 
-  Touch item(int index) native;
+  Touch? item(int index) native;
 }
 // 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
@@ -31042,7 +30982,7 @@
       JS('TrackEvent', 'new TrackEvent(#)', type);
 
   @Creates('Null')
-  final Object? track;
+  Object? get track => JS("Object", "#.track", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -31094,25 +31034,25 @@
     JS("void", "#.currentNode = #", this, value);
   }
 
-  final NodeFilter? filter;
+  NodeFilter? get filter => JS("NodeFilter", "#.filter", this);
 
   Node get root => JS("Node", "#.root", this);
 
   int get whatToShow => JS("int", "#.whatToShow", this);
 
-  Node firstChild() native;
+  Node? firstChild() native;
 
-  Node lastChild() native;
+  Node? lastChild() native;
 
-  Node nextNode() native;
+  Node? nextNode() native;
 
-  Node nextSibling() native;
+  Node? nextSibling() native;
 
-  Node parentNode() native;
+  Node? parentNode() native;
 
-  Node previousNode() native;
+  Node? previousNode() native;
 
-  Node previousSibling() native;
+  Node? previousSibling() native;
 }
 // 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
@@ -31172,14 +31112,14 @@
   // Contrary to JS, we default canBubble and cancelable to true, since that's
   // what people want most of the time anyway.
   factory UIEvent(String type,
-      {Window view,
+      {Window? view,
       int detail: 0,
       bool canBubble: true,
       bool cancelable: true}) {
     if (view == null) {
       view = window;
     }
-    UIEvent e = document._createEvent("UIEvent");
+    UIEvent e = document._createEvent("UIEvent") as UIEvent;
     e._initUIEvent(type, canBubble, cancelable, view, detail);
     return e;
   }
@@ -31197,13 +31137,14 @@
 
   int get detail => JS("int", "#.detail", this);
 
-  final InputDeviceCapabilities? sourceCapabilities;
+  InputDeviceCapabilities? get sourceCapabilities =>
+      JS("InputDeviceCapabilities", "#.sourceCapabilities", this);
 
   WindowBase? get view => _convertNativeToDart_Window(this._get_view);
   @JSName('view')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_view;
+  dynamic get _get_view => JS("", "#.view", this);
 
   @JSName('which')
   @Unstable()
@@ -31247,7 +31188,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Future cancel(Object reason) =>
+  Future cancel(Object? reason) =>
       promiseToFuture(JS("", "#.cancel(#)", this, reason));
 
   void notifyLockAcquired() native;
@@ -31397,7 +31338,7 @@
 
   void delete(String name) native;
 
-  String get(String name) native;
+  String? get(String name) native;
 
   List<String> getAll(String name) native;
 
@@ -31417,23 +31358,23 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final String hash;
+  String get hash => JS("String", "#.hash", this);
 
-  final String host;
+  String get host => JS("String", "#.host", this);
 
-  final String hostname;
+  String get hostname => JS("String", "#.hostname", this);
 
-  final String href;
+  String get href => JS("String", "#.href", this);
 
-  final String origin;
+  String get origin => JS("String", "#.origin", this);
 
-  final String pathname;
+  String get pathname => JS("String", "#.pathname", this);
 
-  final String port;
+  String get port => JS("String", "#.port", this);
 
-  final String protocol;
+  String get protocol => JS("String", "#.protocol", this);
 
-  final String search;
+  String get search => JS("String", "#.search", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -31459,7 +31400,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Float32List getTransformTo(VRCoordinateSystem other) native;
+  Float32List? getTransformTo(VRCoordinateSystem other) native;
 }
 // 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
@@ -31667,7 +31608,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final VRStageBounds? bounds;
+  VRStageBounds? get bounds => JS("VRStageBounds", "#.bounds", this);
 
   num get emulatedHeight => JS("num", "#.emulatedHeight", this);
 }
@@ -31682,17 +31623,21 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final Float32List? angularAcceleration;
+  Float32List? get angularAcceleration =>
+      JS("Float32List", "#.angularAcceleration", this);
 
-  final Float32List? angularVelocity;
+  Float32List? get angularVelocity =>
+      JS("Float32List", "#.angularVelocity", this);
 
-  final Float32List? linearAcceleration;
+  Float32List? get linearAcceleration =>
+      JS("Float32List", "#.linearAcceleration", this);
 
-  final Float32List? linearVelocity;
+  Float32List? get linearVelocity =>
+      JS("Float32List", "#.linearVelocity", this);
 
-  final Float32List? orientation;
+  Float32List? get orientation => JS("Float32List", "#.orientation", this);
 
-  final Float32List? position;
+  Float32List? get position => JS("Float32List", "#.position", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -31953,7 +31898,7 @@
     JS("void", "#.selected = #", this, value);
   }
 
-  final SourceBuffer? sourceBuffer;
+  SourceBuffer? get sourceBuffer => JS("SourceBuffer", "#.sourceBuffer", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -31975,7 +31920,7 @@
 
   VideoTrack __getter__(int index) native;
 
-  VideoTrack getTrackById(String id) native;
+  VideoTrack? getTrackById(String id) native;
 
   Stream<Event> get onChange => changeEvent.forTarget(this);
 }
@@ -32046,23 +31991,11 @@
 
   @Creates('Null')
   @Returns('num|String')
-  Object get line => JS("Object", "#.line", this);
+  Object? line;
 
   @Creates('Null')
   @Returns('num|String')
-  set line(Object value) {
-    JS("void", "#.line = #", this, value);
-  }
-
-  @Creates('Null')
-  @Returns('num|String')
-  Object get position => JS("Object", "#.position", this);
-
-  @Creates('Null')
-  @Returns('num|String')
-  set position(Object value) {
-    JS("void", "#.position = #", this, value);
-  }
+  Object? position;
 
   VttRegion? region;
 
@@ -32351,7 +32284,7 @@
 @Native("WheelEvent")
 class WheelEvent extends MouseEvent {
   factory WheelEvent(String type,
-      {Window view,
+      {Window? view,
       num deltaX: 0,
       num deltaY: 0,
       num deltaZ: 0,
@@ -32368,7 +32301,7 @@
       bool altKey: false,
       bool shiftKey: false,
       bool metaKey: false,
-      EventTarget relatedTarget}) {
+      EventTarget? relatedTarget}) {
     var options = {
       'view': view,
       'deltaMode': deltaMode,
@@ -32603,7 +32536,7 @@
    * * [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window.open)
    *   from MDN.
    */
-  WindowBase open(String url, String name, [String options]) {
+  WindowBase open(String url, String name, [String? options]) {
     if (options == null) {
       return _DOMWindowCrossFrame._createSafe(_open2(url, name));
     } else {
@@ -32964,8 +32897,6 @@
 
   String get defaultStatus => JS("String", "#.defaultStatus", this);
 
-  /// *Deprecated*.
-
   set defaultStatus(String value) {
     JS("void", "#.defaultStatus = #", this, value);
   }
@@ -32974,8 +32905,6 @@
 
   String get defaultstatus => JS("String", "#.defaultstatus", this);
 
-  /// *Deprecated*.
-
   set defaultstatus(String value) {
     JS("void", "#.defaultstatus = #", this, value);
   }
@@ -33080,15 +33009,6 @@
 
   String get name => JS("String", "#.name", this);
 
-  /**
-   * The name of this window.
-   *
-   * ## Other resources
-   *
-   * * [Window.name](https://developer.mozilla.org/en-US/docs/Web/API/Window/name)
-   *   from MDN.
-   */
-
   set name(String value) {
     JS("void", "#.name = #", this, value);
   }
@@ -33120,9 +33040,9 @@
   @JSName('opener')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_opener;
+  dynamic get _get_opener => JS("", "#.opener", this);
 
-  set opener(Window value) {
+  set opener(WindowBase? value) {
     JS("void", "#.opener = #", this, value);
   }
 
@@ -33192,7 +33112,7 @@
   @JSName('parent')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_parent;
+  dynamic get _get_parent => JS("", "#.parent", this);
 
   /**
    * Timing and navigation data for this window.
@@ -33298,7 +33218,7 @@
    */
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_self;
+  dynamic get _get_self => JS("", "#.self", this);
 
   /**
    * Storage for this window that is cleared when this session ends.
@@ -33333,8 +33253,6 @@
 
   String get status => JS("String", "#.status", this);
 
-  /// *Deprecated*.
-
   set status(String value) {
     JS("void", "#.status = #", this, value);
   }
@@ -33379,7 +33297,7 @@
   @JSName('top')
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_top;
+  dynamic get _get_top => JS("", "#.top", this);
 
   VisualViewport get visualViewport =>
       JS("VisualViewport", "#.visualViewport", this);
@@ -33404,16 +33322,16 @@
    */
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _get_window;
+  dynamic get _get_window => JS("", "#.window", this);
 
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  WindowBase? __getter__(index_OR_name) {
+  WindowBase __getter__(index_OR_name) {
     if ((index_OR_name is int)) {
-      return _convertNativeToDart_Window(__getter___1(index_OR_name));
+      return _convertNativeToDart_Window(__getter___1(index_OR_name))!;
     }
     if ((index_OR_name is String)) {
-      return _convertNativeToDart_Window(__getter___2(index_OR_name));
+      return _convertNativeToDart_Window(__getter___2(index_OR_name))!;
     }
     throw new ArgumentError("Incorrect number or type of arguments");
   }
@@ -33467,8 +33385,8 @@
    * * [Window.find](https://developer.mozilla.org/en-US/docs/Web/API/Window.find)
    *   from MDN.
    */
-  bool find(String string, bool caseSensitive, bool backwards, bool wrap,
-      bool wholeWord, bool searchInFrames, bool showDialog) native;
+  bool find(String? string, bool? caseSensitive, bool? backwards, bool? wrap,
+      bool? wholeWord, bool? searchInFrames, bool? showDialog) native;
 
   @JSName('getComputedStyle')
   CssStyleDeclaration _getComputedStyle(Element elt, [String? pseudoElt])
@@ -33481,9 +33399,9 @@
   /**
    * Returns all CSS rules that apply to the element's pseudo-element.
    */
-  @Returns('_CssRuleList|Null')
+  @Returns('_CssRuleList')
   @Creates('_CssRuleList')
-  List<CssRule> getMatchedCssRules(Element element, String? pseudoElement)
+  List<CssRule> getMatchedCssRules(Element? element, String? pseudoElement)
       native;
 
   /**
@@ -33494,7 +33412,7 @@
    * * [Window.getSelection](https://developer.mozilla.org/en-US/docs/Web/API/Window.getSelection)
    *   from MDN.
    */
-  Selection getSelection() native;
+  Selection? getSelection() native;
 
   /**
    * Returns a list of media queries for the given query string.
@@ -33668,7 +33586,7 @@
    * * [Window.scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
    *   from MDN.
    */
-  void _scroll_3(num x, num y) native;
+  void _scroll_3(num? x, num? y) native;
   @JSName('scroll')
   /**
    * Scrolls the page horizontally and vertically to a specific point.
@@ -33680,7 +33598,7 @@
    * * [Window.scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
    *   from MDN.
    */
-  void _scroll_4(int x, int y) native;
+  void _scroll_4(int? x, int? y) native;
   @JSName('scroll')
   /**
    * Scrolls the page horizontally and vertically to a specific point.
@@ -33692,7 +33610,7 @@
    * * [Window.scroll](https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll)
    *   from MDN.
    */
-  void _scroll_5(int x, int y, scrollOptions) native;
+  void _scroll_5(int? x, int? y, scrollOptions) native;
 
   /**
    * Scrolls the page horizontally and vertically by an offset.
@@ -33757,7 +33675,7 @@
    * * [Window.scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
    *   from MDN.
    */
-  void _scrollBy_3(num x, num y) native;
+  void _scrollBy_3(num? x, num? y) native;
   @JSName('scrollBy')
   /**
    * Scrolls the page horizontally and vertically by an offset.
@@ -33767,7 +33685,7 @@
    * * [Window.scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
    *   from MDN.
    */
-  void _scrollBy_4(int x, int y) native;
+  void _scrollBy_4(int? x, int? y) native;
   @JSName('scrollBy')
   /**
    * Scrolls the page horizontally and vertically by an offset.
@@ -33777,7 +33695,7 @@
    * * [Window.scrollBy](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollBy)
    *   from MDN.
    */
-  void _scrollBy_5(int x, int y, scrollOptions) native;
+  void _scrollBy_5(int? x, int? y, scrollOptions) native;
 
   /**
    * Scrolls the page horizontally and vertically to a specific point.
@@ -33850,7 +33768,7 @@
    * * [Window.scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
    *   from MDN.
    */
-  void _scrollTo_3(num x, num y) native;
+  void _scrollTo_3(num? x, num? y) native;
   @JSName('scrollTo')
   /**
    * Scrolls the page horizontally and vertically to a specific point.
@@ -33862,7 +33780,7 @@
    * * [Window.scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
    *   from MDN.
    */
-  void _scrollTo_4(int x, int y) native;
+  void _scrollTo_4(int? x, int? y) native;
   @JSName('scrollTo')
   /**
    * Scrolls the page horizontally and vertically to a specific point.
@@ -33874,7 +33792,7 @@
    * * [Window.scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo)
    *   from MDN.
    */
-  void _scrollTo_5(int x, int y, scrollOptions) native;
+  void _scrollTo_5(int? x, int? y, scrollOptions) native;
 
   /**
    * Stops the window from loading.
@@ -34219,7 +34137,7 @@
    *   from W3C.
    */
   void moveTo(Point p) {
-    _moveTo(p.x, p.y);
+    _moveTo(p.x.toInt(), p.y.toInt());
   }
 
   @JSName('openDatabase')
@@ -34228,7 +34146,7 @@
   @Creates('SqlDatabase')
   SqlDatabase openDatabase(
       String name, String version, String displayName, int estimatedSize,
-      [DatabaseCallback creationCallback]) {
+      [DatabaseCallback? creationCallback]) {
     var db;
     if (creationCallback == null)
       db = _openDatabase(name, version, displayName, estimatedSize);
@@ -34257,7 +34175,7 @@
    */
   int get scrollX => JS<bool>('bool', '("scrollX" in #)', this)
       ? JS<num>('num', '#.scrollX', this).round()
-      : document.documentElement.scrollLeft;
+      : document.documentElement!.scrollLeft;
 
   /**
    * The distance this window has been scrolled vertically.
@@ -34271,13 +34189,15 @@
    */
   int get scrollY => JS<bool>('bool', '("scrollY" in #)', this)
       ? JS<num>('num', '#.scrollY', this).round()
-      : document.documentElement.scrollTop;
+      : document.documentElement!.scrollTop;
 }
 
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
   String _returnValue;
 
-  _BeforeUnloadEvent(Event base) : super(base);
+  _BeforeUnloadEvent(Event base)
+      : _returnValue = '',
+        super(base);
 
   String get returnValue => _returnValue;
 
@@ -34297,7 +34217,8 @@
 
   const _BeforeUnloadEventStreamProvider(this._eventType);
 
-  Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
+  Stream<BeforeUnloadEvent> forTarget(EventTarget? e,
+      {bool useCapture: false}) {
     // Specify the generic type for EventStream only in dart2js.
     var stream = new _EventStream<BeforeUnloadEvent>(e, _eventType, useCapture);
     var controller = new StreamController<BeforeUnloadEvent>(sync: true);
@@ -34463,7 +34384,7 @@
   }
 
   @JSName('postMessage')
-  void _postMessage_1(message, List<Object> transfer) native;
+  void _postMessage_1(message, List<Object>? transfer) native;
   @JSName('postMessage')
   void _postMessage_2(message) native;
 
@@ -34576,21 +34497,22 @@
 
   num get timeOrigin => JS("num", "#.timeOrigin", this);
 
-  void clearMarks(String markName) native;
+  void clearMarks(String? markName) native;
 
-  void clearMeasures(String measureName) native;
+  void clearMeasures(String? measureName) native;
 
   void clearResourceTimings() native;
 
   List<PerformanceEntry> getEntries() native;
 
-  List<PerformanceEntry> getEntriesByName(String name, String entryType) native;
+  List<PerformanceEntry> getEntriesByName(String name, String? entryType)
+      native;
 
   List<PerformanceEntry> getEntriesByType(String entryType) native;
 
   void mark(String markName) native;
 
-  void measure(String measureName, String startMark, String endMark) native;
+  void measure(String measureName, String? startMark, String? endMark) native;
 
   double now() native;
 
@@ -34695,7 +34617,7 @@
   }
 
   @JSName('lookupNamespaceURI')
-  String lookupNamespaceUri(String prefix) native;
+  String? lookupNamespaceUri(String? prefix) native;
 }
 // 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
@@ -34744,9 +34666,9 @@
 
   String get stringValue => JS("String", "#.stringValue", this);
 
-  Node iterateNext() native;
+  Node? iterateNext() native;
 
-  Node snapshotItem(int index) native;
+  Node? snapshotItem(int index) native;
 }
 // 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
@@ -34806,7 +34728,7 @@
 
   void clearParameters() native;
 
-  String getParameter(String? namespaceURI, String localName) native;
+  String? getParameter(String? namespaceURI, String localName) native;
 
   void importStylesheet(Node style) native;
 
@@ -34817,9 +34739,9 @@
   void setParameter(String? namespaceURI, String localName, String value)
       native;
 
-  Document transformToDocument(Node source) native;
+  Document? transformToDocument(Node source) native;
 
-  DocumentFragment transformToFragment(Node source, Document output) native;
+  DocumentFragment? transformToFragment(Node source, Document output) native;
 }
 // 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
@@ -34838,7 +34760,7 @@
   String get name => JS("String", "#.name", this);
 
   @JSName('namespaceURI')
-  final String? _namespaceUri;
+  String? get _namespaceUri => JS("String", "#.namespaceURI", this);
 
   String get value => JS("String", "#.value", this);
 
@@ -35045,7 +34967,7 @@
   CssRule elementAt(int index) => this[index];
   // -- end List<CssRule> mixins.
 
-  CssRule item(int index) native;
+  CssRule? item(int index) native;
 }
 // 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
@@ -35128,7 +35050,7 @@
    * Returns the intersection of this and `other`, or null if they don't
    * intersect.
    */
-  Rectangle intersection(Rectangle other) {
+  Rectangle? intersection(Rectangle other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
@@ -35345,8 +35267,8 @@
 
 @Native("GamepadList")
 class _GamepadList extends Interceptor
-    with ListMixin<Gamepad>, ImmutableListMixin<Gamepad>
-    implements List<Gamepad>, JavaScriptIndexingBehavior<Gamepad> {
+    with ListMixin<Gamepad?>, ImmutableListMixin<Gamepad?>
+    implements List<Gamepad?>, JavaScriptIndexingBehavior<Gamepad?> {
   // To suppress missing implicit constructor warnings.
   factory _GamepadList._() {
     throw new UnsupportedError("Not supported");
@@ -35354,30 +35276,30 @@
 
   int get length => JS("int", "#.length", this);
 
-  Gamepad operator [](int index) {
+  Gamepad? operator [](int index) {
     if (JS("bool", "# >>> 0 !== # || # >= #", index, index, index, length))
       throw new RangeError.index(index, this);
     return JS("Gamepad|Null", "#[#]", this, index);
   }
 
-  void operator []=(int index, Gamepad value) {
+  void operator []=(int index, Gamepad? value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
   }
-  // -- start List<Gamepad> mixins.
-  // Gamepad is the element type.
+  // -- start List<Gamepad?> mixins.
+  // Gamepad? is the element type.
 
   set length(int value) {
     throw new UnsupportedError("Cannot resize immutable List.");
   }
 
-  Gamepad get first {
+  Gamepad? get first {
     if (this.length > 0) {
       return JS('Gamepad|Null', '#[0]', this);
     }
     throw new StateError("No elements");
   }
 
-  Gamepad get last {
+  Gamepad? get last {
     int len = this.length;
     if (len > 0) {
       return JS('Gamepad|Null', '#[#]', this, len - 1);
@@ -35385,7 +35307,7 @@
     throw new StateError("No elements");
   }
 
-  Gamepad get single {
+  Gamepad? get single {
     int len = this.length;
     if (len == 1) {
       return JS('Gamepad|Null', '#[0]', this);
@@ -35394,10 +35316,10 @@
     throw new StateError("More than one element");
   }
 
-  Gamepad elementAt(int index) => this[index];
-  // -- end List<Gamepad> mixins.
+  Gamepad? elementAt(int index) => this[index];
+  // -- end List<Gamepad?> mixins.
 
-  Gamepad item(int index) native;
+  Gamepad item(int? index) native;
 }
 // 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
@@ -35413,7 +35335,7 @@
   }
 
   @JSName('item')
-  Element _item(int index) native;
+  Element _item(int? index) native;
 }
 // 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
@@ -35669,19 +35591,19 @@
   Node elementAt(int index) => this[index];
   // -- end List<Node> mixins.
 
-  _Attr getNamedItem(String name) native;
+  _Attr? getNamedItem(String name) native;
 
-  _Attr getNamedItemNS(String? namespaceURI, String localName) native;
+  _Attr? getNamedItemNS(String? namespaceURI, String localName) native;
 
-  _Attr item(int index) native;
+  _Attr? item(int index) native;
 
   _Attr removeNamedItem(String name) native;
 
   _Attr removeNamedItemNS(String? namespaceURI, String localName) native;
 
-  _Attr setNamedItem(_Attr attr) native;
+  _Attr? setNamedItem(_Attr attr) native;
 
-  _Attr setNamedItemNS(_Attr attr) native;
+  _Attr? setNamedItemNS(_Attr attr) native;
 }
 // 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
@@ -35714,7 +35636,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final ReportBody? body;
+  ReportBody? get body => JS("ReportBody", "#.body", this);
 
   String get type => JS("String", "#.type", this);
 
@@ -35925,7 +35847,7 @@
 
   CssStyleSheet __getter__(String name) native;
 
-  StyleSheet item(int index) native;
+  StyleSheet? item(int index) native;
 }
 // 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
@@ -36375,7 +36297,7 @@
   }
 
   String? operator [](Object? key) {
-    return _element.getAttribute(key as String?);
+    return _element.getAttribute(key as String);
   }
 
   void operator []=(String key, String value) {
@@ -36423,7 +36345,7 @@
   }
 
   String? operator [](Object? key) {
-    return _element.getAttributeNS(_namespace, key as String?);
+    return _element.getAttributeNS(_namespace, key as String);
   }
 
   void operator []=(String key, String value) {
diff --git a/sdk_nnbd/lib/html/html_common/conversions.dart b/sdk_nnbd/lib/html/html_common/conversions.dart
index 8801eae..a7775ed 100644
--- a/sdk_nnbd/lib/html/html_common/conversions.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Conversions for IDBKey.
 //
 // Per http://www.w3.org/TR/IndexedDB/#key-construct
diff --git a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
index 1ff21ba..c1fb0be 100644
--- a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
@@ -1,13 +1,12 @@
-// @dart = 2.5
-
 part of html_common;
 
 /// Converts a JavaScript object with properties into a Dart Map.
 /// Not suitable for nested objects.
-Map<String, dynamic> convertNativeToDart_Dictionary(object) {
+Map<String, dynamic>? convertNativeToDart_Dictionary(object) {
   if (object == null) return null;
   var dict = <String, dynamic>{};
-  var keys = JS('JSExtendableArray', 'Object.getOwnPropertyNames(#)', object);
+  var keys = JS<JSExtendableArray>(
+      'JSExtendableArray', 'Object.getOwnPropertyNames(#)', object);
   for (final key in keys) {
     dict[key] = JS('var', '#[#]', object, key);
   }
@@ -15,7 +14,7 @@
 }
 
 /// Converts a flat Dart map into a JavaScript object with properties.
-convertDartToNative_Dictionary(Map dict, [void postCreate(Object f)]) {
+convertDartToNative_Dictionary(Map? dict, [void postCreate(Object? f)?]) {
   if (dict == null) return null;
   var object = JS('var', '{}');
   if (postCreate != null) {
@@ -38,7 +37,7 @@
 }
 
 DateTime convertNativeToDart_DateTime(date) {
-  var millisSinceEpoch = JS('int', '#.getTime()', date);
+  int millisSinceEpoch = JS('int', '#.getTime()', date);
   return new DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch, isUtc: true);
 }
 
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 bda757e..3421b75 100644
--- a/sdk_nnbd/lib/html/html_common/css_class_set.dart
+++ b/sdk_nnbd/lib/html/html_common/css_class_set.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of html_common;
 
 abstract class CssClassSetImpl extends SetBase<String> implements CssClassSet {
@@ -25,7 +23,7 @@
    * If [shouldAdd] is true, then we always add that [value] to the element. If
    * [shouldAdd] is false then we always remove [value] from the element.
    */
-  bool toggle(String value, [bool shouldAdd]) {
+  bool toggle(String value, [bool? shouldAdd]) {
     _validateToken(value);
     Set<String> s = readClasses();
     bool result = false;
@@ -91,14 +89,14 @@
    * This is the Dart equivalent of jQuery's
    * [hasClass](http://api.jquery.com/hasClass/).
    */
-  bool contains(Object value) {
+  bool contains(Object? value) {
     if (value is! String) return false;
     _validateToken(value);
     return readClasses().contains(value);
   }
 
   /** Lookup from the Set interface. Not interesting for a String set. */
-  String lookup(Object value) => contains(value) ? value : null;
+  String? lookup(Object? value) => contains(value) ? value as String : null;
 
   /**
    * Add the class [value] to element.
@@ -120,9 +118,9 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  bool remove(Object value) {
-    _validateToken(value);
+  bool remove(Object? value) {
     if (value is! String) return false;
+    _validateToken(value);
     Set<String> s = readClasses();
     bool result = s.remove(value);
     writeClasses(s);
@@ -146,7 +144,7 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  void removeAll(Iterable<Object> iterable) {
+  void removeAll(Iterable<Object?> iterable) {
     modify((s) => s.removeAll(iterable));
   }
 
@@ -160,11 +158,11 @@
    * element. If [shouldAdd] is false then we always remove all the classes in
    * [iterable] from the element.
    */
-  void toggleAll(Iterable<String> iterable, [bool shouldAdd]) {
+  void toggleAll(Iterable<String> iterable, [bool? shouldAdd]) {
     iterable.forEach((e) => toggle(e, shouldAdd));
   }
 
-  void retainAll(Iterable<Object> iterable) {
+  void retainAll(Iterable<Object?> iterable) {
     modify((s) => s.retainAll(iterable));
   }
 
@@ -176,15 +174,15 @@
     modify((s) => s.retainWhere(test));
   }
 
-  bool containsAll(Iterable<Object> collection) =>
+  bool containsAll(Iterable<Object?> collection) =>
       readClasses().containsAll(collection);
 
-  Set<String> intersection(Set<Object> other) =>
+  Set<String> intersection(Set<Object?> other) =>
       readClasses().intersection(other);
 
   Set<String> union(Set<String> other) => readClasses().union(other);
 
-  Set<String> difference(Set<Object> other) => readClasses().difference(other);
+  Set<String> difference(Set<Object?> other) => readClasses().difference(other);
 
   String get first => readClasses().first;
   String get last => readClasses().last;
@@ -198,11 +196,11 @@
   Iterable<String> skip(int n) => readClasses().skip(n);
   Iterable<String> skipWhile(bool test(String value)) =>
       readClasses().skipWhile(test);
-  String firstWhere(bool test(String value), {String orElse()}) =>
+  String firstWhere(bool test(String value), {String orElse()?}) =>
       readClasses().firstWhere(test, orElse: orElse);
-  String lastWhere(bool test(String value), {String orElse()}) =>
+  String lastWhere(bool test(String value), {String orElse()?}) =>
       readClasses().lastWhere(test, orElse: orElse);
-  String singleWhere(bool test(String value), {String orElse()}) =>
+  String singleWhere(bool test(String value), {String orElse()?}) =>
       readClasses().singleWhere(test, orElse: orElse);
   String elementAt(int index) => readClasses().elementAt(index);
 
diff --git a/sdk_nnbd/lib/html/html_common/device.dart b/sdk_nnbd/lib/html/html_common/device.dart
index 1062bb6..57c37e6 100644
--- a/sdk_nnbd/lib/html/html_common/device.dart
+++ b/sdk_nnbd/lib/html/html_common/device.dart
@@ -2,21 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of html_common;
 
 /**
  * Utils for device detection.
  */
 class Device {
-  static bool _isOpera;
-  static bool _isIE;
-  static bool _isFirefox;
-  static bool _isWebKit;
-  static String _cachedCssPrefix;
-  static String _cachedPropertyPrefix;
-
   /**
    * Gets the browser's user agent. Using this function allows tests to inject
    * the user agent.
@@ -27,78 +18,33 @@
   /**
    * Determines if the current device is running Opera.
    */
-  static bool get isOpera {
-    if (_isOpera == null) {
-      _isOpera = userAgent.contains("Opera", 0);
-    }
-    return _isOpera;
-  }
+  static final bool isOpera = userAgent.contains("Opera", 0);
 
   /**
    * Determines if the current device is running Internet Explorer.
    */
-  static bool get isIE {
-    if (_isIE == null) {
-      _isIE = !isOpera && userAgent.contains("Trident/", 0);
-    }
-    return _isIE;
-  }
+  static final bool isIE = !isOpera && userAgent.contains("Trident/", 0);
 
   /**
    * Determines if the current device is running Firefox.
    */
-  static bool get isFirefox {
-    if (_isFirefox == null) {
-      _isFirefox = userAgent.contains("Firefox", 0);
-    }
-    return _isFirefox;
-  }
+  static final bool isFirefox = userAgent.contains("Firefox", 0);
 
   /**
    * Determines if the current device is running WebKit.
    */
-  static bool get isWebKit {
-    if (_isWebKit == null) {
-      _isWebKit = !isOpera && userAgent.contains("WebKit", 0);
-    }
-    return _isWebKit;
-  }
+  static final bool isWebKit = !isOpera && userAgent.contains("WebKit", 0);
 
   /**
    * Gets the CSS property prefix for the current platform.
    */
-  static String get cssPrefix {
-    String prefix = _cachedCssPrefix;
-    if (prefix != null) return prefix;
-    if (isFirefox) {
-      prefix = '-moz-';
-    } else if (isIE) {
-      prefix = '-ms-';
-    } else if (isOpera) {
-      prefix = '-o-';
-    } else {
-      prefix = '-webkit-';
-    }
-    return _cachedCssPrefix = prefix;
-  }
+  static final String cssPrefix = '-${propertyPrefix}-';
 
   /**
    * Prefix as used for JS property names.
    */
-  static String get propertyPrefix {
-    String prefix = _cachedPropertyPrefix;
-    if (prefix != null) return prefix;
-    if (isFirefox) {
-      prefix = 'moz';
-    } else if (isIE) {
-      prefix = 'ms';
-    } else if (isOpera) {
-      prefix = 'o';
-    } else {
-      prefix = 'webkit';
-    }
-    return _cachedPropertyPrefix = prefix;
-  }
+  static final String propertyPrefix =
+      isFirefox ? 'moz' : (isIE ? 'ms' : (isOpera ? 'o' : 'webkit'));
 
   /**
    * Checks to see if the event class is supported by the current platform.
diff --git a/sdk_nnbd/lib/html/html_common/filtered_element_list.dart b/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
index e3b0a3e..8bedca4 100644
--- a/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
+++ b/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of html_common;
 
 /**
@@ -64,7 +62,7 @@
     }
   }
 
-  bool contains(Object needle) {
+  bool contains(Object? needle) {
     if (needle is! Element) return false;
     Element element = needle;
     return element.parentNode == _node;
@@ -72,7 +70,7 @@
 
   Iterable<Element> get reversed => _filtered.reversed;
 
-  void sort([int compare(Element a, Element b)]) {
+  void sort([int compare(Element a, Element b)?]) {
     throw new UnsupportedError('Cannot sort filtered list');
   }
 
@@ -81,7 +79,7 @@
     throw new UnsupportedError('Cannot setRange on filtered list');
   }
 
-  void fillRange(int start, int end, [Element fillValue]) {
+  void fillRange(int start, int end, [Element? fillValue]) {
     throw new UnsupportedError('Cannot fillRange on filtered list');
   }
 
@@ -113,7 +111,7 @@
       add(value);
     } else {
       var element = _iterable.elementAt(index);
-      element.parentNode.insertBefore(value, element);
+      element.parentNode!.insertBefore(value, element);
     }
   }
 
@@ -122,7 +120,7 @@
       addAll(iterable);
     } else {
       var element = _iterable.elementAt(index);
-      element.parentNode.insertAllBefore(iterable, element);
+      element.parentNode!.insertAllBefore(iterable, element);
     }
   }
 
@@ -132,7 +130,7 @@
     return result;
   }
 
-  bool remove(Object element) {
+  bool remove(Object? element) {
     if (element is! Element) return false;
     if (contains(element)) {
       (element as Element).remove(); // Placate the type checker
diff --git a/sdk_nnbd/lib/html/html_common/html_common.dart b/sdk_nnbd/lib/html/html_common/html_common.dart
index 2dfec89..1fb9d52 100644
--- a/sdk_nnbd/lib/html/html_common/html_common.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common.dart
@@ -1,8 +1,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.
 
-// @dart = 2.5
-
 library html_common;
 
 import 'dart:async';
@@ -10,7 +8,6 @@
 import 'dart:html';
 import 'dart:js' as js;
 import 'dart:_internal' show WhereIterable;
-import 'dart:mirrors';
 import 'dart:nativewrappers';
 import 'dart:typed_data';
 import 'dart:web_gl' as gl;
diff --git a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
index 73141ac..3df2ccf 100644
--- a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 library html_common;
 
 import 'dart:async';
diff --git a/sdk_nnbd/lib/html/html_common/lists.dart b/sdk_nnbd/lib/html/html_common/lists.dart
index 5f9d86c..c7abc41 100644
--- a/sdk_nnbd/lib/html/html_common/lists.dart
+++ b/sdk_nnbd/lib/html/html_common/lists.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of html_common;
 
 class Lists {
diff --git a/sdk_nnbd/lib/html/html_common/metadata.dart b/sdk_nnbd/lib/html/html_common/metadata.dart
index f21f495..8e2f616 100644
--- a/sdk_nnbd/lib/html/html_common/metadata.dart
+++ b/sdk_nnbd/lib/html/html_common/metadata.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 library metadata;
 
 /**
@@ -25,7 +23,7 @@
 
   /// The minimum version of the browser that supports the feature, or null
   /// if supported on all versions.
-  final String minimumVersion;
+  final String? minimumVersion;
 
   const SupportedBrowser(this.browserName, [this.minimumVersion]);
 }
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 26b7a28..64eaa06 100644
--- a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -231,7 +231,7 @@
   }
 
   @JSName('continue')
-  void next([Object key]) {
+  void next([Object? key]) {
     if (key == null) {
       JS('void', '#.continue()', this);
     } else {
@@ -248,15 +248,15 @@
 
   @_annotation_Creates_IDBKey
   @_annotation_Returns_IDBKey
-  Object get key => JS("Object", "#.key", this);
+  Object? get key => JS("Object", "#.key", this);
 
   @_annotation_Creates_IDBKey
   @_annotation_Returns_IDBKey
-  Object get primaryKey => JS("Object", "#.primaryKey", this);
+  Object? get primaryKey => JS("Object", "#.primaryKey", this);
 
   @Creates('Null')
   @Returns('ObjectStore|Index|Null')
-  Object get source => JS("Object", "#.source", this);
+  Object? get source => JS("Object", "#.source", this);
 
   void advance(int count) native;
 
@@ -289,7 +289,7 @@
   @JSName('value')
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _get_value;
+  dynamic get _get_value => JS("", "#.value", this);
 }
 // 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
@@ -305,7 +305,7 @@
 @Unstable()
 @Native("IDBDatabase")
 class Database extends EventTarget {
-  ObjectStore createObjectStore(String name, {keyPath, bool autoIncrement}) {
+  ObjectStore createObjectStore(String name, {keyPath, bool? autoIncrement}) {
     var options = {};
     if (keyPath != null) {
       options['keyPath'] = keyPath;
@@ -402,7 +402,7 @@
 
   String get name => JS("String", "#.name", this);
 
-  @Returns('DomStringList|Null')
+  @Returns('DomStringList')
   @Creates('DomStringList')
   List<String> get objectStoreNames =>
       JS("DomStringList", "#.objectStoreNames", this);
@@ -470,9 +470,9 @@
   }
 
   Future<Database> open(String name,
-      {int version,
-      void onUpgradeNeeded(VersionChangeEvent event),
-      void onBlocked(Event event)}) {
+      {int? version,
+      void onUpgradeNeeded(VersionChangeEvent event)?,
+      void onBlocked(Event event)?}) {
     if ((version == null) != (onUpgradeNeeded == null)) {
       return new Future.error(new ArgumentError(
           'version and onUpgradeNeeded must be specified together'));
@@ -497,7 +497,7 @@
     }
   }
 
-  Future<IdbFactory> deleteDatabase(String name, {void onBlocked(Event e)}) {
+  Future<IdbFactory> deleteDatabase(String name, {void onBlocked(Event e)?}) {
     try {
       var request = _deleteDatabase(name);
 
@@ -601,7 +601,7 @@
    * * [ObjectStore.openCursor]
    */
   Stream<CursorWithValue> openCursor(
-      {key, KeyRange range, String direction, bool autoAdvance}) {
+      {key, KeyRange? range, String? direction, bool? autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
@@ -629,7 +629,7 @@
    * * [ObjectStore.openCursor]
    */
   Stream<Cursor> openKeyCursor(
-      {key, KeyRange range, String direction, bool autoAdvance}) {
+      {key, KeyRange? range, String? direction, bool? autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
@@ -655,7 +655,7 @@
   }
 
   @annotation_Creates_SerializedScriptValue
-  Object get keyPath => JS("Object", "#.keyPath", this);
+  Object? get keyPath => JS("Object", "#.keyPath", this);
 
   bool get multiEntry => JS("bool", "#.multiEntry", this);
 
@@ -670,7 +670,7 @@
   bool get unique => JS("bool", "#.unique", this);
 
   @JSName('count')
-  Request _count(Object key) native;
+  Request _count(Object? key) native;
 
   @JSName('get')
   @Returns('Request')
@@ -678,9 +678,9 @@
   @annotation_Creates_SerializedScriptValue
   Request _get(Object key) native;
 
-  Request getAll(Object query, [int? count]) native;
+  Request getAll(Object? query, [int? count]) native;
 
-  Request getAllKeys(Object query, [int? count]) native;
+  Request getAllKeys(Object? query, [int? count]) native;
 
   @JSName('getKey')
   @Returns('Request')
@@ -693,13 +693,13 @@
   @Returns('Request')
   @Creates('Request')
   @Creates('Cursor')
-  Request _openCursor(Object range, [String? direction]) native;
+  Request _openCursor(Object? range, [String? direction]) native;
 
   @JSName('openKeyCursor')
   @Returns('Request')
   @Creates('Request')
   @Creates('Cursor')
-  Request _openKeyCursor(Object range, [String? direction]) native;
+  Request _openKeyCursor(Object? range, [String? direction]) native;
 }
 // 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
@@ -728,12 +728,12 @@
   }
 
   @annotation_Creates_SerializedScriptValue
-  Object get lower => JS("Object", "#.lower", this);
+  Object? get lower => JS("Object", "#.lower", this);
 
   bool get lowerOpen => JS("bool", "#.lowerOpen", this);
 
   @annotation_Creates_SerializedScriptValue
-  Object get upper => JS("Object", "#.upper", this);
+  Object? get upper => JS("Object", "#.upper", this);
 
   bool get upperOpen => JS("bool", "#.upperOpen", this);
 
@@ -844,7 +844,7 @@
    * the current transaction.
    */
   Stream<CursorWithValue> openCursor(
-      {key, KeyRange range, String direction, bool autoAdvance}) {
+      {key, KeyRange? range, String? direction, bool? autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
@@ -865,7 +865,7 @@
     return _cursorStreamFromResult(request, autoAdvance);
   }
 
-  Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+  Index createIndex(String name, keyPath, {bool? unique, bool? multiEntry}) {
     var options = {};
     if (unique != null) {
       options['unique'] = unique;
@@ -884,12 +884,12 @@
 
   bool get autoIncrement => JS("bool", "#.autoIncrement", this);
 
-  @Returns('DomStringList|Null')
+  @Returns('DomStringList')
   @Creates('DomStringList')
   List<String> get indexNames => JS("DomStringList", "#.indexNames", this);
 
   @annotation_Creates_SerializedScriptValue
-  Object get keyPath => JS("Object", "#.keyPath", this);
+  Object? get keyPath => JS("Object", "#.keyPath", this);
 
   String get name => JS("String", "#.name", this);
 
@@ -927,7 +927,7 @@
   Request _clear() native;
 
   @JSName('count')
-  Request _count(Object key) native;
+  Request _count(Object? key) native;
 
   Index _createIndex(String name, Object keyPath, [Map? options]) {
     if (options != null) {
@@ -953,9 +953,9 @@
   @annotation_Creates_SerializedScriptValue
   Request _get(Object key) native;
 
-  Request getAll(Object query, [int? count]) native;
+  Request getAll(Object? query, [int? count]) native;
 
-  Request getAllKeys(Object query, [int? count]) native;
+  Request getAllKeys(Object? query, [int? count]) native;
 
   Request getKey(Object key) native;
 
@@ -965,9 +965,9 @@
   @Returns('Request')
   @Creates('Request')
   @Creates('Cursor')
-  Request _openCursor(Object range, [String? direction]) native;
+  Request _openCursor(Object? range, [String? direction]) native;
 
-  Request openKeyCursor(Object range, [String? direction]) native;
+  Request openKeyCursor(Object? range, [String? direction]) native;
 
   @Returns('Request')
   @Creates('Request')
@@ -997,7 +997,7 @@
    * Helper for iterating over cursors in a request.
    */
   static Stream<T> _cursorStreamFromResult<T extends Cursor>(
-      Request request, bool autoAdvance) {
+      Request request, bool? autoAdvance) {
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
@@ -1031,11 +1031,11 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Object get key => JS("Object", "#.key", this);
+  Object? get key => JS("Object", "#.key", this);
 
   String get type => JS("String", "#.type", this);
 
-  Object get value => JS("Object", "#.value", this);
+  Object? get value => JS("Object", "#.value", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -1079,7 +1079,7 @@
 
   Database get database => JS("Database", "#.database", this);
 
-  Object get records => JS("Object", "#.records", this);
+  Object? get records => JS("Object", "#.records", this);
 
   Transaction get transaction => JS("Transaction", "#.transaction", this);
 }
@@ -1157,10 +1157,10 @@
   dynamic get result => _convertNativeToDart_IDBAny(this._get_result);
   @JSName('result')
   @Creates('Null')
-  final dynamic _get_result;
+  dynamic get _get_result => JS("", "#.result", this);
 
   @Creates('Null')
-  Object get source => JS("Object", "#.source", this);
+  Object? get source => JS("Object", "#.source", this);
 
   Transaction get transaction => JS("Transaction", "#.transaction", this);
 
@@ -1243,7 +1243,7 @@
 
   String get mode => JS("String", "#.mode", this);
 
-  @Returns('DomStringList|Null')
+  @Returns('DomStringList')
   @Creates('DomStringList')
   List<String> get objectStoreNames =>
       JS("DomStringList", "#.objectStoreNames", this);
@@ -1294,7 +1294,7 @@
 
   @Creates('int|String|Null')
   @Returns('int|String|Null')
-  final int? newVersion;
+  int? get newVersion => JS("int", "#.newVersion", this);
 
   @Creates('int|String|Null')
   @Returns('int|String|Null')
diff --git a/sdk_nnbd/lib/io/file_impl.dart b/sdk_nnbd/lib/io/file_impl.dart
index 47593d3..e0b2d30 100644
--- a/sdk_nnbd/lib/io/file_impl.dart
+++ b/sdk_nnbd/lib/io/file_impl.dart
@@ -832,7 +832,7 @@
       return new Future.error(e);
     }
 
-    List request = new List.filled(4, null);
+    List request = new List<dynamic>.filled(4, null);
     request[0] = null;
     request[1] = result.buffer;
     request[2] = result.start;
diff --git a/sdk_nnbd/lib/io/secure_server_socket.dart b/sdk_nnbd/lib/io/secure_server_socket.dart
index c7b58f5..dbdcc28 100644
--- a/sdk_nnbd/lib/io/secure_server_socket.dart
+++ b/sdk_nnbd/lib/io/secure_server_socket.dart
@@ -67,7 +67,7 @@
    * isolates this way.
    */
   static Future<SecureServerSocket> bind(
-      address, int port, SecurityContext context,
+      address, int port, SecurityContext? context,
       {int backlog: 0,
       bool v6Only: false,
       bool requestClientCertificate: false,
@@ -124,7 +124,7 @@
   final RawServerSocket _socket;
   late StreamController<RawSecureSocket> _controller;
   StreamSubscription<RawSocket>? _subscription;
-  final SecurityContext _context;
+  final SecurityContext? _context;
   final bool requestClientCertificate;
   final bool requireClientCertificate;
   final List<String>? supportedProtocols;
@@ -195,7 +195,7 @@
    * multiple isolates this way.
    */
   static Future<RawSecureServerSocket> bind(
-      address, int port, SecurityContext context,
+      address, int port, SecurityContext? context,
       {int backlog: 0,
       bool v6Only: false,
       bool requestClientCertificate: false,
diff --git a/sdk_nnbd/lib/io/secure_socket.dart b/sdk_nnbd/lib/io/secure_socket.dart
index 2f6fc00..907a98f 100644
--- a/sdk_nnbd/lib/io/secure_socket.dart
+++ b/sdk_nnbd/lib/io/secure_socket.dart
@@ -1019,7 +1019,7 @@
 
   Future<_FilterStatus> _pushAllFilterStages() {
     bool wasInHandshake = _status != connectedStatus;
-    List args = new List.filled(2 + bufferCount * 2, null);
+    List args = new List<dynamic>.filled(2 + bufferCount * 2, null);
     args[0] = _secureFilter!._pointer();
     args[1] = wasInHandshake;
     var bufs = _secureFilter!.buffers!;
diff --git a/sdk_nnbd/lib/libraries.json b/sdk_nnbd/lib/libraries.json
index d98f2aa..a54b73f 100644
--- a/sdk_nnbd/lib/libraries.json
+++ b/sdk_nnbd/lib/libraries.json
@@ -7,71 +7,71 @@
   "vm": {
     "libraries": {
       "_builtin": {
-        "uri": "../../sdk/lib/_internal/vm/bin/builtin.dart"
+        "uri": "_internal/vm/bin/builtin.dart"
       },
       "_internal": {
-        "uri": "../../sdk/lib/internal/internal.dart",
+        "uri": "internal/internal.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/lib/internal_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/class_id_fasta.dart",
-          "../../sdk/lib/_internal/vm/lib/print_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/symbol_patch.dart",
-          "../../sdk/lib/internal/patch.dart"
+          "_internal/vm/lib/internal_patch.dart",
+          "_internal/vm/lib/class_id_fasta.dart",
+          "_internal/vm/lib/print_patch.dart",
+          "_internal/vm/lib/symbol_patch.dart",
+          "internal/patch.dart"
         ]
       },
       "async": {
-        "uri": "../../sdk/lib/async/async.dart",
+        "uri": "async/async.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/lib/async_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/timer_patch.dart"
+          "_internal/vm/lib/async_patch.dart",
+          "_internal/vm/lib/deferred_load_patch.dart",
+          "_internal/vm/lib/schedule_microtask_patch.dart",
+          "_internal/vm/lib/timer_patch.dart"
         ]
       },
       "collection": {
-        "uri": "../../sdk/lib/collection/collection.dart",
+        "uri": "collection/collection.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/lib/collection_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/compact_hash.dart"
+          "_internal/vm/lib/collection_patch.dart",
+          "_internal/vm/lib/compact_hash.dart"
         ]
       },
       "convert": {
-        "uri": "../../sdk/lib/convert/convert.dart",
-        "patches": "../../sdk/lib/_internal/vm/lib/convert_patch.dart"
+        "uri": "convert/convert.dart",
+        "patches": "_internal/vm/lib/convert_patch.dart"
       },
       "core": {
-        "uri": "../../sdk/lib/core/core.dart",
+        "uri": "core/core.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/lib/core_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/array.dart",
-          "../../sdk/lib/_internal/vm/lib/array_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/bigint_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/bool_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/date_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/double.dart",
-          "../../sdk/lib/_internal/vm/lib/double_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/errors_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/expando_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/function.dart",
-          "../../sdk/lib/_internal/vm/lib/function_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/growable_array.dart",
-          "../../sdk/lib/_internal/vm/lib/identical_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/immutable_map.dart",
-          "../../sdk/lib/_internal/vm/lib/integers.dart",
-          "../../sdk/lib/_internal/vm/lib/integers_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/lib_prefix.dart",
-          "../../sdk/lib/_internal/vm/lib/map_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/null_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/object_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/regexp_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/stacktrace.dart",
-          "../../sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/string_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/type_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/uri_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/weak_property.dart"
+          "_internal/vm/lib/core_patch.dart",
+          "_internal/vm/lib/array.dart",
+          "_internal/vm/lib/array_patch.dart",
+          "_internal/vm/lib/bigint_patch.dart",
+          "_internal/vm/lib/bool_patch.dart",
+          "_internal/vm/lib/date_patch.dart",
+          "_internal/vm/lib/double.dart",
+          "_internal/vm/lib/double_patch.dart",
+          "_internal/vm/lib/errors_patch.dart",
+          "_internal/vm/lib/expando_patch.dart",
+          "_internal/vm/lib/function.dart",
+          "_internal/vm/lib/function_patch.dart",
+          "_internal/vm/lib/growable_array.dart",
+          "_internal/vm/lib/identical_patch.dart",
+          "_internal/vm/lib/immutable_map.dart",
+          "_internal/vm/lib/integers.dart",
+          "_internal/vm/lib/integers_patch.dart",
+          "_internal/vm/lib/invocation_mirror_patch.dart",
+          "_internal/vm/lib/lib_prefix.dart",
+          "_internal/vm/lib/map_patch.dart",
+          "_internal/vm/lib/null_patch.dart",
+          "_internal/vm/lib/object_patch.dart",
+          "_internal/vm/lib/regexp_patch.dart",
+          "_internal/vm/lib/stacktrace.dart",
+          "_internal/vm/lib/stopwatch_patch.dart",
+          "_internal/vm/lib/string_buffer_patch.dart",
+          "_internal/vm/lib/string_patch.dart",
+          "_internal/vm/lib/type_patch.dart",
+          "_internal/vm/lib/uri_patch.dart",
+          "_internal/vm/lib/weak_property.dart"
         ]
       },
       "developer": {
@@ -97,25 +97,25 @@
         ]
       },
       "_http": {
-        "uri": "../../sdk/lib/_http/http.dart"
+        "uri": "_http/http.dart"
       },
       "io": {
-        "uri": "../../sdk/lib/io/io.dart",
+        "uri": "io/io.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/bin/common_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/directory_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/file_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/filter_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/io_service_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/namespace_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/platform_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/process_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/socket_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/stdio_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
-          "../../sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+          "_internal/vm/bin/common_patch.dart",
+          "_internal/vm/bin/directory_patch.dart",
+          "_internal/vm/bin/eventhandler_patch.dart",
+          "_internal/vm/bin/file_patch.dart",
+          "_internal/vm/bin/file_system_entity_patch.dart",
+          "_internal/vm/bin/filter_patch.dart",
+          "_internal/vm/bin/io_service_patch.dart",
+          "_internal/vm/bin/namespace_patch.dart",
+          "_internal/vm/bin/platform_patch.dart",
+          "_internal/vm/bin/process_patch.dart",
+          "_internal/vm/bin/socket_patch.dart",
+          "_internal/vm/bin/stdio_patch.dart",
+          "_internal/vm/bin/secure_socket_patch.dart",
+          "_internal/vm/bin/sync_socket_patch.dart"
         ]
       },
       "isolate": {
@@ -126,8 +126,8 @@
         ]
       },
       "math": {
-        "uri": "../../sdk/lib/math/math.dart",
-        "patches": "../../sdk/lib/_internal/vm/lib/math_patch.dart"
+        "uri": "math/math.dart",
+        "patches": "_internal/vm/lib/math_patch.dart"
       },
       "mirrors": {
         "uri": "mirrors/mirrors.dart",
@@ -147,8 +147,8 @@
         ]
       },
       "typed_data": {
-        "uri": "../../sdk/lib/typed_data/typed_data.dart",
-        "patches": "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+        "uri": "typed_data/typed_data.dart",
+        "patches": "_internal/vm/lib/typed_data_patch.dart"
       },
       "_vmservice": {
         "uri": "vmservice/vmservice.dart"
@@ -217,11 +217,6 @@
         "uri": "../../sdk/lib/math/math.dart",
         "patches": "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
       },
-      "mirrors": {
-        "uri": "../../sdk/lib/mirrors/mirrors.dart",
-        "patches": "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart",
-        "supported": false
-      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -327,11 +322,6 @@
         "uri": "../../sdk/lib/math/math.dart",
         "patches": "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
       },
-      "mirrors": {
-        "uri": "../../sdk/lib/mirrors/mirrors.dart",
-        "patches": "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart",
-        "supported": false
-      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -399,9 +389,6 @@
       "_js_helper": {
         "uri": "_internal/js_dev_runtime/private/js_helper.dart"
       },
-      "_js_mirrors": {
-        "uri": "_internal/js_dev_runtime/private/js_mirrors.dart"
-      },
       "_js_primitives": {
         "uri": "_internal/js_dev_runtime/private/js_primitives.dart"
       },
@@ -441,11 +428,6 @@
         "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
         "supported": false
       },
-      "mirrors": {
-        "uri": "mirrors/mirrors.dart",
-        "patches": "_internal/js_dev_runtime/patch/mirrors_patch.dart",
-        "supported": false
-      },
       "math": {
         "uri": "math/math.dart",
         "patches": "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk_nnbd/lib/libraries.yaml b/sdk_nnbd/lib/libraries.yaml
index 8d4d307..2ba3e09 100644
--- a/sdk_nnbd/lib/libraries.yaml
+++ b/sdk_nnbd/lib/libraries.yaml
@@ -17,68 +17,68 @@
 vm:
   libraries:
     _builtin:
-      uri: "../../sdk/lib/_internal/vm/bin/builtin.dart"
+      uri: "_internal/vm/bin/builtin.dart"
 
     _internal:
-      uri: "../../sdk/lib/internal/internal.dart"
+      uri: "internal/internal.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/internal_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/class_id_fasta.dart"
-        - "../../sdk/lib/_internal/vm/lib/print_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/symbol_patch.dart"
-        - "../../sdk/lib/internal/patch.dart"
+        - "_internal/vm/lib/internal_patch.dart"
+        - "_internal/vm/lib/class_id_fasta.dart"
+        - "_internal/vm/lib/print_patch.dart"
+        - "_internal/vm/lib/symbol_patch.dart"
+        - "internal/patch.dart"
 
     async:
-      uri: "../../sdk/lib/async/async.dart"
+      uri: "async/async.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/async_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/timer_patch.dart"
+        - "_internal/vm/lib/async_patch.dart"
+        - "_internal/vm/lib/deferred_load_patch.dart"
+        - "_internal/vm/lib/schedule_microtask_patch.dart"
+        - "_internal/vm/lib/timer_patch.dart"
 
     collection:
-      uri: "../../sdk/lib/collection/collection.dart"
+      uri: "collection/collection.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/collection_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/compact_hash.dart"
+        - "_internal/vm/lib/collection_patch.dart"
+        - "_internal/vm/lib/compact_hash.dart"
 
     convert:
-      uri: "../../sdk/lib/convert/convert.dart"
-      patches: "../../sdk/lib/_internal/vm/lib/convert_patch.dart"
+      uri: "convert/convert.dart"
+      patches: "_internal/vm/lib/convert_patch.dart"
 
     core:
-      uri: "../../sdk/lib/core/core.dart"
+      uri: "core/core.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/core_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/array.dart"
-        - "../../sdk/lib/_internal/vm/lib/array_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/bigint_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/bool_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/date_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/double.dart"
-        - "../../sdk/lib/_internal/vm/lib/double_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/errors_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/expando_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/function.dart"
-        - "../../sdk/lib/_internal/vm/lib/function_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/growable_array.dart"
-        - "../../sdk/lib/_internal/vm/lib/identical_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/immutable_map.dart"
-        - "../../sdk/lib/_internal/vm/lib/integers.dart"
-        - "../../sdk/lib/_internal/vm/lib/integers_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/lib_prefix.dart"
-        - "../../sdk/lib/_internal/vm/lib/map_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/null_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/object_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/regexp_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/stacktrace.dart"
-        - "../../sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/string_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/type_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/uri_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/weak_property.dart"
+        - "_internal/vm/lib/core_patch.dart"
+        - "_internal/vm/lib/array.dart"
+        - "_internal/vm/lib/array_patch.dart"
+        - "_internal/vm/lib/bigint_patch.dart"
+        - "_internal/vm/lib/bool_patch.dart"
+        - "_internal/vm/lib/date_patch.dart"
+        - "_internal/vm/lib/double.dart"
+        - "_internal/vm/lib/double_patch.dart"
+        - "_internal/vm/lib/errors_patch.dart"
+        - "_internal/vm/lib/expando_patch.dart"
+        - "_internal/vm/lib/function.dart"
+        - "_internal/vm/lib/function_patch.dart"
+        - "_internal/vm/lib/growable_array.dart"
+        - "_internal/vm/lib/identical_patch.dart"
+        - "_internal/vm/lib/immutable_map.dart"
+        - "_internal/vm/lib/integers.dart"
+        - "_internal/vm/lib/integers_patch.dart"
+        - "_internal/vm/lib/invocation_mirror_patch.dart"
+        - "_internal/vm/lib/lib_prefix.dart"
+        - "_internal/vm/lib/map_patch.dart"
+        - "_internal/vm/lib/null_patch.dart"
+        - "_internal/vm/lib/object_patch.dart"
+        - "_internal/vm/lib/regexp_patch.dart"
+        - "_internal/vm/lib/stacktrace.dart"
+        - "_internal/vm/lib/stopwatch_patch.dart"
+        - "_internal/vm/lib/string_buffer_patch.dart"
+        - "_internal/vm/lib/string_patch.dart"
+        - "_internal/vm/lib/type_patch.dart"
+        - "_internal/vm/lib/uri_patch.dart"
+        - "_internal/vm/lib/weak_property.dart"
 
     developer:
       uri: "developer/developer.dart"
@@ -100,25 +100,25 @@
         - "_internal/vm/lib/wasm_patch.dart"
 
     _http:
-      uri: "../../sdk/lib/_http/http.dart"
+      uri: "_http/http.dart"
 
     io:
-      uri: "../../sdk/lib/io/io.dart"
+      uri: "io/io.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/bin/common_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/directory_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/file_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/filter_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/io_service_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/namespace_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/platform_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/process_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/socket_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/stdio_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
-        - "../../sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+        - "_internal/vm/bin/common_patch.dart"
+        - "_internal/vm/bin/directory_patch.dart"
+        - "_internal/vm/bin/eventhandler_patch.dart"
+        - "_internal/vm/bin/file_patch.dart"
+        - "_internal/vm/bin/file_system_entity_patch.dart"
+        - "_internal/vm/bin/filter_patch.dart"
+        - "_internal/vm/bin/io_service_patch.dart"
+        - "_internal/vm/bin/namespace_patch.dart"
+        - "_internal/vm/bin/platform_patch.dart"
+        - "_internal/vm/bin/process_patch.dart"
+        - "_internal/vm/bin/socket_patch.dart"
+        - "_internal/vm/bin/stdio_patch.dart"
+        - "_internal/vm/bin/secure_socket_patch.dart"
+        - "_internal/vm/bin/sync_socket_patch.dart"
 
     isolate:
       uri: "isolate/isolate.dart"
@@ -127,8 +127,8 @@
         - "_internal/vm/lib/timer_impl.dart"
 
     math:
-      uri: "../../sdk/lib/math/math.dart"
-      patches: "../../sdk/lib/_internal/vm/lib/math_patch.dart"
+      uri: "math/math.dart"
+      patches: "_internal/vm/lib/math_patch.dart"
 
     mirrors:
       uri: "mirrors/mirrors.dart"
@@ -146,8 +146,8 @@
         - "_internal/vm/bin/cli_patch.dart"
 
     typed_data:
-      uri: "../../sdk/lib/typed_data/typed_data.dart"
-      patches: "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+      uri: "typed_data/typed_data.dart"
+      patches: "_internal/vm/lib/typed_data_patch.dart"
 
     _vmservice:
       uri: "vmservice/vmservice.dart"
@@ -214,11 +214,6 @@
       uri: "../../sdk/lib/math/math.dart"
       patches: "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
 
-    mirrors:
-      uri: "../../sdk/lib/mirrors/mirrors.dart"
-      patches: "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart"
-      supported: false
-
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -322,11 +317,6 @@
       uri: "../../sdk/lib/math/math.dart"
       patches: "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
 
-    mirrors:
-      uri: "../../sdk/lib/mirrors/mirrors.dart"
-      patches: "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart"
-      supported: false
-
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -392,9 +382,6 @@
       _js_helper:
         uri: "_internal/js_dev_runtime/private/js_helper.dart"
 
-      _js_mirrors:
-        uri: "_internal/js_dev_runtime/private/js_mirrors.dart"
-
       _js_primitives:
         uri: "_internal/js_dev_runtime/private/js_primitives.dart"
 
@@ -434,11 +421,6 @@
         patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
         supported: false
 
-      mirrors:
-        uri: "mirrors/mirrors.dart"
-        patches: "_internal/js_dev_runtime/patch/mirrors_patch.dart"
-        supported: false
-
       math:
         uri: "math/math.dart"
         patches: "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk_nnbd/lib/mirrors/mirrors.dart b/sdk_nnbd/lib/mirrors/mirrors.dart
index 573548e..9b7d454 100644
--- a/sdk_nnbd/lib/mirrors/mirrors.dart
+++ b/sdk_nnbd/lib/mirrors/mirrors.dart
@@ -58,6 +58,7 @@
 library dart.mirrors;
 
 import 'dart:async' show Future;
+import "dart:_internal" show Since;
 
 /**
  * A [MirrorSystem] is the main interface used to reflect on a set of
@@ -109,6 +110,12 @@
   TypeMirror get voidType;
 
   /**
+   * A mirror on the [:Never:] type.
+   */
+  @Since("2.8")
+  TypeMirror get neverType;
+
+  /**
    * Returns the name of [symbol].
    *
    * The following text is non-normative:
diff --git a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
index 792a63a..3a87ae9 100644
--- a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
@@ -1839,15 +1839,15 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final AnimatedLength height;
+  AnimatedLength get height => JS("AnimatedLength", "#.height", this);
 
-  final AnimatedString result;
+  AnimatedString get result => JS("AnimatedString", "#.result", this);
 
-  final AnimatedLength width;
+  AnimatedLength get width => JS("AnimatedLength", "#.width", this);
 
-  final AnimatedLength x;
+  AnimatedLength get x => JS("AnimatedLength", "#.x", this);
 
-  final AnimatedLength y;
+  AnimatedLength get y => JS("AnimatedLength", "#.y", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -1860,9 +1860,10 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final AnimatedPreserveAspectRatio preserveAspectRatio;
+  AnimatedPreserveAspectRatio get preserveAspectRatio =>
+      JS("AnimatedPreserveAspectRatio", "#.preserveAspectRatio", this);
 
-  final AnimatedRect viewBox;
+  AnimatedRect get viewBox => JS("AnimatedRect", "#.viewBox", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3054,7 +3055,7 @@
     JS("void", "#.media = #", this, value);
   }
 
-  final StyleSheet? sheet;
+  StyleSheet? get sheet => JS("StyleSheet", "#.sheet", this);
 
   // Use implementation from Element.
   // final String title;
@@ -3104,16 +3105,16 @@
   static final _START_TAG_REGEXP = new RegExp('<(\\w+)');
 
   factory SvgElement.tag(String tag) =>
-      document.createElementNS("http://www.w3.org/2000/svg", tag);
+      document.createElementNS("http://www.w3.org/2000/svg", tag) as SvgElement;
   factory SvgElement.svg(String svg,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (validator == null && treeSanitizer == null) {
       validator = new NodeValidatorBuilder.common()..allowSvg();
     }
 
     final match = _START_TAG_REGEXP.firstMatch(svg);
     var parentElement;
-    if (match != null && match.group(1).toLowerCase() == 'svg') {
+    if (match != null && match.group(1)!.toLowerCase() == 'svg') {
       parentElement = document.body;
     } else {
       parentElement = new SvgSvgElement();
@@ -3135,14 +3136,14 @@
 
   String get outerHtml {
     final container = new DivElement();
-    final SvgElement cloned = this.clone(true);
+    final SvgElement cloned = this.clone(true) as SvgElement;
     container.children.add(cloned);
     return container.innerHtml;
   }
 
   String get innerHtml {
     final container = new DivElement();
-    final SvgElement cloned = this.clone(true);
+    final SvgElement cloned = this.clone(true) as SvgElement;
     container.children.addAll(cloned.children);
     return container.innerHtml;
   }
@@ -3152,7 +3153,7 @@
   }
 
   DocumentFragment createFragment(String svg,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     if (treeSanitizer == null) {
       if (validator == null) {
         validator = new NodeValidatorBuilder.common()..allowSvg();
@@ -3169,7 +3170,7 @@
     // The root is the <svg/> element, need to pull out the contents.
     var root = fragment.nodes.single;
     while (root.firstChild != null) {
-      svgFragment.append(root.firstChild);
+      svgFragment.append(root.firstChild!);
     }
     return svgFragment;
   }
@@ -3181,7 +3182,7 @@
   }
 
   void insertAdjacentHtml(String where, String text,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator? validator, NodeTreeSanitizer? treeSanitizer}) {
     throw new UnsupportedError("Cannot invoke insertAdjacentHtml on SVG.");
   }
 
@@ -3396,7 +3397,8 @@
   AnimatedString get _svgClassName => JS("AnimatedString", "#.className", this);
 
   @JSName('ownerSVGElement')
-  final SvgSvgElement? ownerSvgElement;
+  SvgSvgElement? get ownerSvgElement =>
+      JS("SvgSvgElement", "#.ownerSVGElement", this);
 
   // Use implementation from Element.
   // final CssStyleDeclaration style;
@@ -3404,7 +3406,8 @@
   // Use implementation from Element.
   // final int tabIndex;
 
-  final SvgElement? viewportElement;
+  SvgElement? get viewportElement =>
+      JS("SvgElement", "#.viewportElement", this);
 
   void blur() native;
 
@@ -3554,7 +3557,7 @@
     final el = new SvgElement.tag("svg");
     // The SVG spec requires the version attribute to match the spec version
     el.attributes['version'] = "1.1";
-    return el;
+    return el as SvgSvgElement;
   }
 
   // To suppress missing implicit constructor warnings.
@@ -3622,11 +3625,11 @@
 
   Element getElementById(String elementId) native;
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getEnclosureList(Rect rect, SvgElement? referenceElement) native;
 
-  @Returns('NodeList|Null')
+  @Returns('NodeList')
   @Creates('NodeList')
   List<Node> getIntersectionList(Rect rect, SvgElement? referenceElement)
       native;
@@ -3741,9 +3744,10 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final StringList requiredExtensions;
+  StringList get requiredExtensions =>
+      JS("StringList", "#.requiredExtensions", this);
 
-  final StringList systemLanguage;
+  StringList get systemLanguage => JS("StringList", "#.systemLanguage", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -4014,7 +4018,7 @@
 
   void clear() native;
 
-  Transform consolidate() native;
+  Transform? consolidate() native;
 
   @JSName('createSVGTransformFromMatrix')
   Transform createSvgTransformFromMatrix(Matrix matrix) native;
@@ -4058,7 +4062,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  final AnimatedString href;
+  AnimatedString get href => JS("AnimatedString", "#.href", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/sdk_nnbd/lib/vmservice/asset.dart b/sdk_nnbd/lib/vmservice/asset.dart
index ac88aa7..a29984e 100644
--- a/sdk_nnbd/lib/vmservice/asset.dart
+++ b/sdk_nnbd/lib/vmservice/asset.dart
@@ -43,6 +43,7 @@
       return null;
     }
     List assetList = _decodeAssets(tarBytes);
+    Map<String, Asset> assets = new HashMap<String, Asset>();
     for (int i = 0; i < assetList.length; i += 2) {
       final a = Asset(assetList[i], assetList[i + 1]);
       assets[a.name] = a;
diff --git a/sdk_nnbd/lib/vmservice/message.dart b/sdk_nnbd/lib/vmservice/message.dart
index 31275b4..ee29fe3 100644
--- a/sdk_nnbd/lib/vmservice/message.dart
+++ b/sdk_nnbd/lib/vmservice/message.dart
@@ -147,9 +147,13 @@
   // elements in the list are strings, making consumption by C++ simpler.
   // This has a side effect that boolean literal values like true become 'true'
   // and thus indistinguishable from the string literal 'true'.
-  List<String> _makeAllString(List list) => <String>[
-        for (final e in list) e.toString(),
-      ];
+  List<String> _makeAllString(List list) {
+    var new_list = List<String>.filled(list.length, "");
+    for (var i = 0; i < list.length; i++) {
+      new_list[i] = list[i].toString();
+    }
+    return new_list;
+  }
 
   Future<Response> sendToIsolate(SendPort sendPort) {
     final receivePort = RawReceivePort();
diff --git a/sdk_nnbd/lib/vmservice/running_isolates.dart b/sdk_nnbd/lib/vmservice/running_isolates.dart
index 629d9c7..a17b889 100644
--- a/sdk_nnbd/lib/vmservice/running_isolates.dart
+++ b/sdk_nnbd/lib/vmservice/running_isolates.dart
@@ -120,7 +120,7 @@
     Client? externalClient =
         _service._findFirstClientThatHandlesService('compileExpression');
 
-    final compileParams = <String, String>{
+    final compileParams = <String, dynamic>{
       'isolateId': _message.params['isolateId']!,
       'expression': _message.params['expression']!,
       'definitions': buildScopeResponseResult['param_names']!,
diff --git a/sdk_nnbd/lib/vmservice/vmservice.dart b/sdk_nnbd/lib/vmservice/vmservice.dart
index 41833ba..f5a176e 100644
--- a/sdk_nnbd/lib/vmservice/vmservice.dart
+++ b/sdk_nnbd/lib/vmservice/vmservice.dart
@@ -163,10 +163,10 @@
 typedef Future<Uri> ServerInformamessage_routertionCallback();
 
 /// Called when we need information about the server.
-typedef Future<Uri> ServerInformationCallback();
+typedef Uri? ServerInformationCallback();
 
 /// Called when we want to [enable] or disable the web server.
-typedef Future<Uri> WebServerControlCallback(bool enable);
+typedef Future<Uri?> WebServerControlCallback(bool enable);
 
 /// Hooks that are setup by the embedder.
 class VMServiceEmbedderHooks {
diff --git a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
index 370361b..8021d08 100644
--- a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -194,7 +194,7 @@
   Future close() => promiseToFuture(JS("", "#.close()", this));
 
   Map getOutputTimestamp() {
-    return convertNativeToDart_Dictionary(_getOutputTimestamp_1());
+    return convertNativeToDart_Dictionary(_getOutputTimestamp_1())!;
   }
 
   @JSName('getOutputTimestamp')
@@ -238,9 +238,9 @@
   }
 
   @JSName('decodeAudioData')
-  Future _decodeAudioData(ByteBuffer audioData,
-      [DecodeSuccessCallback successCallback,
-      DecodeErrorCallback errorCallback]) native;
+  Future<AudioBuffer> _decodeAudioData(ByteBuffer audioData,
+      [DecodeSuccessCallback? successCallback,
+      DecodeErrorCallback? errorCallback]) native;
 
   Future<AudioBuffer> decodeAudioData(ByteBuffer audioData,
       [DecodeSuccessCallback? successCallback,
@@ -406,7 +406,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Map _getItem(String key) =>
+  Map? _getItem(String key) =>
       convertNativeToDart_Dictionary(JS('', '#.get(#)', this, key));
 
   void addAll(Map<String, dynamic> other) {
@@ -417,7 +417,7 @@
 
   bool containsKey(dynamic key) => _getItem(key) != null;
 
-  Map operator [](dynamic key) => _getItem(key);
+  Map? operator [](dynamic key) => _getItem(key);
 
   void forEach(void f(String key, dynamic value)) {
     var entries = JS('', '#.entries()', this);
@@ -536,7 +536,7 @@
 
   String get language => JS("String", "#.language", this);
 
-  final SourceBuffer? sourceBuffer;
+  SourceBuffer? get sourceBuffer => JS("SourceBuffer", "#.sourceBuffer", this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -556,7 +556,7 @@
 
   AudioTrack __getter__(int index) native;
 
-  AudioTrack getTrackById(String id) native;
+  AudioTrack? getTrackById(String id) native;
 
   Stream<Event> get onChange => changeEvent.forTarget(this);
 }
diff --git a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
index f47047a..424c29e 100644
--- a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -340,7 +340,7 @@
     throw new UnsupportedError("Not supported");
   }
 
-  String getTranslatedShaderSource(Shader shader) native;
+  String? getTranslatedShaderSource(Shader shader) native;
 }
 // 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
@@ -463,10 +463,10 @@
   void endQueryExt(int target) native;
 
   @JSName('getQueryEXT')
-  Object getQueryExt(int target, int pname) native;
+  Object? getQueryExt(int target, int pname) native;
 
   @JSName('getQueryObjectEXT')
-  Object getQueryObjectExt(TimerQueryExt query, int pname) native;
+  Object? getQueryObjectExt(TimerQueryExt query, int pname) native;
 
   @JSName('isQueryEXT')
   bool isQueryExt(TimerQueryExt? query) native;
@@ -852,16 +852,16 @@
 
   ActiveInfo getActiveUniform(Program program, int index) native;
 
-  List<Shader> getAttachedShaders(Program program) native;
+  List<Shader>? getAttachedShaders(Program program) native;
 
   int getAttribLocation(Program program, String name) native;
 
   @Creates('int|Null')
   @Returns('int|Null')
-  Object getBufferParameter(int target, int pname) native;
+  Object? getBufferParameter(int target, int pname) native;
 
   @Creates('ContextAttributes|Null')
-  Map getContextAttributes() {
+  Map? getContextAttributes() {
     return convertNativeToDart_Dictionary(_getContextAttributes_1());
   }
 
@@ -871,57 +871,57 @@
 
   int getError() native;
 
-  Object getExtension(String name) native;
+  Object? getExtension(String name) native;
 
   @Creates('int|Renderbuffer|Texture|Null')
   @Returns('int|Renderbuffer|Texture|Null')
-  Object getFramebufferAttachmentParameter(
+  Object? getFramebufferAttachmentParameter(
       int target, int attachment, int pname) native;
 
   @Creates(
       'Null|num|String|bool|JSExtendableArray|NativeFloat32List|NativeInt32List|NativeUint32List|Framebuffer|Renderbuffer|Texture')
   @Returns(
       'Null|num|String|bool|JSExtendableArray|NativeFloat32List|NativeInt32List|NativeUint32List|Framebuffer|Renderbuffer|Texture')
-  Object getParameter(int pname) native;
+  Object? getParameter(int pname) native;
 
-  String getProgramInfoLog(Program program) native;
+  String? getProgramInfoLog(Program program) native;
 
   @Creates('int|bool|Null')
   @Returns('int|bool|Null')
-  Object getProgramParameter(Program program, int pname) native;
+  Object? getProgramParameter(Program program, int pname) native;
 
   @Creates('int|Null')
   @Returns('int|Null')
-  Object getRenderbufferParameter(int target, int pname) native;
+  Object? getRenderbufferParameter(int target, int pname) native;
 
-  String getShaderInfoLog(Shader shader) native;
+  String? getShaderInfoLog(Shader shader) native;
 
   @Creates('int|bool|Null')
   @Returns('int|bool|Null')
-  Object getShaderParameter(Shader shader, int pname) native;
+  Object? getShaderParameter(Shader shader, int pname) native;
 
   ShaderPrecisionFormat getShaderPrecisionFormat(
       int shadertype, int precisiontype) native;
 
-  String getShaderSource(Shader shader) native;
+  String? getShaderSource(Shader shader) native;
 
-  List<String> getSupportedExtensions() native;
+  List<String>? getSupportedExtensions() native;
 
   @Creates('int|Null')
   @Returns('int|Null')
-  Object getTexParameter(int target, int pname) native;
+  Object? getTexParameter(int target, int pname) native;
 
   @Creates(
       'Null|num|String|bool|JSExtendableArray|NativeFloat32List|NativeInt32List|NativeUint32List')
   @Returns(
       'Null|num|String|bool|JSExtendableArray|NativeFloat32List|NativeInt32List|NativeUint32List')
-  Object getUniform(Program program, UniformLocation location) native;
+  Object? getUniform(Program program, UniformLocation location) native;
 
   UniformLocation getUniformLocation(Program program, String name) native;
 
   @Creates('Null|num|bool|NativeFloat32List|Buffer')
   @Returns('Null|num|bool|NativeFloat32List|Buffer')
-  Object getVertexAttrib(int index, int pname) native;
+  Object? getVertexAttrib(int index, int pname) native;
 
   int getVertexAttribOffset(int index, int pname) native;
 
@@ -1465,13 +1465,13 @@
   void copyTexSubImage3D(int target, int level, int xoffset, int yoffset,
       int zoffset, int x, int y, int width, int height) native;
 
-  Query createQuery() native;
+  Query? createQuery() native;
 
-  Sampler createSampler() native;
+  Sampler? createSampler() native;
 
-  TransformFeedback createTransformFeedback() native;
+  TransformFeedback? createTransformFeedback() native;
 
-  VertexArrayObject createVertexArray() native;
+  VertexArrayObject? createVertexArray() native;
 
   void deleteQuery(Query? query) native;
 
@@ -1498,49 +1498,49 @@
 
   void endTransformFeedback() native;
 
-  Sync fenceSync(int condition, int flags) native;
+  Sync? fenceSync(int condition, int flags) native;
 
   void framebufferTextureLayer(int target, int attachment, Texture? texture,
       int level, int layer) native;
 
-  String getActiveUniformBlockName(Program program, int uniformBlockIndex)
+  String? getActiveUniformBlockName(Program program, int uniformBlockIndex)
       native;
 
-  Object getActiveUniformBlockParameter(
+  Object? getActiveUniformBlockParameter(
       Program program, int uniformBlockIndex, int pname) native;
 
-  Object getActiveUniforms(Program program, List<int> uniformIndices, int pname)
-      native;
+  Object? getActiveUniforms(
+      Program program, List<int> uniformIndices, int pname) native;
 
   void getBufferSubData(int target, int srcByteOffset, TypedData dstData,
       [int? dstOffset, int? length]) native;
 
   int getFragDataLocation(Program program, String name) native;
 
-  Object getIndexedParameter(int target, int index) native;
+  Object? getIndexedParameter(int target, int index) native;
 
-  Object getInternalformatParameter(int target, int internalformat, int pname)
+  Object? getInternalformatParameter(int target, int internalformat, int pname)
       native;
 
-  Object getQuery(int target, int pname) native;
+  Object? getQuery(int target, int pname) native;
 
-  Object getQueryParameter(Query query, int pname) native;
+  Object? getQueryParameter(Query query, int pname) native;
 
-  Object getSamplerParameter(Sampler sampler, int pname) native;
+  Object? getSamplerParameter(Sampler sampler, int pname) native;
 
-  Object getSyncParameter(Sync sync, int pname) native;
+  Object? getSyncParameter(Sync sync, int pname) native;
 
-  ActiveInfo getTransformFeedbackVarying(Program program, int index) native;
+  ActiveInfo? getTransformFeedbackVarying(Program program, int index) native;
 
   int getUniformBlockIndex(Program program, String uniformBlockName) native;
 
-  List<int> getUniformIndices(Program program, List<String> uniformNames) {
+  List<int>? getUniformIndices(Program program, List<String> uniformNames) {
     List uniformNames_1 = convertDartToNative_StringArray(uniformNames);
     return _getUniformIndices_1(program, uniformNames_1);
   }
 
   @JSName('getUniformIndices')
-  List<int> _getUniformIndices_1(Program program, List uniformNames) native;
+  List<int>? _getUniformIndices_1(Program program, List uniformNames) native;
 
   void invalidateFramebuffer(int target, List<int> attachments) native;
 
@@ -2429,13 +2429,13 @@
 
   ActiveInfo getActiveUniform(Program program, int index) native;
 
-  List<Shader> getAttachedShaders(Program program) native;
+  List<Shader>? getAttachedShaders(Program program) native;
 
   int getAttribLocation(Program program, String name) native;
 
-  Object getBufferParameter(int target, int pname) native;
+  Object? getBufferParameter(int target, int pname) native;
 
-  Map getContextAttributes() {
+  Map? getContextAttributes() {
     return convertNativeToDart_Dictionary(_getContextAttributes_1());
   }
 
@@ -2444,37 +2444,37 @@
 
   int getError() native;
 
-  Object getExtension(String name) native;
+  Object? getExtension(String name) native;
 
-  Object getFramebufferAttachmentParameter(
+  Object? getFramebufferAttachmentParameter(
       int target, int attachment, int pname) native;
 
-  Object getParameter(int pname) native;
+  Object? getParameter(int pname) native;
 
-  String getProgramInfoLog(Program program) native;
+  String? getProgramInfoLog(Program program) native;
 
-  Object getProgramParameter(Program program, int pname) native;
+  Object? getProgramParameter(Program program, int pname) native;
 
-  Object getRenderbufferParameter(int target, int pname) native;
+  Object? getRenderbufferParameter(int target, int pname) native;
 
-  String getShaderInfoLog(Shader shader) native;
+  String? getShaderInfoLog(Shader shader) native;
 
-  Object getShaderParameter(Shader shader, int pname) native;
+  Object? getShaderParameter(Shader shader, int pname) native;
 
   ShaderPrecisionFormat getShaderPrecisionFormat(
       int shadertype, int precisiontype) native;
 
-  String getShaderSource(Shader shader) native;
+  String? getShaderSource(Shader shader) native;
 
-  List<String> getSupportedExtensions() native;
+  List<String>? getSupportedExtensions() native;
 
-  Object getTexParameter(int target, int pname) native;
+  Object? getTexParameter(int target, int pname) native;
 
-  Object getUniform(Program program, UniformLocation location) native;
+  Object? getUniform(Program program, UniformLocation location) native;
 
   UniformLocation getUniformLocation(Program program, String name) native;
 
-  Object getVertexAttrib(int index, int pname) native;
+  Object? getVertexAttrib(int index, int pname) native;
 
   int getVertexAttribOffset(int index, int pname) native;
 
diff --git a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
index 53f192b..fde77d8 100644
--- a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -30,7 +30,8 @@
         Creates,
         JSName,
         Native,
-        JavaScriptIndexingBehavior;
+        JavaScriptIndexingBehavior,
+        Returns;
 
 // 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
@@ -223,7 +224,7 @@
   Map operator [](int index) {
     if (JS("bool", "# >>> 0 !== # || # >= #", index, index, index, length))
       throw new RangeError.index(index, this);
-    return this.item(index);
+    return this.item(index)!;
   }
 
   void operator []=(int index, Map value) {
@@ -263,7 +264,7 @@
   Map elementAt(int index) => this[index];
   // -- end List<Map> mixins.
 
-  Map item(int index) {
+  Map? item(int index) {
     return convertNativeToDart_Dictionary(_item_1(index));
   }
 
diff --git a/tests/.dart_tool/package_config.json b/tests/.dart_tool/package_config.json
new file mode 100644
index 0000000..f710103
--- /dev/null
+++ b/tests/.dart_tool/package_config.json
@@ -0,0 +1,167 @@
+{
+  "configVersion": 2,
+  "comment": [
+    "This file tells each Dart implementation to treat the test subdirectories",
+    "as 'packages' so that we can set the default language version for each",
+    "directory. That in turn lets us treat the legacy tests as opted out of",
+    "NNBD without having to put a version comment in every single file."
+  ],
+  "packages": [
+    {
+      "name": "co19_2",
+      "rootUri": "../co19_2/",
+      "languageVersion": "2.7"
+    },
+    {
+      "name": "corelib_2",
+      "rootUri": "../corelib_2/",
+      "languageVersion": "2.7"
+    },
+    {
+      "name": "ffi_2",
+      "rootUri": "../ffi_2/",
+      "languageVersion": "2.7"
+    },
+    {
+      "name": "language_2",
+      "rootUri": "../language_2/",
+      "languageVersion": "2.7"
+    },
+    {
+      "name": "lib_2",
+      "rootUri": "../lib_2/",
+      "languageVersion": "2.7"
+    },
+    {
+      "name": "standalone_2",
+      "rootUri": "../standalone_2/",
+      "languageVersion": "2.7"
+    },
+
+    {
+      "name": "_fe_analyzer_shared",
+      "rootUri": "../../pkg/_fe_analyzer_shared/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "args",
+      "rootUri": "../../third_party/pkg/args/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "async_helper",
+      "rootUri": "../../pkg/async_helper/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "collection",
+      "rootUri": "../../third_party/pkg/collection/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "compiler",
+      "rootUri": "../../pkg/compiler/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "convert",
+      "rootUri": "../../third_party/pkg/convert/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "crypto",
+      "rootUri": "../../third_party/pkg/crypto/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "dart2js_info",
+      "rootUri": "../../third_party/pkg/dart2js_info/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "dart2js_tools",
+      "rootUri": "../../pkg/dart2js_tools/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "dart_internal",
+      "rootUri": "../../pkg/dart_internal/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "expect",
+      "rootUri": "../../pkg/expect/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "ffi",
+      "rootUri": "../../third_party/pkg/ffi/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "front_end",
+      "rootUri": "../../pkg/front_end/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "http",
+      "rootUri": "../../third_party/pkg/http/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "js",
+      "rootUri": "../../pkg/js/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "js_ast",
+      "rootUri": "../../pkg/js_ast/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "kernel",
+      "rootUri": "../../pkg/kernel/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "meta",
+      "rootUri": "../../pkg/meta/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "native_stack_traces",
+      "rootUri": "../../pkg/native_stack_traces/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "path",
+      "rootUri": "../../third_party/pkg/path/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "source_maps",
+      "rootUri": "../../third_party/pkg/source_maps/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "sourcemap_testing",
+      "rootUri": "../../pkg/sourcemap_testing/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "test",
+      "rootUri": "../../third_party/pkg/test/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "testing",
+      "rootUri": "../../pkg/testing/lib",
+      "language": "2.7"
+    },
+    {
+      "name": "unittest",
+      "rootUri": "../../pkg/unittest/lib",
+      "language": "2.7"
+    }
+  ]
+}
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index df64c4a..2bb6211 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -2,6 +2,15 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+[ $compiler == dart2js ]
+Language/Expressions/Null/instance_of_class_null_t01: Skip # dart:mirrors not supported https://github.com/dart-lang/co19/issues/522.
+Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
+Language/Metadata/before*: Skip # dart:mirrors not supported https://github.com/dart-lang/co19/issues/523.
+LayoutTests/*: Skip # These tests are going to be removed.
+LibTest/io/*: SkipByDesign # dart:io not supported.
+LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
+WebPlatformTest/*: Skip # These tests are going to be removed.
+
 [ $compiler == dart2js && $runtime == d8 ]
 LayoutTests/*: SkipByDesign # d8 is not a browser
 LibTest/html/*: SkipByDesign # d8 is not a browser
@@ -27,10 +36,3 @@
 LibTest/core/List/List_class_A01_t04: SkipSlow # slow babeljs transformation
 LibTest/core/List/List_class_A01_t05: SkipSlow # slow babeljs transformation
 LibTest/core/List/List_class_A01_t06: SkipSlow # slow babeljs transformation
-
-[ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
-Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
-LayoutTests/*: Skip # These tests are going to be removed.
-LibTest/io/*: SkipByDesign # dart:io not supported.
-LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
-WebPlatformTest/*: Skip # These tests are going to be removed.
diff --git a/tests/co19_2/co19_2-dartdevc.status b/tests/co19_2/co19_2-dartdevc.status
index 2219172..b204630 100644
--- a/tests/co19_2/co19_2-dartdevc.status
+++ b/tests/co19_2/co19_2-dartdevc.status
@@ -2,9 +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.
 
-[ $compiler == dartdevc ]
-LanguageFeatures/Extension-methods/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing extension methods.
-
 [ $compiler == dartdevc || $compiler == dartdevk ]
 Language/Classes/Constructors/Generative_Constructors/formal_parameter_t07: Skip # Times out
 Language/Classes/Constructors/Generative_Constructors/fresh_instance_t01: Skip # Times out
@@ -57,237 +54,12 @@
 Language/Classes/Setters/instance_setter_t01: Skip # Times out
 Language/Expressions/Function_Invocation/async_generator_invokation_t08: Skip # Times out
 Language/Expressions/Function_Invocation/async_generator_invokation_t10: Skip # Times out
+Language/Expressions/Null/instance_of_class_null_t01: Skip # dart:mirrors not supported https://github.com/dart-lang/co19/issues/522.
+Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign # dart:isolate not supported.
+Language/Metadata/before*: Skip # dart:mirrors not supported https://github.com/dart-lang/co19/issues/523.
 Language/Types/Interface_Types/subtype_t27: Skip # Times out
 Language/Types/Interface_Types/subtype_t28: Skip # Times out
-LayoutTests/fast/backgrounds/001_t01: Skip # Times out
-LayoutTests/fast/backgrounds/animated-gif-as-background_t01: Skip # Times out
-LayoutTests/fast/backgrounds/multiple-backgrounds-assert_t01: Skip # Times out
-LayoutTests/fast/canvas/2d.text.draw.fill.maxWidth.gradient_t01: Skip # Times out
-LayoutTests/fast/canvas/DrawImageSinglePixelStretch_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-before-css_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-composite-alpha_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-composite-canvas_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-composite-image_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-composite-stroke-alpha_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-css-crazy_t01: Skip # Times out
-LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-repaint_t01: Skip # Times out
-LayoutTests/fast/canvas/drawImage-with-valid-image_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/canvas-resize-crash_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/gl-teximage_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/texture-color-profile_t01: Skip # Times out
-LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/bug91547_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/inline-splitting-with-after-float-crash_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/pseudo-animation-display_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/pseudo-animation_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Times out
-LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/auto-content-resolution-rows_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/breadth-size-resolution-grid_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/calc-resolution-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/display-grid-set-get_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/flex-content-resolution-columns_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/flex-content-resolution-rows_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-auto-flow-get-set_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-auto-flow-update_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-container-change-explicit-grid-recompute-child_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-bad-cast-addchild_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-border-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-border-padding-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-empty-row-column_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-min-max-height_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-padding-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-padding-margin_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-remove-svg-child_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-element-shrink-to-fit_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-area-get-set_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-bad-named-area-auto-placement_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-bad-resolution-double-span_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-change-order-auto-flow_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-display_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-horiz-bt_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-vert-lr_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-vert-rl_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-margin-resolution_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-strict-ordering-crash_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/grid-template-areas-get-set_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/implicit-rows-auto-resolution_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/justify-self-cell_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/minmax-fixed-logical-height-only_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/minmax-fixed-logical-width-only_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-update_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item-update_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/percent-resolution-grid-item_t01: Skip # Times out
-LayoutTests/fast/css-grid-layout/place-cell-by-index_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/css-tables_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-absolutes_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-blocks_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-column-flex-items_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-flex-items_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/tables_t01: Skip # Times out
-LayoutTests/fast/css-intrinsic-dimensions/width-shrinks-avoid-floats_t01: Skip # Times out
-LayoutTests/fast/css/cached-sheet-restore-crash_t01: Skip # Times out
-LayoutTests/fast/css/comment-before-charset-external_t01: Skip # Times out
-LayoutTests/fast/css/comment-before-charset_t01: Skip # Times out
-LayoutTests/fast/css/counters/asterisk-counter-update-after-layout-crash_t01: Skip # Times out
-LayoutTests/fast/css/counters/complex-before_t01: Skip # Times out
-LayoutTests/fast/css/counters/counter-before-selector-crash_t01: Skip # Times out
-LayoutTests/fast/css/counters/counter-reparent-table-children-crash_t01: Skip # Times out
-LayoutTests/fast/css/counters/counter-reset-subtree-insert-crash_t01: Skip # Times out
-LayoutTests/fast/css/counters/counter-ruby-text-cleared_t01: Skip # Times out
-LayoutTests/fast/css/counters/counter-traverse-object-crash_t01: Skip # Times out
-LayoutTests/fast/css/font-face-svg-decoding-error_t01: Skip # Times out
-LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: Skip # Times out
-LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out
-LayoutTests/fast/css/link-alternate-stylesheet-1_t01: Skip # Times out
-LayoutTests/fast/css/link-alternate-stylesheet-2_t01: Skip # Times out
-LayoutTests/fast/css/link-alternate-stylesheet-3_t01: Skip # Times out
-LayoutTests/fast/css/link-alternate-stylesheet-4_t01: Skip # Times out
-LayoutTests/fast/css/link-alternate-stylesheet-5_t01: Skip # Times out
-LayoutTests/fast/css/link-disabled-attr-parser_t01: Skip # Times out
-LayoutTests/fast/css/nested-at-rules_t01: Skip # Times out
-LayoutTests/fast/css/percent-min-width-img-src-change_t01: Skip # Times out
-LayoutTests/fast/css/percent-width-img-src-change_t01: Skip # Times out
-LayoutTests/fast/css/pseudo-target-indirect-sibling-001_t01: Skip # Times out
-LayoutTests/fast/css/pseudo-target-indirect-sibling-002_t01: Skip # Times out
-LayoutTests/fast/css/remove-fixed-resizer-crash_t01: Skip # Times out
-LayoutTests/fast/css/sheet-collection-link_t01: Skip # Times out
-LayoutTests/fast/css/sheet-title_t01: Skip # Times out
-LayoutTests/fast/css/space-before-charset-external_t01: Skip # Times out
-LayoutTests/fast/css/space-before-charset_t01: Skip # Times out
-LayoutTests/fast/css/sticky/remove-inline-sticky-crash_t01: Skip # Times out
-LayoutTests/fast/css/sticky/remove-sticky-crash_t01: Skip # Times out
-LayoutTests/fast/css/sticky/sticky-table-col-crash_t01: Skip # Times out
-LayoutTests/fast/css/style-element-process-crash_t01: Skip # Times out
-LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: Skip # Times out
-LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-link_t01: Skip # Times out
-LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-sheet_t01: Skip # Times out
-LayoutTests/fast/css/stylesheet-enable-second-alternate-link_t01: Skip # Times out
-LayoutTests/fast/css/stylesheet-parentStyleSheet_t01: Skip # Times out
-LayoutTests/fast/css/webkit-keyframes-crash_t01: Skip # Times out
-LayoutTests/fast/css/webkit-marquee-speed-unit-in-quirksmode_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLDocument/active-element-gets-unforcusable_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLDocument/set-focus-on-valid-element_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLImageElement/image-loading-gc_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLImageElement/image-natural-width-height_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/link-and-subresource-test_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/link-beforeload-recursive_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/link-onload-before-page-load_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/link-onload2_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/onload-completion-test_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/prefetch-onload_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLLinkElement/prefetch_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLObjectElement/beforeload-set-text-crash_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLObjectElement/set-type-to-null-crash_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/async-onbeforeload_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/dont-load-unknown-type_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/remove-in-beforeload_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/script-for-attribute-unexpected-execution_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/script-load-events_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/script-reexecution_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLScriptElement/script-set-src_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLStyleElement/style-onload-before-page-load_t01: Skip # Times out
-LayoutTests/fast/dom/HTMLTemplateElement/innerHTML-inert_t01: Skip # Times out
-LayoutTests/fast/dom/SelectorAPI/bug-17313_t01: Skip # Times out
-LayoutTests/fast/dom/StyleSheet/detached-style-2_t01: Skip # Times out
-LayoutTests/fast/dom/StyleSheet/detached-style_t01: Skip # Times out
-LayoutTests/fast/dom/StyleSheet/discarded-sheet-owner-null_t01: Skip # Times out
-LayoutTests/fast/dom/css-cached-import-rule_t01: Skip # Times out
-LayoutTests/fast/dom/css-insert-import-rule-twice_t01: Skip # Times out
-LayoutTests/fast/dom/css-insert-import-rule_t01: Skip # Times out
-LayoutTests/fast/dom/css-mediarule-deleteRule-update_t01: Skip # Times out
-LayoutTests/fast/dom/css-mediarule-insertRule-update_t01: Skip # Times out
-LayoutTests/fast/dom/domtimestamp-is-number_t01: Skip # Times out
-LayoutTests/fast/dom/empty-hash-and-search_t01: Skip # Times out
-LayoutTests/fast/dom/gc-image-element-2_t01: Skip # Times out
-LayoutTests/fast/dom/gc-image-element_t01: Skip # Times out
-LayoutTests/fast/dom/horizontal-scrollbar-in-rtl_t01: Skip # Times out
-LayoutTests/fast/dom/horizontal-scrollbar-when-dir-change_t01: Skip # Times out
-LayoutTests/fast/dom/icon-url-change_t01: Skip # Times out
-LayoutTests/fast/dom/icon-url-list_t01: Skip # Times out
-LayoutTests/fast/dom/id-attribute-with-namespace-crash_t01: Skip # Times out
-LayoutTests/fast/dom/image-object_t01: Skip # Times out
-LayoutTests/fast/dom/inner-text_t01: Skip # Times out
-LayoutTests/fast/dom/shadow/insertion-point-list-menu-crash_t01: Skip # Times out
-LayoutTests/fast/dom/shadow/insertion-point-video-crash_t01: Skip # Times out
-LayoutTests/fast/dom/shadow/link-in-shadow-tree_t01: Skip # Times out
-LayoutTests/fast/dom/shadow/no-renderers-for-light-children_t01: Skip # Times out
-LayoutTests/fast/dom/text-node-attach-crash_t01: Skip # Times out
-LayoutTests/fast/dom/vertical-scrollbar-when-dir-change_t01: Skip # Times out
-LayoutTests/fast/dynamic/continuation-detach-crash_t01: Skip # Times out
-LayoutTests/fast/events/change-overflow-on-overflow-change_t01: Skip # Times out
-LayoutTests/fast/events/clipboard-clearData_t01: Skip # Times out
-LayoutTests/fast/events/clipboard-dataTransferItemList_t01: Skip # Times out
-LayoutTests/fast/events/dispatch-event-being-dispatched_t01: Skip # Times out
-LayoutTests/fast/events/document-elementFromPoint_t01: Skip # Times out
-LayoutTests/fast/events/nested-event-remove-node-crash_t01: Skip # Times out
-LayoutTests/fast/events/no-window-load_t01: Skip # Times out
-LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: Skip # Times out
-LayoutTests/fast/events/tabindex-removal-from-focused-element_t01: Skip # Times out
-LayoutTests/fast/events/window-load-capture_t01: Skip # Times out
-LayoutTests/fast/flexbox/crash-flexbox-no-layout-child_t01: Skip # Times out
-LayoutTests/fast/flexbox/layoutHorizontalBox-crash_t01: Skip # Times out
-LayoutTests/fast/flexbox/overhanging-floats-not-removed-crash_t01: Skip # Times out
-LayoutTests/fast/forms/HTMLOptionElement_selected_t01: Skip # Times out
-LayoutTests/fast/forms/activate-and-disabled-elements_t01: Skip # Times out
-LayoutTests/fast/forms/autofocus-focus-only-once_t01: Skip # Times out
-LayoutTests/fast/forms/autofocus-input-css-style-change_t01: Skip # Times out
-LayoutTests/fast/forms/autofocus-opera-007_t01: Skip # Times out
-LayoutTests/fast/forms/autofocus-readonly-attribute_t01: Skip # Times out
-LayoutTests/fast/forms/button/button-disabled-blur_t01: Skip # Times out
-LayoutTests/fast/forms/focus-style-pending_t01: Skip # Times out
-LayoutTests/fast/forms/form-added-to-table_t01: Skip # Times out
-LayoutTests/fast/forms/input-type-change_t01: Skip # Times out
-LayoutTests/fast/forms/input-width-height-attributes-without-renderer-loaded-image_t01: Skip # Times out
-LayoutTests/fast/forms/input-width-height-attributes-without-renderer_t01: Skip # Times out
-LayoutTests/fast/forms/search-popup-crasher_t01: Skip # Times out
-LayoutTests/fast/forms/select-change-popup-to-listbox-in-event-handler_t01: Skip # Times out
-LayoutTests/fast/forms/select-generated-content_t01: Skip # Times out
-LayoutTests/fast/forms/textarea-placeholder-relayout-assertion_t01: Skip # Times out
-LayoutTests/fast/forms/textarea-scrollbar-height_t01: Skip # Times out
-LayoutTests/fast/forms/textfield-focus-out_t01: Skip # Times out
-LayoutTests/fast/html/imports/import-element-removed-flag_t01: Skip # Times out
-LayoutTests/fast/loader/about-blank-hash-change_t01: Skip # Times out
-LayoutTests/fast/loader/about-blank-hash-kept_t01: Skip # Times out
-LayoutTests/fast/loader/hashchange-event-async_t01: Skip # Times out
-LayoutTests/fast/loader/hashchange-event-properties_t01: Skip # Times out
-LayoutTests/fast/loader/local-css-allowed-in-strict-mode_t01: Skip # Times out
-LayoutTests/fast/loader/onhashchange-attribute-listeners_t01: Skip # Times out
-LayoutTests/fast/loader/onload-policy-ignore-for-frame_t01: Skip # Times out
-LayoutTests/fast/loader/scroll-position-restored-on-back_t01: Skip # Times out
-LayoutTests/fast/loader/scroll-position-restored-on-reload-at-load-event_t01: Skip # Times out
-LayoutTests/fast/overflow/scroll-vertical-not-horizontal_t01: Skip # Times out
-LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: Skip # Times out
-LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-table-cell-ignore-height_t01: Skip # Times out
-LayoutTests/fast/replaced/table-percent-height-text-controls_t01: Skip # Times out
-LayoutTests/fast/replaced/table-percent-height_t01: Skip # Times out
-LayoutTests/fast/replaced/table-percent-width_t01: Skip # Times out
-LayoutTests/fast/replaced/table-replaced-element_t01: Skip # Times out
-LayoutTests/fast/speechsynthesis/speech-synthesis-boundary-events_t01: Skip # Times out
-LayoutTests/fast/speechsynthesis/speech-synthesis-speak_t01: Skip # Times out
-LayoutTests/fast/sub-pixel/float-list-inside_t01: Skip # Times out
+LayoutTests/*: Skip # These tests are going to be removed.
 LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t03: Skip # Times out
 LibTest/html/Element/blur_A01_t01: Skip # Times out
 LibTest/html/Element/focus_A01_t01: Skip # Times out
@@ -308,18 +80,6 @@
 LibTest/html/IFrameElement/focus_A01_t01: Skip # Times out
 LibTest/html/IFrameElement/onMouseWheel_A01_t01: Skip # Times out
 LibTest/html/IFrameElement/onTransitionEnd_A01_t01: Skip # Times out
-WebPlatformTest/DOMEvents/approved/ProcessingInstruction.DOMCharacterDataModified_t01: Skip # Times out
-WebPlatformTest/Utils/test/asyncTestTimeout_t01: Skip # Times out
-WebPlatformTest/dom/nodes/Node-isEqualNode_t01: Skip # Times out
-WebPlatformTest/html/semantics/embedded-content/media-elements/error-codes/error_t01: Skip # Times out
-WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues_t01: Skip # Times out
-WebPlatformTest/webstorage/event_local_key_t01: Skip # Times out
-WebPlatformTest/webstorage/event_local_newvalue_t01: Skip # Times out
-WebPlatformTest/webstorage/event_local_oldvalue_t01: Skip # Times out
-WebPlatformTest/webstorage/event_local_storagearea_t01: Skip # Times out
-WebPlatformTest/webstorage/event_local_url_t01: Skip # Times out
-WebPlatformTest/webstorage/event_session_key_t01: Skip # Times out
-WebPlatformTest/webstorage/event_session_newvalue_t01: Skip # Times out
-WebPlatformTest/webstorage/event_session_oldvalue_t01: Skip # Times out
-WebPlatformTest/webstorage/event_session_storagearea_t01: Skip # Times out
-WebPlatformTest/webstorage/event_session_url_t01: Skip # Times out
+LibTest/io/*: SkipByDesign # dart:io not supported.
+LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
+WebPlatformTest/*: Skip # These tests are going to be removed.
diff --git a/tests/compiler/dartdevc_native/runtime_utils.dart b/tests/compiler/dartdevc_native/runtime_utils.dart
index 4bb6829..f64e3d2 100644
--- a/tests/compiler/dartdevc_native/runtime_utils.dart
+++ b/tests/compiler/dartdevc_native/runtime_utils.dart
@@ -10,71 +10,80 @@
 // 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].
+///
+/// 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);
+}
+
 // Returns sWrapped<tWrapped> as a wrapped type.
 Type generic1(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(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 = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  var r = dart.unwrapType(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 = dart.unwrapType(returnWrapped);
-  var argType = dart.unwrapType(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.wrapType(dart.gFnType(
-    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
+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.wrapType(dart.gFnType(
-        (T) => [
-              T,
-              [dart.unwrapType(argWrapped)]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) => dart.gFnType(
+    (T) => [
+          T,
+          [unwrap(argWrapped)]
+        ],
+    (T) => [unwrap(boundWrapped)]);
 
 // 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.wrapType(dart.gFnType(
-        (T) => [
-              dart.unwrapType(returnWrapped),
-              [T]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) => dart.gFnType(
+    (T) => [
+          unwrap(returnWrapped),
+          [T]
+        ],
+    (T) => [unwrap(boundWrapped)]);
 
 void checkSubtype(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(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 = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(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 = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
   Expect.isFalse(dart.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 8743e56..bbcf7b1 100644
--- a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
+++ b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
@@ -16,7 +16,13 @@
 /// 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.
-Object unwrap(Type t) => t is dart.LegacyType ? t : dart.unwrapType(t);
+/// Generic functions are also unchanged, as they have a separate runtime type object representation.
+Object unwrap(Type t) {
+  if (t is dart.LegacyType || t is dart.GenericFunctionType) {
+    return t;
+  }
+  return dart.unwrapType(t);
+}
 
 /// Returns tWrapped? as a wrapped type.
 Type nullable(Type tWrapped) {
@@ -67,28 +73,26 @@
 
 // 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.wrapType(
-    dart.gFnType((T) => [dart.VoidType, []], (T) => [unwrap(boundWrapped)]));
+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.wrapType(dart.gFnType(
-        (T) => [
-              T,
-              [unwrap(argWrapped)]
-            ],
-        (T) => [unwrap(boundWrapped)]));
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) => dart.gFnType(
+    (T) => [
+          T,
+          [unwrap(argWrapped)]
+        ],
+    (T) => [unwrap(boundWrapped)]);
 
 // 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.wrapType(dart.gFnType(
-        (T) => [
-              unwrap(returnWrapped),
-              [T]
-            ],
-        (T) => [unwrap(boundWrapped)]));
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) => dart.gFnType(
+    (T) => [
+          unwrap(returnWrapped),
+          [T]
+        ],
+    (T) => [unwrap(boundWrapped)]);
 
 void checkSubtype(Type sWrapped, Type tWrapped) {
   var s = unwrap(sWrapped);
diff --git a/tests/ffi/regress_40537_test.dart b/tests/ffi/regress_40537_test.dart
new file mode 100644
index 0000000..d003b21
--- /dev/null
+++ b/tests/ffi/regress_40537_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.
+//
+// Truncation and sign extension of small ints, tested with something else than
+// equality.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import "dylib_utils.dart";
+
+main() {
+  variant1Negative();
+  variant1Positive();
+  variant2Negative();
+  variant2Positive();
+  variant3Negative();
+}
+
+/// `return x == 249 ? 1 : 0`.
+///
+/// This doesn't catch the error.
+final regress40537 = ffiTestFunctions
+    .lookupFunction<IntPtr Function(Uint8), int Function(int)>("Regress40537");
+
+variant1Negative() {
+  // 0xF9 =  -7 in 2s complement.
+  // 0xF9 = 249 in unsinged.
+  final result = regress40537(-7);
+  print(result);
+  Expect.equals(1, result);
+}
+
+variant1Positive() {
+  // 0xF9 = 249 in unsinged.
+  final result = regress40537(0xFFFFFFF9);
+  print(result);
+  Expect.equals(1, result);
+}
+
+/// `return x`.
+///
+/// This does.
+final regress40537Variant2 =
+    ffiTestFunctions.lookupFunction<IntPtr Function(Uint8), int Function(int)>(
+        "Regress40537Variant2");
+
+variant2Negative() {
+  // The 32 bit representation of -7 is 0xFFFFFFF9.
+  // Only the lowest byte, 0xF9, should be interpreted by calling convention,
+  // or it should be truncated and zero extended before calling.
+  final result = regress40537Variant2(-7);
+  print(result);
+  Expect.equals(249, result);
+}
+
+variant2Positive() {
+  // Only the lowest byte, 0xF9, should be interpreted by calling convention,
+  // or it should be truncated and zero extended before calling.
+  final result = regress40537Variant2(0xFFFFFFF9);
+  print(result);
+  Expect.equals(249, result);
+}
+
+/// `return x`.
+final regress40537Variant3 =
+    ffiTestFunctions.lookupFunction<Uint8 Function(IntPtr), int Function(int)>(
+        "Regress40537Variant3");
+
+variant3Negative() {
+  // This really passes -7 its intptr_t.
+  final result = regress40537Variant3(-7);
+  print(result);
+  Expect.equals(249, result);
+}
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
diff --git a/tests/ffi_2/regress_40537_test.dart b/tests/ffi_2/regress_40537_test.dart
new file mode 100644
index 0000000..d003b21
--- /dev/null
+++ b/tests/ffi_2/regress_40537_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.
+//
+// Truncation and sign extension of small ints, tested with something else than
+// equality.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import "dylib_utils.dart";
+
+main() {
+  variant1Negative();
+  variant1Positive();
+  variant2Negative();
+  variant2Positive();
+  variant3Negative();
+}
+
+/// `return x == 249 ? 1 : 0`.
+///
+/// This doesn't catch the error.
+final regress40537 = ffiTestFunctions
+    .lookupFunction<IntPtr Function(Uint8), int Function(int)>("Regress40537");
+
+variant1Negative() {
+  // 0xF9 =  -7 in 2s complement.
+  // 0xF9 = 249 in unsinged.
+  final result = regress40537(-7);
+  print(result);
+  Expect.equals(1, result);
+}
+
+variant1Positive() {
+  // 0xF9 = 249 in unsinged.
+  final result = regress40537(0xFFFFFFF9);
+  print(result);
+  Expect.equals(1, result);
+}
+
+/// `return x`.
+///
+/// This does.
+final regress40537Variant2 =
+    ffiTestFunctions.lookupFunction<IntPtr Function(Uint8), int Function(int)>(
+        "Regress40537Variant2");
+
+variant2Negative() {
+  // The 32 bit representation of -7 is 0xFFFFFFF9.
+  // Only the lowest byte, 0xF9, should be interpreted by calling convention,
+  // or it should be truncated and zero extended before calling.
+  final result = regress40537Variant2(-7);
+  print(result);
+  Expect.equals(249, result);
+}
+
+variant2Positive() {
+  // Only the lowest byte, 0xF9, should be interpreted by calling convention,
+  // or it should be truncated and zero extended before calling.
+  final result = regress40537Variant2(0xFFFFFFF9);
+  print(result);
+  Expect.equals(249, result);
+}
+
+/// `return x`.
+final regress40537Variant3 =
+    ffiTestFunctions.lookupFunction<Uint8 Function(IntPtr), int Function(int)>(
+        "Regress40537Variant3");
+
+variant3Negative() {
+  // This really passes -7 its intptr_t.
+  final result = regress40537Variant3(-7);
+  print(result);
+  Expect.equals(249, result);
+}
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
diff --git a/tests/language/assert/assert_test.dart b/tests/language/assert/assert_test.dart
new file mode 100644
index 0000000..85d0373
--- /dev/null
+++ b/tests/language/assert/assert_test.dart
@@ -0,0 +1,91 @@
+// 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-asserts
+// dart2jsOptions=--enable-asserts
+
+// Dart test program testing assert statements.
+
+import "package:expect/expect.dart";
+
+testTrue() {
+  int i = 0;
+  try {
+    assert(true);
+  } on AssertionError {
+    i = 1;
+  }
+  return i;
+}
+
+testFalse() {
+  int i = 0;
+  try {
+    assert(false);
+  } on AssertionError {
+    i = 1;
+  }
+  return i;
+}
+
+unknown(dynamic a) {
+  return a ? true : false;
+}
+
+testBoolean(bool value) {
+  int i = 0;
+  try {
+    assert(value);
+  } on AssertionError {
+    i = 1;
+  }
+  return i;
+}
+
+testDynamic(dynamic value) {
+  int i = 0;
+  try {
+    assert(value);
+  } on AssertionError {
+    i = 1;
+  }
+  return i;
+}
+
+testMessage(value, message) {
+  try {
+    assert(value, message);
+    return null;
+  } catch (error) {
+    // Catch any type to allow the Boolean conversion to throw either
+    // AssertionError or TypeError.
+    return error;
+  }
+}
+
+main() {
+  Expect.equals(0, testTrue());
+  Expect.equals(0, testBoolean(true));
+  Expect.equals(0, testDynamic(unknown(true)));
+
+  Expect.equals(1, testFalse());
+  Expect.equals(1, testBoolean(false));
+  Expect.equals(1, testDynamic(unknown(false)));
+
+  Expect.equals(1, testDynamic(null));
+  Expect.equals(1, testDynamic(42));
+  Expect.equals(1, testDynamic(() => true));
+  Expect.equals(1, testDynamic(() => false));
+  Expect.equals(1, testDynamic(() => 42));
+  Expect.equals(1, testDynamic(() => null));
+
+  Expect.equals(1234, testMessage(false, 1234).message);
+  Expect.equals('hi', testMessage(false, 'hi').message);
+
+  // These errors do not have the message because boolean conversion failed.
+  Expect.notEquals(1234, testMessage(null, 1234).message);
+  Expect.notEquals('hi', testMessage(null, 'hi').message);
+  Expect.notEquals('hi', testMessage(() => null, 'hi').message);
+  Expect.notEquals('hi', testMessage(() => false, 'hi').message);
+  Expect.notEquals('hi', testMessage(() => true, 'hi').message);
+}
diff --git a/tests/language/assert/assignable_type_test.dart b/tests/language/assert/assignable_type_test.dart
new file mode 100644
index 0000000..06b1c8d
--- /dev/null
+++ b/tests/language/assert/assignable_type_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.
+// Dart test program to test arithmetic operations.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+// This test crashes if we recompute type of AssertAssignableInstr based on its
+// output types. By doing that we would eliminate not only the unnecessary
+// AssertAssignableInstr but also the trailing class check.
+
+main() {
+  // Foul up  IC data in integer's unary minus.
+  var y = -0x80000000;
+  testInt64List();
+}
+
+testInt64List() {
+  var array = new List(10);
+  testInt64ListImpl(array);
+}
+
+testInt64ListImpl(array) {
+  for (int i = 0; i < 10; ++i) {}
+  int sum = 0;
+  for (int i = 0; i < 10; ++i) {
+    array[i] = -0x80000000000000 + i;
+  }
+}
diff --git a/tests/language/assert/initializer_const_error2_runtime_test.dart b/tests/language/assert/initializer_const_error2_runtime_test.dart
new file mode 100644
index 0000000..2ce838b
--- /dev/null
+++ b/tests/language/assert/initializer_const_error2_runtime_test.dart
@@ -0,0 +1,87 @@
+// 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.
+// VMOptions=--enable-asserts
+// dart2jsOptions=--enable-asserts
+//
+// Test of asserts in initializer lists.
+
+import "package:expect/expect.dart";
+
+class C {
+  final int x;
+  // Const constructors.
+  const C.cc01(this.x, y) : assert(x < y);
+  const C.cc02(x, y)
+      : x = x,
+        assert(x < y);
+  const C.cc03(x, y)
+      : assert(x < y),
+        x = x;
+  const C.cc04(this.x, y)
+      : assert(x < y),
+        super();
+  const C.cc05(x, y)
+      : x = x,
+        assert(x < y),
+        super();
+  const C.cc06(x, y)
+      : assert(x < y),
+        x = x,
+        super();
+  const C.cc07(x, y)
+      : assert(x < y),
+        x = x,
+        assert(y > x),
+        super();
+  const C.cc08(this.x, y) : assert(x < y, "$x < $y");
+  const C.cc09(this.x, y) : assert(x < y,);
+  const C.cc10(this.x, y) : assert(x < y, "$x < $y",);
+}
+
+main() {
+  const x = 3;
+  {
+
+    const C.cc01(2, x);
+  }
+  {
+
+    const C.cc02(2, x);
+  }
+  {
+
+    const C.cc03(2, x);
+  }
+  {
+
+    const C.cc04(2, x);
+  }
+  {
+
+    const C.cc05(2, x);
+  }
+  {
+
+    const C.cc06(2, x);
+  }
+  {
+
+    const C.cc07(2, x);
+  }
+  {
+
+    const C.cc08(2, x);
+  }
+  {
+
+    const C.cc09(2, x);
+  }
+  {
+
+    const C.cc10(2, x);
+  }
+}
diff --git a/tests/language/assert/initializer_const_error2_test.dart b/tests/language/assert/initializer_const_error2_test.dart
new file mode 100644
index 0000000..f5fa386
--- /dev/null
+++ b/tests/language/assert/initializer_const_error2_test.dart
@@ -0,0 +1,124 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--enable-asserts
+// dart2jsOptions=--enable-asserts
+//
+// Test of asserts in initializer lists.
+
+import "package:expect/expect.dart";
+
+class C {
+  final int x;
+  // Const constructors.
+  const C.cc01(this.x, y) : assert(x < y);
+  const C.cc02(x, y)
+      : x = x,
+        assert(x < y);
+  const C.cc03(x, y)
+      : assert(x < y),
+        x = x;
+  const C.cc04(this.x, y)
+      : assert(x < y),
+        super();
+  const C.cc05(x, y)
+      : x = x,
+        assert(x < y),
+        super();
+  const C.cc06(x, y)
+      : assert(x < y),
+        x = x,
+        super();
+  const C.cc07(x, y)
+      : assert(x < y),
+        x = x,
+        assert(y > x),
+        super();
+  const C.cc08(this.x, y) : assert(x < y, "$x < $y");
+  const C.cc09(this.x, y) : assert(x < y,);
+  const C.cc10(this.x, y) : assert(x < y, "$x < $y",);
+}
+
+main() {
+  const x = 3;
+  {
+    const x = 1;
+    const C.cc01(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc02(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc03(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc04(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc05(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc06(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc07(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc08(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc09(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+  {
+    const x = 1;
+    const C.cc10(2, x);
+//  ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
+//        ^
+// [cfe] Constant evaluation error:
+  }
+}
diff --git a/tests/language/assert/initializer_const_error_runtime_test.dart b/tests/language/assert/initializer_const_error_runtime_test.dart
new file mode 100644
index 0000000..682d563
--- /dev/null
+++ b/tests/language/assert/initializer_const_error_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.
+
+class C {
+  static bool check(x, y) => x < y;
+  final int x;
+  const C(this.x);
+  // The expression is not a potentially constant expression.
+  // This is a compile-time error even in production mode.
+  const C.bc03(this.x, y)
+
+      ;
+}
+
+main() {
+  var c = new C.bc03(1, 2);
+  if (c.x != 1) throw "non-trivial use of c";
+}
diff --git a/tests/language/assert/initializer_const_error_test.dart b/tests/language/assert/initializer_const_error_test.dart
new file mode 100644
index 0000000..d7ec1fb
--- /dev/null
+++ b/tests/language/assert/initializer_const_error_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.
+
+class C {
+  static bool check(x, y) => x < y;
+  final int x;
+  const C(this.x);
+  // The expression is not a potentially constant expression.
+  // This is a compile-time error even in production mode.
+  const C.bc03(this.x, y)
+      : assert(check(x, y))
+      //       ^^^^^^^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT
+      // [cfe] Method invocation is not a constant expression.
+      ;
+}
+
+main() {
+  var c = new C.bc03(1, 2);
+  if (c.x != 1) throw "non-trivial use of c";
+}
diff --git a/tests/language/assert/initializer_const_function_runtime_test.dart b/tests/language/assert/initializer_const_function_runtime_test.dart
new file mode 100644
index 0000000..ff43fc1
--- /dev/null
+++ b/tests/language/assert/initializer_const_function_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) 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 {
+  static bool staticTrue() => true;
+  final int x;
+
+  // Functions as parameters to assert are no longer supported in Dart 2.0, so
+  // this is now a static type error.
+  const C.bc01(this.x, y)
+
+      ;
+}
+
+main() {
+  new C.bc01(1, 2);
+}
diff --git a/tests/language/assert/initializer_const_function_test.dart b/tests/language/assert/initializer_const_function_test.dart
new file mode 100644
index 0000000..27b99bd
--- /dev/null
+++ b/tests/language/assert/initializer_const_function_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 C {
+  static bool staticTrue() => true;
+  final int x;
+
+  // Functions as parameters to assert are no longer supported in Dart 2.0, so
+  // this is now a static type error.
+  const C.bc01(this.x, y)
+      : assert(staticTrue)
+      //       ^^^^^^^^^^
+      // [analyzer] STATIC_TYPE_WARNING.NON_BOOL_EXPRESSION
+      // [cfe] A value of type 'bool Function()' can't be assigned to a variable of type 'bool'.
+      ;
+}
+
+main() {
+  new C.bc01(1, 2);
+}
diff --git a/tests/language/assert/initializer_test.dart b/tests/language/assert/initializer_test.dart
new file mode 100644
index 0000000..b2fe755
--- /dev/null
+++ b/tests/language/assert/initializer_test.dart
@@ -0,0 +1,130 @@
+// 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 testing assert statements.
+
+import "package:expect/expect.dart";
+
+class C {
+  static bool check(x, y) => x < y;
+  static bool staticTrue() => true;
+  final int x;
+  const C(this.x);
+
+  C.c01(this.x, y) : assert(x < y);
+  C.c02(x, y) : x = x, assert(x < y);
+  C.c03(x, y) : assert(x < y), x = x;
+  C.c05(this.x, y) : assert(x < y), super();
+  C.c06(x, y) : x = x, assert(x < y), super();
+  C.c07(x, y) : assert(x < y), x = x, super();
+  C.c08(x, y) : assert(x < y), x = x, assert(y > x), super();
+  C.c09(this.x, y) : assert(x < y, "$x < $y");
+  C.c10(this.x, y) : assert(x < y,);
+  C.c11(this.x, y) : assert(x < y, "$x < $y",);
+
+  const C.cc01(this.x, y) : assert(x < y);
+  const C.cc02(x, y) : x = x, assert(x < y);
+  const C.cc03(x, y) : assert(x < y), x = x;
+  const C.cc05(this.x, y) : assert(x < y), super();
+  const C.cc06(x, y) : x = x, assert(x < y), super();
+  const C.cc07(x, y) : assert(x < y), x = x, super();
+  const C.cc08(x, y) : assert(x < y), x = x, assert(y > x), super();
+  const C.cc09(this.x, y) : assert(x < y, "$x < $y");
+  const C.cc10(this.x, y) : assert(x < y,);
+  const C.cc11(this.x, y) : assert(x < y, "$x < $y",);
+
+  C.nc01(this.x, y) : assert(check(x, y));
+  C.nc02(x, y) : x = x, assert(check(x, y));
+  C.nc03(x, y) : assert(check(x, y)), x = x;
+  C.nc05(this.x, y) : assert(check(x, y)), super();
+  C.nc06(x, y) : x = x, assert(check(x, y)), super();
+  C.nc07(x, y) : assert(check(x, y)), x = x, super();
+  C.nc08(x, y) : assert(check(x, y)), x = x, assert(y > x), super();
+  C.nc09(this.x, y) : assert(check(x, y), "$x < $y");
+  C.nc10(this.x, y) : assert(check(x, y),);
+  C.nc11(this.x, y) : assert(check(x, y), "$x < $y",);
+
+  C.fc01(this.x, y) : assert((() => x < y)());
+  C.fc02(x, y) : x = x, assert((() => x < y)());
+  C.fc03(x, y) : assert((() => x < y)()), x = x;
+  C.fc05(this.x, y) : assert((() => x < y)()), super();
+  C.fc06(x, y) : x = x, assert((() => x < y)()), super();
+  C.fc07(x, y) : assert((() => x < y)()), x = x, super();
+  C.fc08(x, y) : assert((() => x < y)()),x = x, assert(y > x), super();
+  C.fc09(this.x, y) : assert((() => x < y)(), "$x < $y");
+  C.fc10(this.x, y) : assert((() => x < y)(),);
+  C.fc11(this.x, y) : assert((() => x < y)(), "$x < $y",);
+}
+
+
+main() {
+  // Test all constructors with both succeeding and failing asserts.
+  test(1, 2);
+  test(2, 1);
+
+  const c1 = const C(1);
+
+  // Asserts do not affect canonization.
+  Expect.identical(c1, const C.cc01(1, 2));
+  Expect.identical(c1, const C.cc02(1, 2));
+  Expect.identical(c1, const C.cc03(1, 2));
+  Expect.identical(c1, const C.cc05(1, 2));
+  Expect.identical(c1, const C.cc06(1, 2));
+  Expect.identical(c1, const C.cc07(1, 2));
+  Expect.identical(c1, const C.cc08(1, 2));
+  Expect.identical(c1, const C.cc09(1, 2));
+  Expect.identical(c1, const C.cc10(1, 2));
+  Expect.identical(c1, const C.cc11(1, 2));
+}
+
+void test(int x, int y) {
+  bool assertionsEnabled = false;
+  assert(assertionsEnabled = true);
+
+  bool Function(C Function()) doTest = (assertionsEnabled && x >= y)
+    ? (f) { Expect.throwsAssertionError(f); }
+    : (f) { Expect.equals(x, f().x); };
+
+  doTest(() => new C.c01(x, y));
+  doTest(() => new C.c02(x, y));
+  doTest(() => new C.c03(x, y));
+  doTest(() => new C.c05(x, y));
+  doTest(() => new C.c06(x, y));
+  doTest(() => new C.c07(x, y));
+  doTest(() => new C.c08(x, y));
+  doTest(() => new C.c09(x, y));
+  doTest(() => new C.c10(x, y));
+  doTest(() => new C.c11(x, y));
+  doTest(() => new C.cc01(x, y));
+  doTest(() => new C.cc02(x, y));
+  doTest(() => new C.cc03(x, y));
+  doTest(() => new C.cc05(x, y));
+  doTest(() => new C.cc06(x, y));
+  doTest(() => new C.cc07(x, y));
+  doTest(() => new C.cc08(x, y));
+  doTest(() => new C.cc09(x, y));
+  doTest(() => new C.cc10(x, y));
+  doTest(() => new C.cc11(x, y));
+  doTest(() => new C.nc01(x, y));
+  doTest(() => new C.nc02(x, y));
+  doTest(() => new C.nc03(x, y));
+  doTest(() => new C.nc05(x, y));
+  doTest(() => new C.nc06(x, y));
+  doTest(() => new C.nc07(x, y));
+  doTest(() => new C.nc08(x, y));
+  doTest(() => new C.nc09(x, y));
+  doTest(() => new C.nc10(x, y));
+  doTest(() => new C.nc11(x, y));
+  doTest(() => new C.fc01(x, y));
+  doTest(() => new C.fc02(x, y));
+  doTest(() => new C.fc03(x, y));
+  doTest(() => new C.fc05(x, y));
+  doTest(() => new C.fc06(x, y));
+  doTest(() => new C.fc07(x, y));
+  doTest(() => new C.fc08(x, y));
+  doTest(() => new C.fc09(x, y));
+  doTest(() => new C.fc10(x, y));
+  doTest(() => new C.fc11(x, y));
+}
+
diff --git a/tests/language/assert/message_test.dart b/tests/language/assert/message_test.dart
new file mode 100644
index 0000000..7f7e076
--- /dev/null
+++ b/tests/language/assert/message_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All 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:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+// TODO(rnystrom): Unify with assert_with_message_test.dart.
+
+main() {
+  // Only run with asserts enabled mode.
+  bool assertsEnabled = false;
+  assert(assertsEnabled = true);
+  if (!assertsEnabled) return;
+
+  // Basics.
+  assert(true, "");
+
+  dynamic x = null;
+  // Successful asserts won't execute message.
+  assert(true, x + 42);
+  assert(true, throw "unreachable");
+
+  // Can use any value as message.
+  try {
+    assert(false, 42);
+  } on AssertionError catch (e) {
+    Expect.equals(42, e.message);
+  }
+
+  try {
+    assert(false, "");
+  } on AssertionError catch (e) {
+    Expect.equals("", e.message);
+  }
+
+  try {
+    assert(false, null);
+  } on AssertionError catch (e) {
+    Expect.equals(null, e.message);
+  }
+
+  // Test expression can throw.
+  try {
+    assert(throw "test", throw "message");
+  } on String catch (e) {
+    Expect.equals("test", e);
+  }
+
+  // Message expression can throw.
+  try {
+    assert(false, throw "message");
+  } on String catch (e) {
+    Expect.equals("message", e);
+  }
+
+  // Failing asserts evaluate message after test.
+  var list = [];
+  try {
+    assert((list..add(1)).isEmpty, (list..add(3)).length);
+  } on AssertionError catch (e) {
+    Expect.equals(2, e.message);
+    Expect.listEquals([1, 3], list);
+  }
+
+  asyncStart();
+  asyncTests().then((_) {
+    asyncEnd();
+  });
+}
+
+Future asyncTests() async {
+  // You can await in both condition and message.
+  assert(true, await 0);
+  assert(await true, 1);
+  assert(await true, await 2);
+
+  // Successful asserts won't await/evaluate message.
+  Future unreachable() => throw "unreachable";
+  assert(await true, await unreachable());
+
+  try {
+    assert(false, await 3);
+  } on AssertionError catch (e) {
+    Expect.equals(3, e.message);
+  }
+
+  var falseFuture = new Future.value(false);
+  var numFuture = new Future.value(4);
+
+  try {
+    assert(await falseFuture, await numFuture);
+  } on AssertionError catch (e) {
+    Expect.equals(4, e.message);
+  }
+
+  try {
+    assert(await falseFuture, await new Future.error("error"));
+  } on String catch (e) {
+    Expect.equals("error", e);
+  }
+}
diff --git a/tests/language/assert/trailing_comma_runtime_test.dart b/tests/language/assert/trailing_comma_runtime_test.dart
new file mode 100644
index 0000000..066c5f7
--- /dev/null
+++ b/tests/language/assert/trailing_comma_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.
+
+main() {
+  assert(true);
+  assert(true,);
+  assert(true,"message");
+  assert(true,"message",);
+
+
+}
diff --git a/tests/language/assert/trailing_comma_test.dart b/tests/language/assert/trailing_comma_test.dart
new file mode 100644
index 0000000..7b90068
--- /dev/null
+++ b/tests/language/assert/trailing_comma_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+main() {
+  assert(true);
+  assert(true,);
+  assert(true,"message");
+  assert(true,"message",);
+  assert(true,"message",extra);
+  //                    ^^^^^
+  // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+  // [cfe] Unexpected token 'extra'.
+  assert(true,"message",,);
+  //                    ^
+  // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+  // [cfe] Unexpected token ','.
+}
diff --git a/tests/language/assert/with_message_test.dart b/tests/language/assert/with_message_test.dart
new file mode 100644
index 0000000..147ee2f
--- /dev/null
+++ b/tests/language/assert/with_message_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  var assertsEnabled = false;
+  assert((assertsEnabled = true));
+  if (!assertsEnabled) return;
+
+  // TODO(rnystrom): Test cases where the first argument to assert() is a
+  // function.
+
+  testAssertFails();
+  testAssertDoesNotFail();
+  testNullMessage();
+  testDoesNotEvaluateMessageIfAssertSucceeds();
+  testMessageExpressionThatThrows();
+  testCallsToStringOnMessageLazily();
+}
+
+/// A class with a custom toString() that tracks when it is called.
+class ToString {
+  bool calledToString = false;
+
+  String toString() {
+    calledToString = true;
+    return "toString!";
+  }
+}
+
+testAssertFails() {
+  try {
+    assert(false, "Oops");
+    Expect.fail("Assert should throw.");
+  } catch (e) {
+    Expect.isTrue(e.toString().contains("Oops"));
+  }
+}
+
+testAssertDoesNotFail() {
+  try {
+    assert(true, "Oops");
+  } catch (e) {
+    Expect.fail("Assert should not throw.");
+  }
+}
+
+testNullMessage() {
+  try {
+    assert(false, null);
+    Expect.fail("Assert should throw.");
+  } catch (e) {
+    Expect.isTrue(e.toString().contains("is not true"));
+  }
+}
+
+testDoesNotEvaluateMessageIfAssertSucceeds() {
+  try {
+    var evaluated = false;
+    assert(true, evaluated = true);
+    Expect.isFalse(evaluated);
+  } catch (e) {
+    Expect.fail("Assert should not throw.");
+  }
+}
+
+testMessageExpressionThatThrows() {
+  try {
+    assert(false, throw "dang");
+    Expect.fail("Should throw");
+  } catch (e) {
+    Expect.equals(e, "dang");
+  }
+}
+
+testCallsToStringOnMessageLazily() {
+  var toString = new ToString();
+  try {
+    assert(false, toString);
+    Expect.fail("Assert should throw.");
+  } catch (e) {
+    Expect.isFalse(toString.calledToString);
+    Expect.isTrue(e.toString().contains("Instance of 'ToString'"));
+    Expect.isFalse(toString.calledToString);
+  }
+}
diff --git a/tests/language/assert/with_type_test_or_cast_test.dart b/tests/language/assert/with_type_test_or_cast_test.dart
new file mode 100644
index 0000000..85a18ec
--- /dev/null
+++ b/tests/language/assert/with_type_test_or_cast_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.
+
+// Issue 3741: generic type tests and casts fail in assertion statements
+// when run in production mode.
+//
+// The cause was incomplete generic type skipping, so each of the assert
+// statements below would fail.
+//
+// VMOptions=
+// VMOptions=--enable_asserts
+
+main() {
+  var names = new List<int>();
+
+  // Generic type test.
+  assert(names is List<int>);
+
+  // Negated generic type test.
+  assert(names is! List<String>);
+
+  // Generic type cast.
+  assert((names as List<num>).length == 0);
+
+  // Generic type test inside expression.
+  assert((names is List<int>));
+}
diff --git a/tests/language_2/assert/assert_test.dart b/tests/language_2/assert/assert_test.dart
index 2f1efee..162c270 100644
--- a/tests/language_2/assert/assert_test.dart
+++ b/tests/language_2/assert/assert_test.dart
@@ -56,9 +56,7 @@
   try {
     assert(value, message);
     return null;
-  } catch (error) {
-    // Catch any type to allow the Boolean conversion to throw either
-    // AssertionError or TypeError.
+  } on AssertionError catch (error) {
     return error;
   }
 }
@@ -82,11 +80,4 @@
 
   Expect.equals(1234, testMessage(false, 1234).message);
   Expect.equals('hi', testMessage(false, 'hi').message);
-
-  // These errors do not have the message because boolean conversion failed.
-  Expect.notEquals(1234, testMessage(null, 1234).message);
-  Expect.notEquals('hi', testMessage(null, 'hi').message);
-  Expect.notEquals('hi', testMessage(() => null, 'hi').message);
-  Expect.notEquals('hi', testMessage(() => false, 'hi').message);
-  Expect.notEquals('hi', testMessage(() => true, 'hi').message);
 }
diff --git a/tests/lib/mirrors/constructors_test.dart b/tests/lib/mirrors/constructors_test.dart
index 9bdbc7f..3d82198 100644
--- a/tests/lib/mirrors/constructors_test.dart
+++ b/tests/lib/mirrors/constructors_test.dart
@@ -11,7 +11,7 @@
 import 'stringify.dart';
 
 constructorsOf(ClassMirror cm) {
-  var result = new Map();
+  var result = new Map<Symbol, MethodMirror>();
   cm.declarations.forEach((k, v) {
     if (v is MethodMirror && v.isConstructor) result[k] = v;
   });
diff --git a/tests/lib/mirrors/instance_members_easier_test.dart b/tests/lib/mirrors/instance_members_easier_test.dart
index 4a9fe66..a017ac0 100644
--- a/tests/lib/mirrors/instance_members_easier_test.dart
+++ b/tests/lib/mirrors/instance_members_easier_test.dart
@@ -9,8 +9,8 @@
 
 import 'declarations_model_easier.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 class EasierSuperclass {
diff --git a/tests/lib/mirrors/instance_members_test.dart b/tests/lib/mirrors/instance_members_test.dart
index 4bbf79f..203c665 100644
--- a/tests/lib/mirrors/instance_members_test.dart
+++ b/tests/lib/mirrors/instance_members_test.dart
@@ -9,8 +9,8 @@
 
 import 'declarations_model.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib/mirrors/instance_members_with_override_test.dart b/tests/lib/mirrors/instance_members_with_override_test.dart
index 94a2252..f091200 100644
--- a/tests/lib/mirrors/instance_members_with_override_test.dart
+++ b/tests/lib/mirrors/instance_members_with_override_test.dart
@@ -28,8 +28,8 @@
   /* abstract */ notOverridden();
 }
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib/mirrors/other_declarations_location_test.dart b/tests/lib/mirrors/other_declarations_location_test.dart
index 2c751a5..9c1c85e 100644
--- a/tests/lib/mirrors/other_declarations_location_test.dart
+++ b/tests/lib/mirrors/other_declarations_location_test.dart
@@ -42,7 +42,7 @@
   expectLocation(reflectClass(C).declarations[#c]!, mainSuffix, 17, 14);
   expectLocation(reflectClass(C).declarations[#d]!, mainSuffix, 18, 16);
   expectLocation(reflectClass(C).declarations[#e]!, mainSuffix, 20, 7);
-  expectLocation(reflectClass(C).declarations[#f]!, mainSuffix, 21, 11);
+  expectLocation(reflectClass(C).declarations[#f]!, mainSuffix, 21, 16);
 
   // Type variables.
   expectLocation(reflectClass(C).declarations[#S]!, mainSuffix, 14, 9);
diff --git a/tests/lib/mirrors/static_members_easier_test.dart b/tests/lib/mirrors/static_members_easier_test.dart
index b050a3c..a3912e9 100644
--- a/tests/lib/mirrors/static_members_easier_test.dart
+++ b/tests/lib/mirrors/static_members_easier_test.dart
@@ -10,8 +10,8 @@
 import 'stringify.dart';
 import 'declarations_model_easier.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib/mirrors/static_members_test.dart b/tests/lib/mirrors/static_members_test.dart
index f84bc53..aad20e7 100644
--- a/tests/lib/mirrors/static_members_test.dart
+++ b/tests/lib/mirrors/static_members_test.dart
@@ -10,8 +10,8 @@
 import 'stringify.dart';
 import 'declarations_model.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib/typed_data/typed_data_view_sublist_test.dart b/tests/lib/typed_data/typed_data_view_sublist_test.dart
new file mode 100644
index 0000000..d914587
--- /dev/null
+++ b/tests/lib/typed_data/typed_data_view_sublist_test.dart
@@ -0,0 +1,209 @@
+// 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:typed_data';
+import 'package:expect/expect.dart';
+
+const bool isJS = identical(1, 1.0); // Implies no 64-bit integers.
+
+void main() {
+  testViews();
+  testErrors();
+}
+
+void testViews() {
+  var bytes = Uint8List.fromList([for (int i = 0; i < 256; i++) i]);
+
+  // Non-view classes.
+  var bd = () {
+    var bd = ByteData(256);
+    for (int i = 0; i < 256; i++) bd.setUint8(i, i);
+    return bd;
+  }();
+  var u8 = Uint8List.fromList(bytes);
+  var i8 = Int8List.fromList(bytes);
+  var c8 = Uint8ClampedList.fromList(bytes);
+  var u16 = Uint16List.fromList(Uint16List.view(bytes.buffer));
+  var i16 = Int16List.fromList(Int16List.view(bytes.buffer));
+  var u32 = Uint32List.fromList(Uint32List.view(bytes.buffer));
+  var i32 = Int32List.fromList(Int32List.view(bytes.buffer));
+  var u64 = isJS ? null : Uint64List.fromList(Uint64List.view(bytes.buffer));
+  var i64 = isJS ? null : Int64List.fromList(Int64List.view(bytes.buffer));
+  var f32 = Float32List.fromList(Float32List.view(bytes.buffer));
+  var f64 = Float64List.fromList(Float64List.view(bytes.buffer));
+  var f32x4 = Float32x4List.fromList(Float32x4List.view(bytes.buffer));
+  var i32x4 = Int32x4List.fromList(Int32x4List.view(bytes.buffer));
+  var f64x2 = Float64x2List.fromList(Float64x2List.view(bytes.buffer));
+
+  // View classes. A buffer with the right data in the middle.
+  var doubleBuffer = Uint8List(512)..setRange(128, 384, bytes);
+  var bdv = ByteData.view(doubleBuffer.buffer, 128, 256);
+  var u8v = Uint8List.view(doubleBuffer.buffer, 128, 256);
+  var i8v = Int8List.view(doubleBuffer.buffer, 128, 256);
+  var c8v = Uint8ClampedList.view(doubleBuffer.buffer, 128, 256);
+  var u16v = Uint16List.view(doubleBuffer.buffer, 128, 128);
+  var i16v = Int16List.view(doubleBuffer.buffer, 128, 128);
+  var u32v = Uint32List.view(doubleBuffer.buffer, 128, 64);
+  var i32v = Int32List.view(doubleBuffer.buffer, 128, 64);
+  var u64v = isJS ? null : Uint64List.view(doubleBuffer.buffer, 128, 32);
+  var i64v = isJS ? null : Int64List.view(doubleBuffer.buffer, 128, 32);
+  var f32v = Float32List.view(doubleBuffer.buffer, 128, 64);
+  var f64v = Float64List.view(doubleBuffer.buffer, 128, 32);
+  var f32x4v = Float32x4List.view(doubleBuffer.buffer, 128, 16);
+  var i32x4v = Int32x4List.view(doubleBuffer.buffer, 128, 16);
+  var f64x2v = Float64x2List.view(doubleBuffer.buffer, 128, 16);
+
+  var allTypedData = <TypedData>[
+    bd,
+    u8,
+    i8,
+    c8,
+    u16,
+    i16,
+    u32,
+    i32,
+    if (!isJS) u64!,
+    if (!isJS) i64!,
+    f32,
+    f64,
+    f32x4,
+    i32x4,
+    f64x2,
+    u8v,
+    i8v,
+    c8v,
+    u16v,
+    i16v,
+    u32v,
+    i32v,
+    if (!isJS) u64v!,
+    if (!isJS) i64v!,
+    f32v,
+    f64v,
+    f32x4v,
+    i32x4v,
+    f64x2v,
+  ];
+
+  for (var td in allTypedData) {
+    var tdType = td.runtimeType.toString();
+    testSame(TypedData data) {
+      expectBuffer(td.buffer, data.buffer);
+      Expect.equals(td.lengthInBytes, data.lengthInBytes);
+      Expect.equals(td.offsetInBytes, data.offsetInBytes);
+    }
+
+    testSame(ByteData.sublistView(td));
+    testSame(Int8List.sublistView(td));
+    testSame(Uint8List.sublistView(td));
+    testSame(Uint8ClampedList.sublistView(td));
+    testSame(Int16List.sublistView(td));
+    testSame(Uint16List.sublistView(td));
+    testSame(Int32List.sublistView(td));
+    testSame(Uint32List.sublistView(td));
+    if (!isJS) testSame(Int64List.sublistView(td));
+    if (!isJS) testSame(Uint64List.sublistView(td));
+    testSame(Float32List.sublistView(td));
+    testSame(Float64List.sublistView(td));
+    testSame(Float32x4List.sublistView(td));
+    testSame(Int32x4List.sublistView(td));
+    testSame(Float64x2List.sublistView(td));
+
+    var length = td.lengthInBytes ~/ td.elementSizeInBytes;
+    for (int start = 0; start < length; start += 16) {
+      for (int end = start; end < length; end += 16) {
+        void testSlice(TypedData data) {
+          var name = "$tdType -> ${data.runtimeType} $start..$end";
+          expectBuffer(td.buffer, data.buffer, name);
+          int offsetInBytes = td.offsetInBytes + start * td.elementSizeInBytes;
+          int lengthInBytes = (end - start) * td.elementSizeInBytes;
+          Expect.equals(lengthInBytes, data.lengthInBytes, name);
+          Expect.equals(offsetInBytes, data.offsetInBytes, name);
+        }
+
+        testSlice(ByteData.sublistView(td, start, end));
+        testSlice(Int8List.sublistView(td, start, end));
+        testSlice(Uint8List.sublistView(td, start, end));
+        testSlice(Uint8ClampedList.sublistView(td, start, end));
+        testSlice(Int16List.sublistView(td, start, end));
+        testSlice(Uint16List.sublistView(td, start, end));
+        testSlice(Int32List.sublistView(td, start, end));
+        testSlice(Uint32List.sublistView(td, start, end));
+        if (!isJS) testSlice(Int64List.sublistView(td, start, end));
+        if (!isJS) testSlice(Uint64List.sublistView(td, start, end));
+        testSlice(Float32List.sublistView(td, start, end));
+        testSlice(Float64List.sublistView(td, start, end));
+        testSlice(Float32x4List.sublistView(td, start, end));
+        testSlice(Int32x4List.sublistView(td, start, end));
+        testSlice(Float64x2List.sublistView(td, start, end));
+      }
+    }
+  }
+}
+
+void testErrors() {
+  // Alignment must be right for non-byte-sized results.
+  // offsetInBytes offset must be a multiple of the element size.
+  // lengthInBytes must be a multiple of the element size.
+  var bytes = Uint8List.fromList([for (int i = 0; i < 256; i++) i]);
+
+  var oddStartView = Uint8List.view(bytes.buffer, 1, 32);
+  var oddLengthView = Uint8List.view(bytes.buffer, 0, 33);
+
+  void testThrows(void Function() operation) {
+    Expect.throws<ArgumentError>(operation);
+  }
+
+  testThrows(() => Uint16List.sublistView(oddStartView));
+  testThrows(() => Int16List.sublistView(oddStartView));
+  testThrows(() => Uint32List.sublistView(oddStartView));
+  testThrows(() => Int32List.sublistView(oddStartView));
+  if (!isJS) testThrows(() => Uint64List.sublistView(oddStartView));
+  if (!isJS) testThrows(() => Int64List.sublistView(oddStartView));
+  testThrows(() => Float32List.sublistView(oddStartView));
+  testThrows(() => Float64List.sublistView(oddStartView));
+  testThrows(() => Float32x4List.sublistView(oddStartView));
+  testThrows(() => Int32x4List.sublistView(oddStartView));
+  testThrows(() => Float64x2List.sublistView(oddStartView));
+
+  testThrows(() => Uint16List.sublistView(oddLengthView));
+  testThrows(() => Int16List.sublistView(oddLengthView));
+  testThrows(() => Uint32List.sublistView(oddLengthView));
+  testThrows(() => Int32List.sublistView(oddLengthView));
+  if (!isJS) testThrows(() => Uint64List.sublistView(oddLengthView));
+  if (!isJS) testThrows(() => Int64List.sublistView(oddLengthView));
+  testThrows(() => Float32List.sublistView(oddLengthView));
+  testThrows(() => Float64List.sublistView(oddLengthView));
+  testThrows(() => Float32x4List.sublistView(oddLengthView));
+  testThrows(() => Int32x4List.sublistView(oddLengthView));
+  testThrows(() => Float64x2List.sublistView(oddLengthView));
+}
+
+void expectBuffer(ByteBuffer buffer, ByteBuffer dataBuffer, [String? name]) {
+  // Buffer objects are not necessarily *identical* even though they
+  // represent the same underlying data. The VM allocates buffer objects
+  // lazily for inline typed data objects.
+  if (identical(buffer, dataBuffer)) return;
+  if (buffer.lengthInBytes != dataBuffer.lengthInBytes) {
+    Expect.fail("Different buffers${name == null ? "" : ": $name"}");
+  }
+  // Cannot distinguish empty buffers.
+  if (buffer.lengthInBytes == 0) return;
+  // Contains the same value now.
+  var l1 = Uint8List.view(buffer);
+  var l2 = Uint8List.view(dataBuffer);
+  var byte1 = l1[0];
+  var byte2 = l2[0];
+  if (byte1 != byte2) {
+    Expect.fail("Different buffers${name == null ? "" : ": $name"}");
+  }
+  // Byte written to one buffer can be read from the other.
+  var newByte1 = byte1 ^ 1;
+  l1[0] = newByte1;
+  var newByte2 = l2[0];
+  l1[0] = byte1;
+  if (newByte1 != newByte2) {
+    Expect.fail("Different buffers${name == null ? "" : ": $name"}");
+  }
+}
diff --git a/tests/lib_2/isolate/message3_test.dart b/tests/lib_2/isolate/message3_test.dart
index aa3166c..6536b36 100644
--- a/tests/lib_2/isolate/message3_test.dart
+++ b/tests/lib_2/isolate/message3_test.dart
@@ -60,7 +60,11 @@
 }
 
 class E {
+  // Make sure E.fun is not removed by the tree shaker, as this test verifies
+  // that an object with a tear-off in E.fun cannot be sent.
+  @pragma("vm:entry-point")
   Function fun;
+
   E(this.fun);
 
   static fooFun() => 499;
diff --git a/tests/lib_2/mirrors/constructors_test.dart b/tests/lib_2/mirrors/constructors_test.dart
index 9bdbc7f..3d82198 100644
--- a/tests/lib_2/mirrors/constructors_test.dart
+++ b/tests/lib_2/mirrors/constructors_test.dart
@@ -11,7 +11,7 @@
 import 'stringify.dart';
 
 constructorsOf(ClassMirror cm) {
-  var result = new Map();
+  var result = new Map<Symbol, MethodMirror>();
   cm.declarations.forEach((k, v) {
     if (v is MethodMirror && v.isConstructor) result[k] = v;
   });
diff --git a/tests/lib_2/mirrors/instance_members_easier_test.dart b/tests/lib_2/mirrors/instance_members_easier_test.dart
index 4a9fe66..a017ac0 100644
--- a/tests/lib_2/mirrors/instance_members_easier_test.dart
+++ b/tests/lib_2/mirrors/instance_members_easier_test.dart
@@ -9,8 +9,8 @@
 
 import 'declarations_model_easier.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 class EasierSuperclass {
diff --git a/tests/lib_2/mirrors/instance_members_test.dart b/tests/lib_2/mirrors/instance_members_test.dart
index 4bbf79f..203c665 100644
--- a/tests/lib_2/mirrors/instance_members_test.dart
+++ b/tests/lib_2/mirrors/instance_members_test.dart
@@ -9,8 +9,8 @@
 
 import 'declarations_model.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib_2/mirrors/instance_members_with_override_test.dart b/tests/lib_2/mirrors/instance_members_with_override_test.dart
index 9cefc0b..41d1bcc 100644
--- a/tests/lib_2/mirrors/instance_members_with_override_test.dart
+++ b/tests/lib_2/mirrors/instance_members_with_override_test.dart
@@ -28,8 +28,8 @@
   /* abstract */ notOverridden();
 }
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib_2/mirrors/static_members_easier_test.dart b/tests/lib_2/mirrors/static_members_easier_test.dart
index b050a3c..a3912e9 100644
--- a/tests/lib_2/mirrors/static_members_easier_test.dart
+++ b/tests/lib_2/mirrors/static_members_easier_test.dart
@@ -10,8 +10,8 @@
 import 'stringify.dart';
 import 'declarations_model_easier.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/lib_2/mirrors/static_members_test.dart b/tests/lib_2/mirrors/static_members_test.dart
index f84bc53..aad20e7 100644
--- a/tests/lib_2/mirrors/static_members_test.dart
+++ b/tests/lib_2/mirrors/static_members_test.dart
@@ -10,8 +10,8 @@
 import 'stringify.dart';
 import 'declarations_model.dart' as declarations_model;
 
-selectKeys(map, predicate) {
-  return map.keys.where((key) => predicate(map[key]));
+selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
+  return map.keys.where((K key) => predicate(map[key]));
 }
 
 main() {
diff --git a/tests/standalone/io/addlatexhash_test.dart b/tests/standalone/io/addlatexhash_test.dart
new file mode 100755
index 0000000..fe8c166
--- /dev/null
+++ b/tests/standalone/io/addlatexhash_test.dart
@@ -0,0 +1,221 @@
+#!/usr/bin/env dart
+// 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 ../../../tools/addlatexhash.dart
+
+import 'dart:io';
+import 'package:path/path.dart' as path;
+import '../../../tools/addlatexhash.dart';
+
+final execDir = path.dirname(Platform.resolvedExecutable);
+final dartRootDir = path.dirname(path.dirname(execDir));
+final dartRootPath = dartRootDir.toString();
+
+List<String> packageOptions() {
+  if (Platform.packageRoot != null) {
+    return <String>['--package-root=${Platform.packageRoot}'];
+  } else if (Platform.packageConfig != null) {
+    return <String>['--packages=${Platform.packageConfig}'];
+  } else {
+    return <String>[];
+  }
+}
+
+// Check that the given ProcessResult indicates success; if so
+// return the standard output, otherwise report the failure
+checkAction(result, errorMessage) {
+  if (result.exitCode != 0) {
+    print(result.stdout);
+    print(result.stderr);
+    throw errorMessage;
+  }
+  return result.stdout;
+}
+
+oneTestCutMatch(line, re, expected) {
+  var result = cutMatch(line, new RegExp(re).firstMatch(line));
+  if (result != expected) {
+    throw "cutMatch '$re' from '$line' yields '$result' != '$expected'";
+  }
+}
+
+void testCutMatch() {
+  oneTestCutMatch("test", "", "test");
+  oneTestCutMatch("test", "e", "tst");
+  oneTestCutMatch("test", "te", "st");
+  oneTestCutMatch("test", "st", "te");
+  oneTestCutMatch("test", "test", "");
+}
+
+oneTestSisp(sispFun, nameSuffix, line, expected) {
+  var result = sispFun(line);
+  if (result != expected) {
+    throw "sispIsDart$nameSuffix '$line' yields $result";
+  }
+}
+
+testSisp() {
+  oneTestSisp(sispIsDartBegin, "Begin", "\\begin{dartCode}\n", true);
+  oneTestSisp(sispIsDartBegin, "Begin", " \\begin{dartCode}\n", true);
+  oneTestSisp(sispIsDartBegin, "Begin", "whatever else ..", false);
+  oneTestSisp(sispIsDartEnd, "End", "\\end{dartCode}", true);
+  oneTestSisp(sispIsDartEnd, "End", " \\end{dartCode}\t  \n", true);
+  oneTestSisp(sispIsDartEnd, "End", "whatever else ..", false);
+}
+
+// Check that the hash values of paragraphs in the specially prepared
+// LaTeX source 'addlatexhash_test_src.tex' are identical in groups
+// of eight (so we get 8 identical hash values, then another hash
+// value 8 times, etc.)
+testSameHash(String tmpDirPath) {
+  // file names/paths for file containing groups of 8 variants of a paragraph
+  const par8timesName = "addlatexhash_test_src";
+  const par8timesFileName = "$par8timesName.tex";
+  final par8timesDirPath =
+      path.join(dartRootDir, "tests", "standalone_2", "io");
+  final par8timesPath = path.join(par8timesDirPath, par8timesFileName);
+  final tmpPar8timesPath = path.join(tmpDirPath, par8timesFileName);
+
+  // file names paths for output
+  final hashName = par8timesName + "-hash";
+  final hashFileName = "$hashName.tex";
+  final hashPath = path.join(tmpDirPath, hashFileName);
+  final listName = par8timesName + "-list";
+  final listFileName = "$listName.txt";
+  final listPath = path.join(tmpDirPath, listFileName);
+
+  // dart executable
+  final dartExecutable = Platform.executable;
+  if (dartExecutable == "") throw "dart executable not available";
+
+  // actions to take
+  runAddHash() {
+    var args = <String>[]..addAll(Platform.executableArguments);
+    args.addAll([
+      path.join(dartRootPath, "tools", "addlatexhash.dart"),
+      tmpPar8timesPath,
+      hashPath,
+      listPath
+    ]);
+    return Process.runSync(dartExecutable, args);
+  }
+
+  // perform test
+  new File(par8timesPath).copySync(tmpPar8timesPath);
+  checkAction(runAddHash(), "addlatexhash.dart failed");
+  var listFile = new File(listPath);
+  var listLines = listFile.readAsLinesSync();
+  var latestLine = null;
+  var sameCount = 0;
+  for (var line in listLines) {
+    if (!line.startsWith("  ")) continue; // section marker
+    if (line.startsWith("  %")) continue; // transformed text "comment"
+    if (line != latestLine) {
+      // new hash, check for number of equal hashes, then reset
+      if (sameCount % 8 == 0) {
+        // saw zero or more blocks of 8 identical hash values: OK
+        latestLine = line;
+        sameCount = 1;
+      } else {
+        throw "normalization failed to produce same result";
+      }
+    } else {
+      sameCount++;
+    }
+  }
+}
+
+// Check that the LaTeX source transformation done by addlatexhash.dart
+// does not affect the generated output, as seen via dvi2tty and diff.
+// NB: Not part of normal testing (only local): latex and dvi2tty are
+// not installed in the standard test environment.
+testSameDVI(String tmpDirPath) {
+  // file names/paths for original spec
+  const specName = "dartLangSpec";
+  const specFileName = "$specName.tex";
+  final specDirPath = path.join(dartRootDir, "docs", "language");
+  final specPath = path.join(specDirPath, specFileName);
+  final tmpSpecPath = path.join(tmpDirPath, specFileName);
+  const specDviFileName = "$specName.dvi";
+  final specDviPath = path.join(tmpDirPath, specDviFileName);
+
+  // file names/paths for associated sty
+  const styFileName = "dart.sty";
+  final styPath = path.join(specDirPath, styFileName);
+  final tmpStyPath = path.join(tmpDirPath, styFileName);
+
+  // file names paths for output
+  const hashName = "dartLangSpec-hash";
+  const hashFileName = "$hashName.tex";
+  final hashPath = path.join(tmpDirPath, hashFileName);
+  final hashDviPath = path.join(tmpDirPath, "$hashName.dvi");
+
+  final listName = "$specName-list";
+  final listFileName = "$listName.txt";
+  final listPath = path.join(tmpDirPath, listFileName);
+
+  // dart executable
+  final dartExecutable = Platform.executable;
+  if (dartExecutable == "") throw "dart executable not available";
+
+  // actions to take; rely on having latex and dvi2tty in PATH
+  runLatex(fileName, workingDirectory) =>
+      Process.runSync("latex", [fileName], workingDirectory: workingDirectory);
+
+  runAddHash() {
+    var args = packageOptions();
+    args.addAll([
+      path.join(dartRootPath, "tools", "addlatexhash.dart"),
+      tmpSpecPath,
+      hashPath,
+      listPath
+    ]);
+    return Process.runSync(dartExecutable, args);
+  }
+
+  runDvi2tty(dviFile) =>
+      Process.runSync("dvi2tty", [dviFile], workingDirectory: tmpDirPath);
+
+  chkDvi2tty(file, subject) =>
+      checkAction(runDvi2tty(file), "dvitty on $subject failed");
+
+  // perform test
+  var renewLMHashCmd = r"\renewcommand{\LMHash}[1]{\OriginalLMHash{xxxx}}";
+  new File(styPath)
+      .copySync(tmpStyPath)
+      .writeAsStringSync(renewLMHashCmd, mode: FileMode.append);
+  new File(specPath).copySync(tmpSpecPath);
+
+  checkAction(runAddHash(), "addlatexhash.dart failed");
+  for (var i = 0; i < 5; i++) {
+    checkAction(runLatex(specName, tmpDirPath), "LaTeX on spec failed");
+  }
+  for (var i = 0; i < 5; i++) {
+    checkAction(runLatex(hashFileName, tmpDirPath), "LaTeX on output failed");
+  }
+  if (chkDvi2tty(specDviPath, "spec") != chkDvi2tty(hashDviPath, "output")) {
+    throw "dvi2tty spec != dvitty output";
+  }
+}
+
+runWithTempDir(void test(String tempDir)) {
+  final tempDir = Directory.systemTemp.createTempSync("addlatexhash_test");
+  try {
+    test(tempDir.path);
+  } finally {
+    tempDir.delete(recursive: true);
+  }
+}
+
+main([args]) {
+  testCutMatch();
+  testSisp();
+
+  runWithTempDir(testSameHash);
+  // latex and dvi2tty are not installed in the standard test environment
+  if (args.length > 0 && args[0] == "local") {
+    runWithTempDir(testSameDVI);
+  }
+}
diff --git a/tests/standalone/io/addlatexhash_test_src.tex b/tests/standalone/io/addlatexhash_test_src.tex
new file mode 100644
index 0000000..8f2881b
--- /dev/null
+++ b/tests/standalone/io/addlatexhash_test_src.tex
@@ -0,0 +1,825 @@
+\documentclass{article}
+\usepackage{epsfig}
+\usepackage{color}
+\usepackage{dart}
+\usepackage{bnf}
+\usepackage{hyperref}
+\usepackage{lmodern}
+\newcommand{\code}[1]{{\sf #1}}
+\title{Test File used by addlatexhash}
+
+\begin{document}
+\maketitle
+\tableofcontents
+\newpage
+
+\pagestyle{myheadings}
+\markright{Test file used by addlatexhash}
+
+% begin Ecma boilerplate
+\section{Scope}
+\LMLabel{ecmaScope}
+
+% Selected certain paragraphs from the spec, created exactly eight
+% copies of each of them, modifying the copies in ways that should
+% not affect the hash values; to verify correct behavior, grep for
+% '^ *\\LMHash' in the output LaTeX source or take every 2nd line
+% from the list file, and check that the sequence of hashes consists
+% of subsequences of identical values, all with length eight.
+
+% Test a "normal" paragraph -------------------------------------------
+
+%0 original
+\LMHash{}
+This Ecma standard specifies the syntax and semantics of the Dart programming language.  It does not specify the APIs of the Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+%1 enlarge white space; NB: cannot add new white space, just enlarge
+\LMHash{}
+This Ecma         standard specifies the syntax and semantics of the Dart programming language.  It does not 		specify the APIs of the Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+%2 insert extra newlines
+\LMHash{}
+This Ecma standard specifies the syntax and semantics of the Dart
+programming language.  It does not specify the APIs of the Dart
+libraries except where those library elements are essential to the
+correct functioning of the language itself (e.g., the existence of
+class \cd{Object} with methods such as \cd{noSuchMethod},
+\cd{runtimeType}).
+
+%3 insert comments
+\LMHash{}
+This Ecma standard specifies the syntax and semantics of the Dart % blah
+programming language.  It does not specify the APIs of the Dart%blah
+libraries except where those library elements are essential to the% blah
+correct functioning of the language itself (e.g., the existence of
+class \cd{Object} with methods such as \cd{noSuchMethod},
+\cd{runtimeType}). % blah blah
+
+%4 insert commentary
+\LMHash{}
+This Ecma standard specifies the syntax and semantics of the Dart programming language.  It does not specify the APIs of the Dart libraries except where those library elements are \commentary{whatever} essential to the correct functioning of the language itself (e.g., the existence of class \cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+%5 insert rationale
+\LMHash{}
+This Ecma standard specifies the syntax and semantics of the Dart programming language.  It does not specify the APIs of the \rationale{whatever} Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+%6 insert nested rationale/commentary
+\LMHash{}
+This Ecma standard specifies \rationale{whatever \commentary{whatever}} the syntax and semantics of the Dart programming language.  It does not specify the APIs of the Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+%7 insert all; note that this block ends with more blank lines, too
+\LMHash{}
+This Ecma         standard 		specifies the syntax \rationale{whatever \commentary{whatever}} and semantics of the Dart programming language.  It does not specify the APIs of the
+             Dart libraries except where those library elements are
+essential to the correct functioning of
+the language itself (e.g., the existence of class
+\cd{Object} with methods such as \cd{noSuchMethod}, \cd{runtimeType}).
+
+
+
+
+
+\section{Conformance}
+\LMLabel{ecmaConformance}
+
+% Test a paragraph including math mode --------------------------------
+
+%0 original
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
+
+%1 enlarge white space in math mode; NB: cannot add new ws, even in math mode
+\LMHash{}
+A list $x_1,        \ldots,      x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
+
+%2 enlarge other white space
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes         any list of $n$ elements
+of the form $x_i, 1 \le i \le n$.
+		 Note that $n$ may be zero, in
+which case the list is empty. We use such lists
+ extensively throughout this
+specification.
+
+%3 add comments, also in math mode
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements% blah % blah
+of the form $x_i, 1% blah
+\le i % blah
+ \le n$. Note that $n$ may be zero, in which
+% blah blah %
+case the list is empty. We use such lists extensively throughout this
+specification.
+
+%4 even multiple newlines do not count when before '$'
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form
+
+
+$x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
+
+%5 multiple new lines and leading ws before '$', and comments
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that
+
+% blah blah blah blah blah blah blah blah
+% blah blah blah blah blah blah blah blah
+% blah blah blah blah blah blah blah blah
+% blah blah blah blah blah blah blah blah
+
+ 	 $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
+
+%6 precede paragraph with comments
+\LMHash{}
+% blah
+% blah
+%
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification.
+
+%7 insert comment lines in the middle of the paragraph
+\LMHash{}
+A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero,
+%
+% blah
+%
+in which case the list is empty. We use such lists extensively throughout this specification.
+
+
+% Test paragraph plus dartCode, with commentary -----------------------
+
+%0 original
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
+%1 delete/insert in the commentary, altering number of paragraphs in there
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {% NB: this space before brace begin is ignored by LaTeX
+New paragraph.
+
+New paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph new paragraph.
+
+New paragraph,
+new paragraph, and
+new paragraph. % blah \commentary{ with unbalanced '{'
+
+  \rationale{nested rationale}
+
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
+%2 remove commentary entirely, including newlines
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
+%3 change the amount of indentation in dartCode
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+      \CLASS{} HighlyStrung \{
+                  String() $=>$ "?";
+      \}
+\end{dartCode}
+
+%4 change other white space in dartCode
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+
+\CLASS{} 			HighlyStrung \{
+String() $=>$ "?";
+
+
+\}
+\end{dartCode}
+
+%5 add comments in dartCode
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";% blah % blah
+\} % blah
+%blah
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{dartCode}
+
+%6 remove commentary
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
+%7 add comment lines after the block
+\LMHash{}
+If a  declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$.
+
+\commentary {
+A consequence of these rules is that it is possible to hide a type with a method or variable.
+Naming conventions usually prevent such abuses. Nevertheless,the following program is legal:
+}
+
+\begin{dartCode}
+\CLASS{} HighlyStrung \{
+  String() $=>$ "?";
+\}
+\end{dartCode}
+
+% blah blah blah blah blah blah blah blah blah
+% blah blah blah blah blah blah blah blah blah
+% blah blah blah blah blah blah blah blah blah
+% no blank lines before \section this time
+\section{Variables}
+\LMLabel{variables}
+
+% Test paragraph followed by grammar ----------------------------------
+
+%0 original
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier (`,' identifier)*
+      .
+
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+
+
+
+
+  \end{grammar}
+
+%1 collecting grammar rules on single lines
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+  {\bf variableDeclaration:} declaredIdentifier (`,' identifier)* .
+
+  {\bf declaredIdentifier:} metadata finalConstVarOrType identifier .
+
+  {\bf finalConstVarOrType:}\FINAL{} type?; \CONST{} type?; varOrType .
+
+  {\bf varOrType:}\VAR{}; type .
+
+  {\bf initializedVariableDeclaration:} declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* .
+
+  {\bf initializedIdentifier:} identifier (`=' expression)? .
+
+  {\bf initializedIdentifierList:} initializedIdentifier (`,' initializedIdentifier)* .
+\end{grammar}
+
+%2 adding comments to grammar
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}% blah
+%blah
+{\bf variableDeclaration:}%blah
+      declaredIdentifier (`,' identifier)*%blah
+      .%blah
+%blah
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .%        blah
+
+
+
+%blah
+  \end{grammar}%blah
+
+%3 removing empty lines from grammar
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier (`,' identifier)*
+      .
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+ {\bf varOrType:}\VAR{};
+	type
+    .
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+  \end{grammar}
+
+%4 inserting comment block in grammar
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier (`,' identifier)*
+      .
+
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+%% {\bf finalConstVarOrType:}\FINAL{} type?;
+%%            \CONST{} type?;
+%% 	varOrType
+%%     .
+
+%%  {\bf varOrType:}\VAR{};
+%% 	type
+%%     .
+
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+
+
+
+
+  \end{grammar}
+
+%5 adding commentary/rationale in grammar (may not happen, is OK anyway)
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier (`,' identifier)*
+      .
+
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+
+\rationale{blah \commentary{blah}}
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+
+
+
+
+  \end{grammar}
+
+%6 inserting newlines in grammar (not new paragraph, only at existing ws)
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier
+(`,'
+identifier)*
+      .
+
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType
+                                   identifier
+    .
+
+{\bf
+finalConstVarOrType:}\FINAL{}
+type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)?
+                         (`,' initializedIdentifier)*
+                         % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+
+
+
+
+  \end{grammar}
+
+%7
+\LMHash{}
+Variables are storage locations in memory.
+
+\begin{grammar}
+{\bf variableDeclaration:}
+      declaredIdentifier (`,' identifier)*
+      .
+
+{\bf declaredIdentifier:}
+      metadata finalConstVarOrType identifier
+    .
+
+{\bf finalConstVarOrType:}\FINAL{} type?;
+           \CONST{} type?;
+	varOrType
+    .
+
+ {\bf varOrType:}\VAR{};
+	type
+    .
+
+ {\bf initializedVariableDeclaration:}
+      declaredIdentifier (`=' expression)? (`,' initializedIdentifier)* % could do top level here
+    .
+
+{\bf initializedIdentifier:}
+      identifier (`=' expression)? % could do top-level here
+    .
+
+{\bf initializedIdentifierList:}
+      initializedIdentifier (`,' initializedIdentifier)*
+    .
+
+
+
+
+  \end{grammar}
+
+\subsection{Evaluation of Implicit  Variable Getters}
+\LMLabel{evaluationOfImplicitVariableGetters}
+
+% Test itemized list, right after paragraph ---------------------------
+
+%0 original
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+\begin{itemize}
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+
+%1 insert blank lines and comments between paragraph and list ---------
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+
+%blah
+%blah
+
+\begin{itemize}
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+
+%2 insert line break before each item
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+\begin{itemize}
+\item
+{\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+\item
+{\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+\item
+{\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+
+%3 insert blank/comment lines between,before,after items, and on begin/end
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+\begin{itemize}%blah
+
+% blah
+
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+
+\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+
+%blah
+%blah
+%blah
+
+
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+
+% blah
+\end{itemize}%blah
+
+%4 insert commentary/rationale inside itemized list
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+\begin{itemize}
+\commentary{maybe this will not happen, but it is ok}
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$.
+\rationale{but rationale at the end of an item seems to make sense}
+\item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+\rationale{and we can of course have it immediately after the list}
+
+%5 add line breaks in items, with/without indentation
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows:
+\begin{itemize}
+\item {\bf Non-constant variable declaration with initializer}. If $d$
+is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,
+\code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;},
+\code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; },
+\code{\STATIC{} \FINAL{} $v$ = $e$; } or
+\code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored
+into $v$ then the initializer expression $e$ is evaluated. If, during
+the evaluation of $e$, the getter for $v$ is invoked, a
+\code{CyclicInitializationError} is thrown. If the evaluation succeeded
+yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In
+any case, $r$ is stored into $v$. The result of executing the getter
+is $r$.
+\item  {\bf Constant variable declaration}. If $d$ is of one of the
+    forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },
+    \code{\STATIC{} \CONST{} $v$ = $e$; } or
+    \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the
+    value of the compile time constant $e$.
+    \commentary{Note that a compile time constant cannot depend on
+      itself, so no cyclic references can occur.}
+    Otherwise
+\item {\bf Variable declaration without initializer}. The result of
+    executing the getter method is the value stored in $v$.
+\end{itemize}
+
+%6 add line breaks, then "eliminate" them with comments
+\LMHash{}
+Let $d$ be the declaration of a static or instance%
+variable $v$.  If $d$ is an instance variable, then the %
+invocation of the implicit getter  of $v$ evaluates to%
+                   the value stored in $v$.
+If $d$ is a static or library variable then the implicit %
+getter method of $v$ executes as follows: %
+
+\begin{itemize}
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. %
+
+\item  {\bf Constant variable declaration}. If $d$ is of one of the%
+ forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  %
+\code{\STATIC{} \CONST{} $v$ = $e$; }  or%
+\code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+
+%7 eliminate line break before environment and before \item
+\LMHash{}
+Let $d$ be the declaration of a static or instance variable $v$.  If $d$ is an instance variable, then the invocation of the implicit getter  of $v$ evaluates to the value stored in $v$.
+If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows: \begin{itemize}
+\item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} ,  \code{$T$ $v$ = $e$;} ,   \code{\FINAL{} $v$ = $e$;} ,  \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. \item  {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } ,  \code{\CONST{} $T$  $v$ = $e$; },  \code{\STATIC{} \CONST{} $v$ = $e$; }  or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.}
+Otherwise%
+\item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$.
+\end{itemize}
+
+% Test multiple commentary/rationale blocks in succession -------------
+
+%0 original
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+
+\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
+}
+
+\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.
+
+}
+
+%1 remove commentary/first
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+
+\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.
+
+}
+
+%2 remove rationale second
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+
+\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
+}
+
+%3 remove both
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+
+%4 make first in paragraph, even with \par (double newline)
+\LMHash{}
+\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
+}
+
+\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.
+
+}
+
+The run time type of a function object always implements the class \cd{Function}.
+
+%5 insert misleading 'dartCode' comments
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+
+\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runt
+imeType} will actually be \cd{Function}, or that any two distinct function objec
+%\begin{dartCode}
+ts necessarily have the same runtime type.
+}
+
+\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+%\end{dartCode}
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.
+
+}
+
+%6 remove empty lines between normative and non-normative text
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.
+\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
+}
+\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.
+
+}
+
+%7 remove white space between normative and non-normative text
+\LMHash{}
+The run time type of a function object always implements the class \cd{Function}.\commentary{
+One cannot assume, based on the above, that  given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type.
+}\rationale{
+It is up to the implementation to choose an appropriate representation for functions.
+For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}.}
+
+% Test structure command (\section) with leading white space ----------
+
+ \subsection{ Equality}
+ \LMLabel{equality}
+
+ The subsection should end the hashing block, so these words should
+ not affect the previous hash value.
+
+% ---------------------------------------------------------------------
+
+\end{document}
diff --git a/tests/standalone/io/ansi_supported_test.dart b/tests/standalone/io/ansi_supported_test.dart
new file mode 100644
index 0000000..643ae7a
--- /dev/null
+++ b/tests/standalone/io/ansi_supported_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+testStdout(Stdout s) {
+  try {
+    s.supportsAnsiEscapes;
+  } catch (e, st) {
+    Expect.fail("$s.supportsAnsiEscapes threw: $e\n$st\n");
+  }
+  Expect.isNotNull(s.supportsAnsiEscapes);
+  Expect.isTrue(s.supportsAnsiEscapes is bool);
+  if (s.supportsAnsiEscapes) {
+    s.writeln('\x1b[31mThis text has a red foreground using SGR.31.');
+    s.writeln('\x1b[39mThis text has restored the foreground color.');
+  } else {
+    s.writeln('ANSI escape codes are not supported on this platform');
+  }
+}
+
+main() {
+  testStdout(stdout);
+  testStdout(stderr);
+  try {
+    stdin.supportsAnsiEscapes;
+  } catch (e, st) {
+    Expect.fail("stdin.supportsAnsiEscapes threw: $e\n$st\n");
+  }
+  Expect.isNotNull(stdin.supportsAnsiEscapes);
+  Expect.isTrue(stdin.supportsAnsiEscapes is bool);
+}
diff --git a/tests/standalone/io/arguments_test.dart b/tests/standalone/io/arguments_test.dart
new file mode 100644
index 0000000..9148217
--- /dev/null
+++ b/tests/standalone/io/arguments_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.
+//
+// DartOptions=10 arguments_test 20
+
+import "package:expect/expect.dart";
+
+main(List<String> args) {
+  // Basic test for functionality.
+  Expect.equals(3, args.length);
+  Expect.equals(10, int.parse(args[0]));
+  Expect.equals("arguments_test", args[1]);
+  Expect.equals(20, int.parse(args[2]));
+  // Cannot add an additional argument.
+  Expect.throwsUnsupportedError(() => args.add("Fourth"));
+}
diff --git a/tests/standalone/io/async_catch_errors_test.dart b/tests/standalone/io/async_catch_errors_test.dart
new file mode 100644
index 0000000..431057b
--- /dev/null
+++ b/tests/standalone/io/async_catch_errors_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:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+var events = [];
+
+Future testSocketException() {
+  var completer = new Completer();
+  runZoned(() {
+    Socket.connect("4", 1).then((Socket s) {
+      Expect.fail("Socket should not be able to connect");
+    });
+  }, onError: (err) {
+    if (err is! SocketException) Expect.fail("Not expected error: $err");
+    completer.complete("socket test, ok.");
+    events.add("SocketException");
+  });
+  return completer.future;
+}
+
+Future testFileSystemException() {
+  var completer = new Completer();
+  runZoned(() {
+    new File("lol it's not a file\n").openRead().listen(null);
+  }, onError: (err) {
+    if (err is! FileSystemException) Expect.fail("Not expected error: $err");
+    completer.complete("file test, ok.");
+    events.add("FileSystemException");
+  });
+  return completer.future;
+}
+
+main() {
+  // We keep a ReceivePort open until all tests are done. This way the VM will
+  // hang if the callbacks are not invoked and the test will time out.
+  asyncStart();
+  testSocketException().then((_) => testFileSystemException()).then((_) {
+    asyncEnd();
+    Expect.listEquals(["SocketException", "FileSystemException"], events);
+  });
+}
diff --git a/tests/standalone/io/bytes_builder_test.dart b/tests/standalone/io/bytes_builder_test.dart
new file mode 100644
index 0000000..5b6a6b9
--- /dev/null
+++ b/tests/standalone/io/bytes_builder_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.
+
+import "dart:io";
+import "dart:typed_data";
+import "package:expect/expect.dart";
+
+main() {
+  for (var copying in [true, false]) {
+    var b;
+    testLength(n) {
+      Expect.equals(n, b.length);
+      if (n == 0) {
+        Expect.isTrue(b.isEmpty, "isEmpty: #${b.length}");
+        Expect.isFalse(b.isNotEmpty, "isNotEmpty: #${b.length}");
+      } else {
+        Expect.isTrue(b.isNotEmpty, "isNotEmpty: #${b.length}");
+        Expect.isFalse(b.isEmpty, "isEmpty: #${b.length}");
+      }
+    }
+
+    b = new BytesBuilder(copy: copying);
+    testLength(0);
+
+    b.addByte(0);
+    testLength(1);
+
+    b.add([1, 2, 3]);
+    testLength(4);
+
+    b.add(<int>[4, 5, 6]);
+    testLength(7);
+
+    b.add(new Uint8List.fromList([7, 8, 9]));
+    testLength(10);
+
+    b.add(new Uint16List.fromList([10, 11, 12]));
+    testLength(13);
+
+    var bytes = b.toBytes();
+    Expect.isTrue(bytes is Uint8List);
+    Expect.listEquals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], bytes);
+    testLength(13);
+
+    b.add("\x0d\x0e\x0f".codeUnits);
+    testLength(16);
+
+    bytes = b.takeBytes();
+    testLength(0);
+    Expect.isTrue(bytes is Uint8List);
+    Expect.listEquals(
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], bytes);
+
+    b.addByte(0);
+    testLength(1);
+
+    b.clear();
+    testLength(0);
+
+    b.addByte(0);
+    testLength(1);
+  }
+}
diff --git a/tests/standalone/io/certificates/README b/tests/standalone/io/certificates/README
new file mode 100644
index 0000000..6ecd518
--- /dev/null
+++ b/tests/standalone/io/certificates/README
@@ -0,0 +1,70 @@
+    This directory, tests/standalone/io/certificates, contains the
+X509 TLS certificates and private keys needed to run tests of Dart's
+secure networking code.  The SecureSocket and SecureServer classes
+are tested by making TLS (formerly called SSL) connections, secured
+by certificates from a self-signed test root authority.
+
+The certificates are created by running ../create_sample_certificates.sh
+in a bash or sh shell, with the openssl tools installed.  Run the script
+twice to create the untrusted_* files.
+
+PEM files:
+
+server_chain.pem:
+  Contains the chain of certificates, from the self-signed
+test certificate authority, through the intermediate CA, to the server
+certificate, used on the server side of a test connection.
+
+server_key.pem:
+  Contains the private key for the server certificate
+
+trusted_certs.pem:
+  Contains the self-signed certificate of the test certificate authority.
+This certificate is set as "trusted" by the client side of the connection
+in its SecurityContext object, so that a verified TLS connection to the
+server can be made.
+
+untrusted_server_chain.pem:
+  Contains a chain of certificates, from a different self-signed
+test certificate authority, through an intermediate CA, to a server
+certificate, used on the server side of a test connection that is intended
+to fail because the client does not accept this certificate authority
+
+untrusted_server_key.pem:
+  Contains the private key for the untrusted server certificate
+in untrusted_server_chain.pem
+
+*_malformed.pem:
+  Truncated PEM formatted certificates used to test error handling.
+
+PKCS12 files:
+
+server_key.12:
+  Created with:
+  $ openssl pkcs12 -export -inkey server_key.pem -out server_key.p12 -nocerts
+  with password 'dartdart'
+
+server_chain.p12:
+  Created with:
+  $ openssl pkcs12 -export -in server_chain.pem -out server_chain.p12 -nokeys
+  with password 'dartdart'
+
+client1_key.p12:
+  Created with:
+  $ openssl pkcs12 -export -inkey client1_key.pem -out client1_key.p12 -nocerts
+  with password 'dartdart'
+
+client1.p12:
+  Created with:
+  $ openssl pkcs12 -export -in client1.pem -out client1.p12 -nokeys
+  with password 'dartdart'
+
+trusted_certs.p12:
+  Created with:
+  $ openssl pkcs12 -export -in trusted_certs.pem -out trusted_certs.p12 -nokeys
+  with password 'dartdart'
+
+client_authority.p12:
+  Created with:
+  $ openssl pkcs12 -export -in client_authority.pem -out client_authority.p12 -nokeys
+  with password 'dartdart'
diff --git a/tests/standalone/io/certificates/bad_server_chain.pem b/tests/standalone/io/certificates/bad_server_chain.pem
new file mode 100644
index 0000000..3c5024b
--- /dev/null
+++ b/tests/standalone/io/certificates/bad_server_chain.pem
@@ -0,0 +1,58 @@
+-----BEGIN CERTIFICATE-----
+MIIDJzCCAg+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0
+WjAXMRUwEwYDVQQDDAxiYWRsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC6gVBNsFLEkomxJ1VRe5rZ1ELduRLHJKio9zTrh+o/6EaCZ4X6
+EIr3CwVx7UiBDRyCApGZXbqvtNbP/ihbjRvxmlvCSL9ztF9tNrLqsaEq4w5KvQDT
+5u27+pAzdLjjoFTK6VZfw+AhEZHxiokEDDYB3t6gWkfabOstDouLyEYL25RLKaGQ
+v/Qb7XU6K4f20OnuXVoQ4FxNdqtvm7TgmXBT0kp+f62q6BvLUIzewpblBlgT5h3h
+KAZF7RDpGBxRgYxA6ZH4n3mv4kh84YtTODRGfb8ugdaQjrgTWOhQ4nddcdR5TVww
+A8Jp+G000RQ97Go0zgd29CicKF96zbGdKFkZAgMBAAGjdTBzMAwGA1UdEwEB/wQC
+MAAwHQYDVR0OBBYEFG8s5yvy1kAoNjJ5PYrx9RNSPFJXMB8GA1UdIwQYMBaAFCpT
+tHybjDJ/Jz25uI9Bxikc1muYMA4GA1UdDwEB/wQEAwIDqDATBgNVHSUEDDAKBggr
+BgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAgom55wfxp9ywWKZOzaGCa+uXZjPK
+rmdUcnJLduRdnchuIsQUZa3Ijpzn7Dw+UZV8ggxvU0L07PbT0QlZUoKhDj6BlZ4W
+TAseBh5QyBUeEdMU+Tr2fXGM6+mmVURBLTX5I2Chmnw2ymqqUK8MtbUhPXbfZayV
+eUV35iloOhm3q/5rKBtfdNq31zrg+Naam6/UyRgBhinweFFXiYeZRpctD3w3cA3g
+RGjuNNNRASZZzAXGiE4IOv9drd0/wGajwBT1DJDQOAxZPfADC3wEcDRG4ve1SYHY
+5N3AlidXe8dPDePhlxH3JH9s2WPi6lgiHQSmtzyeehbzqpJ9JCBM5BerdQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/bad_server_key.pem b/tests/standalone/io/certificates/bad_server_key.pem
new file mode 100644
index 0000000..4b5670a
--- /dev/null
+++ b/tests/standalone/io/certificates/bad_server_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4zAcBgoqhkiG9w0BDAEBMA4ECPLRqWLveTDuAgIIAASCBMGjMwpu3Hy4cuO7
+i3p2EyH+UJGm9J/KcRN2ys6E5rwCdLHtURLmdWsmtNkDNTvmgdllXfdVhO9XavRJ
+ShBSvTzvOokpl/nxRaFmhEhMWskdGpP1WSp+GtQiVHM2gczDR2jNZDZKWEnZfU5B
+CUt0VJkokJZxmdeSpFIrTTJxcOQZEsbb1ujrAMpWqEvIGq+U2Is7A5RxWJl1XKmY
+5QB9nfw5Olj0J499kMKJx8WjRhmfQHu+qMpN2HglBVK44fnk/I5ilNdhuScuaKPZ
+csOv5D5Ojlgc6hQG1zCPh8lRNH1MXLd2BMwEJqPSKNbvfrUWvr7BnJMoOdnlZwaH
+73/zJrMwuUpZzAm2sgHZlJhELoYyK0A40IhAz4u9XF1iv35yK2D6/O2qJO6VUzqD
+TsdSnUYaUTZkZdgfucR+EbmPSw7r+QYEsHFzErPTUR64hwIeC3bCv0Q4hrPskxKj
+135iDQDbuCykeNe8s51qgEt8oawdig/Anaguksuj/eKGTWZXPrhA3LTYqBkaX8ao
+XFWkj3ALvjRHCeLfQ5AlXyd3mJiHl93pxH9GIaTiL66ptYvfcN5tERcD6GL/sUXh
+vJ0kr8HsBS9WTFvVg4dzQ9NAqtRoDB1IUqEq2dLys/gjrhE26tmUnuaXiOuokSWx
+HXEK/2pWAqZ/ZA7vbQ/DyV25TDeEP3SRKeTDLdlWBjTNUKyBv3nfsoZBK1K2wOUh
+UDmB3TMBEdXI6L2FvjxMuDRJxruhn7HhRz7ifsizRHPyaPDbUFF9IK/x9qPAzufK
+lk6NqqcgJdNg8wxv/dVYAHeJmMOhTau9CL6N7AYo2VDWphlZSjBgtTZw7sY739c2
+35ziR9yBoJyveFcQko01ycJrjhivn3cqbFXZfsIbecDKz+8qZhWjKw/yysv0X6tI
+tB1btpWtlVB8h7WlXWgUGJWKCUFXRC1fCJA5W7LoTnvZ9VvYMBRKUbDsMiSWNcTZ
+mLmJj0yIhve9uCHsFXBidTCT751CYucaZYvOqNr3pKf4eTQQNCYB5Pt6jx4V7Xks
+ZDjr5ljVy6Ux6NweQT2Zs/hOnuS3q1XoLbRVsW9d9YttahnNyjP8il3HphSzBHOF
+SUReTlgAHEbSUZTZ1z2GXFblUJPb2syfJOIXP5qHQtSrGN3CkQ//JvysxlOck41h
+fLO6TZUadorgEHqb+en6h6gVvDvI3i0T66yWwurhlEvWZepAWetzSv64VsVGXEjc
+lrT8yj6AAZYISoYZU0vtM0tP+FDqvyA597DZMiDDBU6chmGxWhcnaqIIDTP2KQIJ
+Z0NAYp924NHAgnTq1FbXxllej6vxcCwymsnXGyCMhsOt1RTAVHeY0uZ5qPCToJ30
+xS/WTrVH5z0xtp2Qz+INFleNnseYKBJvEDfk+gK0sLm533fehnFeB+GgNqqV9hKc
+bLpU+C3VrsxX0JLWYgfweVDT+jT78FXzUIkWykvBGv+iv+ztFUFiopDzJzfLriH8
+K4kG2o/K3MQWrygjnt+iTjpBe08auX9Ot8X65ygArOa0zOy0nUwSQGyPXL/7L3dQ
+LqS6ZBpreqXClTeegKH8SwEYnXLFNDuU1GuD+pRyQJVWYfqiiWeenaKpCi73VWaK
+J+9e86VqcQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/client1.p12 b/tests/standalone/io/certificates/client1.p12
new file mode 100644
index 0000000..69a674d
--- /dev/null
+++ b/tests/standalone/io/certificates/client1.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1.pem b/tests/standalone/io/certificates/client1.pem
new file mode 100644
index 0000000..468a677
--- /dev/null
+++ b/tests/standalone/io/certificates/client1.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAe+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAQMQ4w
+DAYDVQQDDAV1c2VyMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0k
+FC9D1LDt0as0Kk3EbMKR9IXBtKazVOXq1y3VYmSM+r8l70HViKZOQ13vWHBt+iYI
+2ATt+lFfKrAo2xO74d7bJD6ag12Ar60mpfVWO1lrmbSzGGsfJZl1kI7Z9SJ4RQCp
+xqAKu+ZtIY40fO7YqRFT+yPjjdcsNOYHedATa4coq1ZHnFbU4HZgerFIeMCHr2Mb
+MPuqraJuk4G7yJgPWMwNawKKfWWiH4aRNGgmVqInVTh6hLLFC2po0koF8h4fyVz9
+BmptVyn7+/V5OOWteiaaNanRlSc9ozljSxVnqSUD9JuaIINd4+0Lf5Yp2hcPj54l
+Mt8q51euv2JGzk5NLOcCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUZOyE
++fTDi2XHfAg9q9Ci4B3/PKIwHwYDVR0jBBgwFoAU+TlPoMTEPn2GHUDuD49Nm+iq
+vwwwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAADdlG1z
+kHKAI4HQojtx8yWM/D5q48/5wQjmsx6oBfaWPobL1mkc0iPQ6GNARY1Mv8OPbGkk
+8M00qVikaUyA3K14mZBzNY1Pprr06JRlDuYZABU7Jcfd6pe1LAfM0GMlng5KbHlK
+NqsECNQNIihEECdJ9UxEl191aAf4hnfvnL+RRaalCCeM9LZY+CTCuG1RH61H8Dxl
+Fq615+4DP7bKHUf2FiYVcqu9MqLCw6YasrCNFcBQuZuzO/3HUyBWHOQ2jb5w5uID
+cDsV5rGtQjc0DNc7v34lHYsfP8BWRF+z/VE865wgupQ3f5OTTHPBeMy1bO0t5rU6
+iDdImoz2KZ3ZwDc=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
new file mode 100644
index 0000000..8f5681d
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key.pem b/tests/standalone/io/certificates/client1_key.pem
new file mode 100644
index 0000000..16c513c
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE5DAcBgoqhkiG9w0BDAEBMA4ECDBZgjf6kratAgIIAASCBML/IWUC3eylBatQ
+SawxuYM81Ak+LnjidlC+/3APnYNFdppoUbZu8WK9Nj/SPQBXnpuGpVuUWWaIkjzI
+d3tivlboh17M6TBSBiI6wopmi4uO7k+BKTCH0chdqKM8OjJajpeGOfejW7Jojnr8
+Yx8G3IYO5DWWXSU7kp4w5WwN93vvRZh4pmLwOIFLwdGVNooBu1FRBaguPFQoWgO+
+JFbT3qDYvpttdsgtOalqpudHcQteapgQkUfKwk+unB+dgxS3sTTY+Zy9ClnArd0d
+1wlgOm34jgDxxWIdfaa/l/hcz82F45HeA/jwvP7/EXTni3hkDT92vTMHJQPKguhL
+V+be+XNnGihNT3k6fXpHAr6Y+HXN+4nqd/ndKRkfzVeZkNMzjFgeWy/LQ1bruMSP
+Cz/RdpatxH/fRvazCXe160YIB25cwFMUvt4saiN3SvHETxC02SsA6hY1TZB2UOmO
+/PjyXiXB6nyHchwEbTkzwnHKJSDX5FlAvweOkJ9PhKZIgfXRG/5orqXWqczUV+Vk
+FyC4338kCtY8sGYlbBvusNqugkbOEMaKUtJd4R2vvXUUbcybrAmjHg10To1uHAxw
+2xE/gewcvrPTdo4upV4JzyGszJte3MWspv/tyXY/s8F1/ENwatPOZWqMDAa3WSaz
+dzi8cfQFVo2Pq2b2TtrBE0KPKt1Zw7zIHYcyWnGJaLTzXhFdaw+8jY1+tudnBtzE
+l84fqwBX/9sAjOdCz1TkIskdpDhWQm33MvTbWluj1FvEQMYgLpLpLIOs1kw8DMNE
+TH6rrVnMDpdr9bGOPwmxBa/SC6n0EHGczSJ0IyGt5GrjOLGhPgYvETUDCH00GUY7
+cH+v6S4Lh4Z19aBcDEcW+drU/I+HfoC1qhnqksvNJFeYbEDqTcXD3De2zd6MzMiL
+qoxaNWshoAYqMbNdZNeCjlJTFq4mU2v+CxLKxUmnoLzkPsrfdniEfTwCg+LoERCk
+t588o6N8g3JfPDjpTWiH17KEuiKvDYPfheKr3Zu2Zzgd3Rm63l80vINtYffTfKB+
+U/nuGRzX0bRqWLZlEEnUJxnSYurG7DH7uozCgozbkVqYRE75/wxBDNSeOWSy5HDq
+0UeRafBOJmGU/7jhNLnKP8YZ5o+XBI3oQMfLb2q3uNbLTc73vqWoFCC7hCUJnKq9
+z8yD7mETNYTyS1g7uGt2yWmuYinyn+VQkg/f2ExQ36HCjzkoaJyobpNgdzoTF0+q
+dhzCAfb3C04p/iUIXFQCD1YdZVgwXCmAgxRKbfJaW6B1FFHe3PYzac5RQtvLJQ0q
+u8sUFlkhr/ax5wUXhILXnvH0S7QtEcGTRJawna7TBZWk4kvTlU0N0DcLU+LKUmws
+3seuvYROHZ6VSrGikL5IMVZl+h47Ub4HMTvdWAiaSMchl3fxVFW5kGJcAMvoI9ZO
+ENIWeZVgXrz7FPfnfYnLLNXeHC1LM0hYHztkaXuBC4ujupPmy4/oHNmQXx/yufDK
+wmQEWsFPf/JrwraW6PAX+/FvZ2G97LIDoxB4TjaIdBXKr17YRAOD9PCcqWBtFrHu
+4HXwSF4tALbDlMryhjMNOOs0jWjl+jx1LtZ+I+USOjX+3G1ZBWgl5Ps29YMJYF5e
+NRqyXPpLaco=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
new file mode 100644
index 0000000..8c1f7d8
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key_malformed.pem
@@ -0,0 +1,17 @@
+MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
+B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
+w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
++qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
+HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
+/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
+xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
+g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
+38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
+q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
+XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
+O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
+gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
+M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
+I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
+nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
+HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
diff --git a/tests/standalone/io/certificates/client2.pem b/tests/standalone/io/certificates/client2.pem
new file mode 100644
index 0000000..3999216
--- /dev/null
+++ b/tests/standalone/io/certificates/client2.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAQMQ4w
+DAYDVQQDDAV1c2VyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBX
+SxFoCWZxTjBXABqf9ygEicJDLcBEnStDbo+XE7CGDNkf6AmYy9cFpNK3brxfmU3x
+ZKizie8fLeTMpaEAAR73epPn9Ui3JzP4e12HacLXVIZkDdoOjCcksf1n6CTXSTeC
+K2h8aO5oqC7ouwUcWbCbdLu+OxohAMg/vmDXvRhJC9uoJyW8hYJwpAuErh/W/DuX
+LUgAAGNnztth5UWmrD4b9vdhU6yR2t5Gj2DP44Ow5rlurqC0vY87pe+rMal26mF0
+GLYCzrJOdEwy4WGCuTxXtbqvud9NIV++61cPtOu+GQKwI6/KJ5TEKsLGEbqQViM4
+rUguOwndm/7HK00nbPECAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUKpNM
+YZQHavaPs/m1k7d3a9QbbTQwHwYDVR0jBBgwFoAU+TlPoMTEPn2GHUDuD49Nm+iq
+vwwwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAJSyKalJ
+wh1wQvmZ6sa7imzsWwQ70Kr8NgDZFm8Ds1dkfzxsP6lBey8HVY6nDQD2LzJth9ny
+2AXcHvT9DKRto1cJI5z8/H+E7oKzPAlJjnmhL2dIk6als2KYfBHu5eLyaoWOCvNx
+wd4wk+JrMIQuVeIQwrG2PPDSUffScb5y5OeW1PvmnAJNTI9bHSIA4/GN45/l3FEW
+IZuOBfv5DjubYoWT+OJMfSXoqIU/wciyx+SsSPHQ8F8Q6eLgxhF74eqIrIWstZIf
+bwo83QHOpqXxEkzny4Pbdcis6rGWagH6JXHoiIHcHlsRveMEUGLUJaV0nxN2DgUa
+Umod67RaTcbdses=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client2_key.pem b/tests/standalone/io/certificates/client2_key.pem
new file mode 100644
index 0000000..8bb2fd8
--- /dev/null
+++ b/tests/standalone/io/certificates/client2_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE5DAcBgoqhkiG9w0BDAEBMA4ECOesX1fugaR0AgIIAASCBMIl6TrcBn0oHRHl
+X3MSXdAyEMLYBaSVgyRUt1gu0WhyT9uu1xlB1VGu14QHY3uqvTMZpJabSYsafV+P
+3dbFmk9YHg3Ss0GPaRcx4Q74NR/3BzMIB3q429JSK+GYKHNkRtdMNiQ9OcFVavhD
+BDApEkavka/A9U5YOB4+/20BPYpfSZT9Z+hLffH6vl6PSsuRzYHdqbbTi44Rff+R
+m62xzgSxG2+n9J68XPaVxVOLAoNQAlPVfq+lxYF04PdZGz8euJMw2C281Ddpo+sU
+Jtvbp0JuAa24GNLM5DnmHvRbfQVxlm6dKJi40Gi0g4ellSs0roqUY+RXUC6VqL/R
+qPWiJhtnvue8zOA6F0C2nFF+Qdtm0UiwEp4TR5jhC5y1+uWzy190mM2fuo0m/7/0
+6FRv2Oc3tnYXTYg0m8h8QjPGCp3A1TwDlTOoeG81GD4sYvu/kPQH0cKmytwAqMJw
+LP6OCgOjEFwWxKkYaBVSnr7aP7f/26F8Rf8eGJO0VH2P67F8usweof30bP9eQ9MR
+rrA9uA0+odpufNMaVbA9Vnj4ipCWR0xqU0Uq+UODVwvI3Vnf1c8gWm9rFCi3hZb5
+kuxtDpXWlR7SgiRejt1cZmWTWijToF81HkFZf9XoS8jdN26XLlhqy45h9G2N3mVQ
+jS0uSAjZVk4A1k/HbicOcj92eL1nXK0QFY7OPL9XBSms+KlwAVN15M2tnfQ5mlxC
+mVAFqho5KQmYipViO/VI5aS/CxVnABSqLxhhj/ge9SQFONjsNDKkaIz7tYtz5KJ+
+dvJAg2IMcOtV4jZIBrNdfslw0TP17GZwrCUibLzEdPQ02awpemyi1sHquR/B9uoi
+3CDsPoDABzVp79wsiYz2sEwY23AaKZtMuQRSbR8BtvmMIArgJ273/vfx92skMdjn
+dpJbxTlNZ/xPo3NSXVTQYxlfeNrGelXvJYT0LxZ4uapMa91gRXRvJsjC3JGu4o+T
+CeMtclG9uYrSOlbyg4WzVKpwIHTjSCp/CkWCBJIkdxKkScwhDoG3mAcglwMikUEt
+Eg60+jPBHH3dTOvuaRXvYDVdPG8SPa3txrR1tetKGB6g7eMjYgbmYDOxQESS0j1H
+cUCIfK+NwKMBRJFy1wjWqZLKhCWrtevAMhpPFa3HWv2fLY0Vf2s6n9W9mr/hA3Tt
+tPo+c5r7M/I2jzxiHSo1bJD/0yeZDegWrB+8+8PzHoFY05458ei1rc9iNTziogl1
+DYOOcBlROOitO3VZYjbab0iwX0zqEuSYQy41zVJHbMQFp+rbIpuPWQpNAC3FxZuW
+iTVchbpHiCHZ+I1Lud3aqN2z3CBC6GLONUoyCvLfmCKoLIbjusZ/xFH9Q7INPOkH
+g2Sr/bw+8oC+FCujORB2iUmFo5fcgrF1FLxFEbYaB629ed8vE+2aII2OA4amsiD5
+1RkylPMD4Tv6FOvp4G37ph98vfdQvZeX9OdkqS3rGdbwSCf6+AngomJEJ7uVA/c7
+Won/1j0eF6JtcRPBo+jFKfdzr6ynu2AoAyKg0Rn/S7HC0YLEB1iPDWpOC39yQp+A
+x4NNJm1NJjR3oby6LdVp2J8GlKuhztxqkJ6aV9BZDM0rEpP4EdA0QClhXnIJ9H6e
+7bQ8uhT8sW8=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/client_authority.p12 b/tests/standalone/io/certificates/client_authority.p12
new file mode 100644
index 0000000..76b0575
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client_authority.pem b/tests/standalone/io/certificates/client_authority.pem
new file mode 100644
index 0000000..142756f
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAaMRgw
+FgYDVQQDDA9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDckwmIcOYIRbH1jcuBCC/y1a4aiqXhvUCty59Cdqzlx0gbrhkVGmf0
+B0Tmo/PW4p9rcl0hwwxGvGoCvsxVpodHQmIxYwwn1sRl2C7Yo2ZHPMYbv9uq+D0d
+kS8SxHb5l4HvpcT7WoqUq8ZWEm0Losbp8cOcrvLiBQgo8xIOKQzKbwrXydnviQKL
+E5iBmUswzHwb7ZK84u6dS3iHbl9iPy+QTfiboT6BNMsO/dm6Nqmdj35fOPQgFUN/
+QR3NsPWL9GtzB9iZc3D7c30FqqqQO/THjaLJIyzdFdF3Fsp+omSuZw/q1d4/R8M3
+FRCcqzbWLA9Dy12kK/9asmlpf/fdHByVAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
+Af8CAQAwHQYDVR0OBBYEFPk5T6DExD59hh1A7g+PTZvoqr8MMB8GA1UdIwQYMBaA
+FPk5T6DExD59hh1A7g+PTZvoqr8MMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
+BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh4f1I0kXK88S3yC8k0zRAp4n
+RyyjnPW9Sr2nIuC27RgfH0lxWGOlAVVrFUlgifECD/RSoMuQk5yYgAJiALbnfdlP
+AutjtwClWZ6u1BXnwdUxS+ypWtq4Fb4+vz/VRSK24ZNcrI9NF3wkqKHxnjccxROA
+BratiMbHi5VxU63iec2XqAEhqi+ArWks8XJyTvv/tBYOqmmP4Fi0i/wbpzxmFJ61
+ZGUiHFifkYHKBI/HhjDazdeAhAwcFHSbVInea10+V0dkW7sOGnJFW5PyW1F/TBBe
+3dsp8Tz88+oHbSGwV7qF/Qf6U6kRxeVVctmSSCAohUbPH26xhPhk+t1TVdb3EA==
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
new file mode 100644
index 0000000..d0aeff4
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority_malformed.pem
@@ -0,0 +1,8 @@
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
+bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
+FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
+TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
+DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
+SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
+3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
new file mode 100644
index 0000000..9ef96a7
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain.pem b/tests/standalone/io/certificates/server_chain.pem
new file mode 100644
index 0000000..0d18b96
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain.pem
@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDZE0gF3bAFxBaxAZUFGkeFkF5B8nJD//+14rcz/Kr/Rau38g38jNyp
+K3bsyWIBq/4A/cPykwncG6Z04WD2FrLR1xDdAbO2zD3cQKbOoFOYXeYMmP4FZcbq
+nSngCzfUfJkwXXHfCC6v3XZkmR0ojWp9tGHJ6G4f9QI8wwT/Y9pvAVQVR9+S43C0
+ZAPkuNiMBN3lAH4QF2WTC5GTQo4hR+IAWN28lnqAbVoRMNvFoDenDZxURq2kT/6j
+ot6UB9f6AOugCUlEpVovTX3evPKrIZz68BM4DttA/r2wo6dw3fouZk/REJ38fi7x
+lg5n5ccCmguE2fF5PoAMH7WCc7EupYKNAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSFtW0d7VGk7g7ywHgrf+bbg/BhQTAf
+BgNVHSMEGDAWgBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAKL0FaPO+YM+
+JJgQryvkf2/WqdnnTGg/7A/HCOk1rkT9q0282Bj1OT4GiyOIOTyHkxrF72dSiN4Q
+0hg1YoUITR1uR5odQsnK3YKSfmGfn+IRNuHf/Oy1XfRrjuIgo3syeqquIJM4W1MO
+uZBkqwdXQIYqBGj4E+y32bxGVhI53rb9MyKfugajRxImTO7UnUydHsIgqNG6MfuH
+LXBNUAw6uPLyW6srfWiiDVlkUzSmXYFoScCXTj7u12Ar/hffGKrXqHojSE0XtcRz
+WuncYKJE/pflgClA5Qe64erD3q2w2SfOZDFwizP7aZU9uAMin8NbiE8Nd6h8hoRc
+ztJfeC+1gro=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
new file mode 100644
index 0000000..cb623fd
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed1.pem
@@ -0,0 +1,6 @@
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
new file mode 100644
index 0000000..978c523
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed2.pem
@@ -0,0 +1,41 @@
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
+oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
+1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
+PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
+BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
+B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
+phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
+YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
+UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
+2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
+PkLkXmoIod8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
+ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
+VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
+V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
+Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
+kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
+GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
+eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
+NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
+MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
+rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
+9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
+RUE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
new file mode 100644
index 0000000..c95c46b
--- /dev/null
+++ b/tests/standalone/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_key.pem b/tests/standalone/io/certificates/server_key.pem
new file mode 100644
index 0000000..7598e59
--- /dev/null
+++ b/tests/standalone/io/certificates/server_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4zAcBgoqhkiG9w0BDAEBMA4ECDmmTgwIo/3yAgIIAASCBMHPUDfzHGi72H4W
+nKLepeD31Upra9tvQx6UrRQaBmf0frh5Coo4Yw3Z+IOZQ4ZwxoIv0/kty7FvXVDU
+BMdFqFeVvKKlsMm7Ub0hC5ks7A0mTVqcc9nW/aBL87W4nZsJ3LSLiPYXptBWOGRh
+kVghEsySowsK8OmYDwauLi5ZoZC/3cwy2YIaOC9/J8sbnzAq3EVEpJwI0GIQgYET
+aGGELjpariWrcPUa16dRU5vrBlFL2Sn3BVJU24DFq/8RJwsL2rpWXxg9x5QxoraW
+WPvxIGvanBphthRABjZ4A8mtQwvkKfdqMuJ7bWAA2YqcZnk7N5zh4XmARKvjlM5K
+ujpjRFu4+NjyQ65vqTfAwQptxj9l/nzaSZqV5K8ROlpa+UODNzLsL/gf4l/22zZ+
+/rnyko97NQ0Jhy/m0xPhXd620IWjmsjNZk+txYWx4K0srBTptRTqKWkQuY7DV/N0
+4xEA0y3T1kLXZmGmvoidB8VwWD7ZC4/fhuFKAKQmEccMsR9AUsI0h4bAjJ419AK2
+G1jsirQS5P1vBweddwbzCtztUNuCCFy9LHmJCLE/yJ2JMmnePi7eOiyvsjU4es6b
+yj9/ekbWQwZO5L15UkY9T/pP8kSR+gAvn/92DB+e2U4R+ZK886unDyLCCp0rGsPK
+ijdcwMkAJampirw3iO5FkXbGO4GoVggNUxTTCDnYenY8jcKePlP0YM7A9XZ+kmmS
+1gcNuNikKmfzusvUuvOX4Dt24gCOGa5dDEOeYHsC7SZT40IFogshZyVdKNzlyIxj
+yqIlr9LOGo7vL84aUYUUF2mRJ9n2+ivqRadQ9s59iH96uYjvZ12KztCjHEPVSVHk
++rwd4WJ5ByBV7MeB8370JtwN/ZfzAIB7ONfXP9rrfcP19VC+MpsIuOCYPJERlhBT
+9w/UuThPhM/cXp9YiDJepa0T2vmCRKHSz932WKGe3dZn+0saKa5ShdMSepp9CroE
+ot2aF+uU9rMh+DIeNVLmHFwa5+3UC18G6rIB9wpZCHmg6LyMDf/OwW2/yao/GKXN
+WayHbex+Z4yXrVUo+5m9rFwFgo2Hl8fVdSJhKmvp9HQKQjEgxUhUC9B46ErS5efM
+SPlMOYfWST5eOG55vr04dWI5t2AXAKWAxxowO1OBhj3J0FjCS/vtUkUiFohc91oV
+b11afVtizPQJOJ9D1xNEADemnJq6KNT1pRaeKOA94JKODwBMi4K3KmEN51l1uJZ8
+U5h1CjweXZjmq81Da2LMLtGgJuTUuAT6LWIXLSck7EX35D1mY4lGHcuMqVCQ1St1
+UvRjRFx3rd6aBEgj7M/FNsUAIlq4X6+58wdh3mx31608CYGyQ8p5kPhj26ZxziJj
+WSFW+YiVrLPBXhIn6Q9DIqvMPdTbLM/fDy9G0ZinhHZH+a41t7v+UZh2FtiT+p52
+n+hiHTbkGQgQ8SYZT0WAjiaS+1pVVvv+MRqpsYpnNPYxI5bp6orSFOudF3pdAbqQ
+f4WDOY0kGg2tPmaNpZSz+FPuuiWC7Y0J1+o3fMnrUMvY4XrUwkstFfROdnM0W9YG
+I1MsVM4NhcKPHcVxKWgsmL5yAVl92mz88rhgbsArhcpO5K4lxE1LB/giUZRdTkRP
+bKFBVqrcpg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/server_trusted.pem b/tests/standalone/io/certificates/server_trusted.pem
new file mode 100644
index 0000000..c6c2cc3
--- /dev/null
+++ b/tests/standalone/io/certificates/server_trusted.pem
@@ -0,0 +1,58 @@
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAsSFr3/sYhGFF7gEZSn7Am8ATtPhTo5ypQqSAv/4Uy+k4zvT3
+b3OZyYpzr5Wsa6NXcEKwNipyR1GBpYwaYI/W4DSi+COdH4DQSZDQFr+hvmXRazzj
+VSsOxF6veGLcza53meLPRb4o4yVoZARd6xR5i3OUD4kezvOjpmlFT3OKNU0Di+Vq
+qeS14/at6Vt6G0rS8CluafD7Z0/5zp6vrImKwC6OWzlmmcAqBGsE/BTzrAxLdt4K
+uw3Xs3uvS3YZIAC536C1Mop1n4FBUGxeUMWH+I/llzK9ol1pmQHJrxfOD5WdFuuE
+iFfpiOmBdUfDBbEPllmIvzUBFOo5VhxVmq8EHQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBQqU7R8m4wyfyc9ubiPQcYpHNZrmDAfBgNVHSME
+GDAWgBT0rD9lRUhqJvAg7hfBEz/ZqHCzHjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGjRSFvVeIrRF3iuA5vr
+SgufTCNzAyEz7+pDKflzHSQXF1fdItiOdPGv1i57gIr7HaYuxvBiEklhmnWreYye
+Tn6ghfhEHhdZHBpihDXuIvLizhtR/lg9CDZrHjuY6nukyx4JnWwUBR3TulPK5gJu
+jB9YISY8tjXrvVNqdi0a+G0T4HHnVs3v6Nd/Qdsxfp4maAB1U3HFmR3DXKTxDtBK
+mNNMqf9PpX4lw4o6UieiEwOMd+4REhmwLNTwhWrhVg5q6GKQl873Ge/7J2nXvgkH
+nUbEsncLsArqqrz201f2m32A6pinwY/j85vEeRkHwlsU0jOvVnHzAlggP0u/kFAF
+EjE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9jbGll
+bnRhdXRob3JpdHkwHhcNMTgwNDIzMjAxNjM0WhcNMjgwNDIwMjAxNjM0WjAaMRgw
+FgYDVQQDDA9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDckwmIcOYIRbH1jcuBCC/y1a4aiqXhvUCty59Cdqzlx0gbrhkVGmf0
+B0Tmo/PW4p9rcl0hwwxGvGoCvsxVpodHQmIxYwwn1sRl2C7Yo2ZHPMYbv9uq+D0d
+kS8SxHb5l4HvpcT7WoqUq8ZWEm0Losbp8cOcrvLiBQgo8xIOKQzKbwrXydnviQKL
+E5iBmUswzHwb7ZK84u6dS3iHbl9iPy+QTfiboT6BNMsO/dm6Nqmdj35fOPQgFUN/
+QR3NsPWL9GtzB9iZc3D7c30FqqqQO/THjaLJIyzdFdF3Fsp+omSuZw/q1d4/R8M3
+FRCcqzbWLA9Dy12kK/9asmlpf/fdHByVAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
+Af8CAQAwHQYDVR0OBBYEFPk5T6DExD59hh1A7g+PTZvoqr8MMB8GA1UdIwQYMBaA
+FPk5T6DExD59hh1A7g+PTZvoqr8MMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
+BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh4f1I0kXK88S3yC8k0zRAp4n
+RyyjnPW9Sr2nIuC27RgfH0lxWGOlAVVrFUlgifECD/RSoMuQk5yYgAJiALbnfdlP
+AutjtwClWZ6u1BXnwdUxS+ypWtq4Fb4+vz/VRSK24ZNcrI9NF3wkqKHxnjccxROA
+BratiMbHi5VxU63iec2XqAEhqi+ArWks8XJyTvv/tBYOqmmP4Fi0i/wbpzxmFJ61
+ZGUiHFifkYHKBI/HhjDazdeAhAwcFHSbVInea10+V0dkW7sOGnJFW5PyW1F/TBBe
+3dsp8Tz88+oHbSGwV7qF/Qf6U6kRxeVVctmSSCAohUbPH26xhPhk+t1TVdb3EA==
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
new file mode 100644
index 0000000..f45af0a
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.pem b/tests/standalone/io/certificates/trusted_certs.pem
new file mode 100644
index 0000000..dd8edb4
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzIwMTYzM1oXDTI4MDQyMDIwMTYzM1owGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALkvRWdbx9GwxePkh0nnpht4MrPW5NkZBORqfhFi7PFbQ7Rwgl39hm9iAmci
+pOWZGSJi7AaqLuSID0UEeRdG/fNFawI5XIoxP+TmdKdrk/SaTJQKKJiZ9B8+EG0z
+hV8/v6jrlwj0gq9eBBAmOInnmQiEYE4gKFNvh9xdP//gi+otBf30gmtJ4AxXOTu/
+M+XEigXelmIvy57b+B+qnonTFcGkXhSr+JfCA1l6ta7OtknQtItpV0FDr/d8hA+6
+Bn25ZSisd00GC3CUMX1tM5V8cQE6GO/W2mnpUFVvWycYx9wDyU7rlyNUf8nWeoIW
+3d3s/6KAppa07KrkLiTantIrqMUCAwEAAaNTMFEwHQYDVR0OBBYEFPSsP2VFSGom
+8CDuF8ETP9mocLMeMB8GA1UdIwQYMBaAFPSsP2VFSGom8CDuF8ETP9mocLMeMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ1VynTevPnNtwevQpUa
+zlur64N+Dx/yF4gvd4byjO+JouMJLaJqV2dwnqgAahg6YKasVtv4xX9MVJR2IjIb
+Tfa0nYQxM5clwk3J78nh82Ncb2RNeYJyNmSdocnOkmTSoOGUFOxtRz1vmKUcrfwl
+yENO/qGe/sYmOv0IWJjeGQ2OZPblRumV4dJy3qTHFmOLpYwA0BGiIV5uj5Ou7QU1
+R5PY2pnJg4RXeaq95Pr50lkO9vpRyFUJHjR+P+J05M9FbjLPOQIFkpMYx/GyBg5n
+P+omyagOGW8bXfBTtUYu+rP/k+BC5AxI3Kdv/AD5vyHKi/JXhP3ycb8AYx5ENHoK
+qjA=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
new file mode 100644
index 0000000..f96698e
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs_malformed.pem
@@ -0,0 +1,8 @@
+MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
+FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
+ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
+wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
+a
diff --git a/tests/standalone/io/certificates/untrusted_server_chain.pem b/tests/standalone/io/certificates/untrusted_server_chain.pem
new file mode 100644
index 0000000..4845069
--- /dev/null
+++ b/tests/standalone/io/certificates/untrusted_server_chain.pem
@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTgwNDIzMTcxNTEzWhcNMjgwNDIwMTcxNTEz
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDO+XxT1pAvzkIWvAZJFGEjuIuXz1kNoCDxBHAilptAOCX5sKyLaWTc
+YvzYpDf0LOwU3T/ZtlSinkX2xCY7EXgsGJEFc1RDmhmPmSsY9Az/ewS1TNrTOkD5
+VGUwnRKpl3o+140A/aNYGQfHJRz0+BCLftv7b95HinLDq26d01eTHLOozfGqkcfA
+LfUauiwXRV817ceLiliGUtgW8DDNTVqtHA2aeKVisZZtyeEMc3BsnJDGmU6kcQ4B
+KeLHaaxCufy4bMlObwSLcdlp7R6MTudzKVEjXVz/WRLz7yZYaYDrcacUvsI8v+jX
+B7quGGkLGJH+GxDGMObFWKsAB229c9ZlAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR6zQbX0GnDCsjksKYXlzovO2yplDAf
+BgNVHSMEGDAWgBSkX16pB/ZB0hzdYIUgMhWO89CxZzAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIDPqZllHvJa
+XSpqOFaT7oFzKbBnV8lLMvYnbDWHL8N+23q+y803GGNRMkDJG98OalqqKMskk4/v
+ek6dhkTHKnB7hunhogIICXCcHOJGaHN67vvkxkP5mTx6AMaPT+q6NXzu2y9YBTkr
+BIw6ZUyPxqIcH4/GezVe+pokvNZHghDePBChALXEmQLBuJy+gM55w4nB5eq8pNnP
+1r9vVhlr4jqiVNd95MglwB4xLQV5SeG8gGwGvad0vvIpHljOwT9TmlofeqqGpPLf
+3LtqrBK5qdxWcn0jDxG/Qe2EfsdmzsCQ+imu5rTc1YMCGZD52mnnq4tZj0hroWLn
+Wys+JpPMdKo=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzE3MTUxMloXDTI4MDQyMDE3MTUxMlowIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAvpFatw9XMWQDbKzWtsA5NfjQsddw5wlDpFeRYghyqo/mgWru
+Rapcz6tEpEodc3SZ/4PCwE1PmYZuxhcYnaDCM3YdmJAMPUhqi+YO+Gc7WNTbrOR0
+aJGzS2HEPxjbC4OsFG7TVuKMH1uI4rWOZxBn4rODkTmiH7epuyu65nzUJemct8GV
+OcPChjPVKvXzbHVtk8UVreD/DVyuYwsBMSAuYWiq2pgAAQV/7TKVDAQ8yRVW28J7
++QrNXqV+I6MZeMho45xgLNQmi5os9vqTuEu3oGyLFWxXz6uJ2MOFOFTjxMhHGcGn
+aICAA9BIcCeaWWRN9nZkvQuS2nysvJwBu/LROQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBSkX16pB/ZB0hzdYIUgMhWO89CxZzAfBgNVHSME
+GDAWgBR9W+i1d5oZtiZAEjI9RDLd9SnUnDAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIdIh5sIk9Qi2KZfzJUQ
+/DmMTv6NZzAGROJGA+o6jfrMh/plzBre7QM2vzw6iHxFokepLnsXtgrqdtr1lluO
+R6apN2QLp5AJeT8gZfn0V35Wz2iYn+fJR77Map3u57IOj08gvk/BZmJxxqMT/qH/
+1H5qpd934aFLSgqsmpGOVIzrdwHVmwOKU9SDNxOILVpvgtjQ/KWEUxftKtU7Z/dd
+WGN56Vu3Ul0gzgCFifj8mnHnHpug/wEHLl0l2hk3BD1AUrCyCK4yalvsDV7vFex7
+8+Whuh4OijTP/yomn8VGPN5lMmGT4XN8Z3h97PUHF9yF4FYGJJ/lilIhxctashk+
+HuE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE4MDQyMzE3MTUxMloXDTI4MDQyMDE3MTUxMlowGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMuTL5lztughNg/G/9Ge8c6EmROymW0zGTN6hRp3rG2SkpJdag08ntKAmny3
+ilpnlEoxGOk1L9jq/lJsCsiqsSETCadkLsXFNeKOG+S48nc8ThOrmJe5WV6NDNmn
+qaQeek5rjvuRSdukhyZVLzmIyTYNErwkMuo+Jk1V7IS1X2pFyTfF+SLlYrOuDQIW
+qXYfWqdMSYpI8s3onIwR/qVapGu55D0CECzNyX6ZBnqYK0cGzmRaZToT84VPsJwB
+DmALQw9WNNn1CHAIt17CwsdSSasgaKz/XDDjwgKL7CI6bFttDIWVLBt8ikrsrjZN
+6L5b8PZx/dHwJJ7QjYOMKKSUjyECAwEAAaNTMFEwHQYDVR0OBBYEFH1b6LV3mhm2
+JkASMj1EMt31KdScMB8GA1UdIwQYMBaAFH1b6LV3mhm2JkASMj1EMt31KdScMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJTJx9nh+fTJ6a0aIzPY
+FUX5tg+MdUxsAG5QA2jrwZIKCSrHa/ka0vjwLO+94EWcWgKdNDu8lt2FPnJh0nzN
+Ad/CaQNSMesihlmGOgxvLgd3ndYDVYjsCrXx3ESoRavgAWXY+/p69KR1ibVLpKF/
+yr/YURqT9SLKAlgrZt5I/syzxhWdAND62oxqiDCMzPoVR2cLswIUDNRvq5nRiCIt
+1TLPDINjG1EdmwzV2jyPxphL8esopopVm/d9wgD0xQ2Ocb2Nj6Jduuli0sm+dVBL
+3t2pldRq0hXZt/9qhu38tF41TlKSpCz2oFyx2D6ObLSX0MeFp6zXM0c1lGqSCDIM
+ubk=
+-----END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/untrusted_server_key.pem b/tests/standalone/io/certificates/untrusted_server_key.pem
new file mode 100644
index 0000000..b281bb3
--- /dev/null
+++ b/tests/standalone/io/certificates/untrusted_server_key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE5TAcBgoqhkiG9w0BDAEBMA4ECI8YmURjepD4AgIIAASCBMMwp7gfo4FvSVuR
+5w7+OcjkXNQmvrwTRFDaMWV3ORgVFMQx02Q325SnoQsmulB+dk19uj2Piel5j/+j
+xHLvC0rBQC8BjHg/uLmN/f9yW6qolDthmeJEad/L8slB7rziilOGmlPh7H1voJgr
+94uoTn6L2tE9GfoPDsksedRtGIlgSOM3UmLvCkCMcZBqrDi4uqzbhrW3bIbqdoeo
+1lbNsvFuNzF+P3cBHyUUZpPGwCZ8M/XCsCAB+9eH7TM2FJnbuffA6BfkanpQR0ul
+PLo5KDjcS5lQ4YUkI2+lYMSZMiIf50Y8eHP0QnDAuYunA2cPLd90rPpdBCgNtQqk
+aUI7FHvtLFZsTJ1s8EPnZhZOZq1LYUTFQuimMWz+nvC0oQy925brwyjfnrm44KS7
+xpJqsYMBHYflDCwE4LbxjFSeneOy4wwNMurupSdcLCm02Sm1wUMrzRrNsAy3jxP6
+TfJjHRBSt3XEDwDG3olQoK/Ewa1qP0JhAZOd7SrKw9eLQltH+djy0iDUblf5uIHj
+pDC+T1pY9tTwSVxhsJI5a0qxXYNgdaxhr0Fv8BbdScd8Tzdw7g4AByjvgCKArlNJ
+alR1ZaJP/JYuzb3VH8uXEO4b6Tjqw9O4tkZGrc8He5HTAOnSZKbclDxyRH8hkDy+
+apIJUjbE3Gc1mCbyo2nc6WDrGfQNrXDWAVIz4/lb8e8P5k1Rex4rVNhb/VA0Vh4m
+T2BSQ3pvZtKTFedvWgIFIk85rVaYyuB7Icb0YLs2cPppMCfbv+6bOMkJ4hVk5tbX
+AGk6FOjgqsQSY/gzDo9ReCJooETP2AmvHEi2b7LKs+M0Pw+CfvKD/dOkQp62WMpt
+vZJVSXIQ2bHarbhxmUxcT//G+i3QBgkM2xTRvARfRMBiCoBh0Ta3gd4/GJDwv8pr
+pkJi3Q6u88NfGG0eyYyHz+kqTtptqJj1hbAFPdt6d6sFL/wpwhK/L5MOECQ3m100
+N3/aGT7yizM0w/m6PSycSbXycRafRF3XNMBXsUWeFpSWxpJV9GH+T3z8k46GrsM6
+c3YrLG6nvmersDI2AuS9KuhIQQvp+sgwjt3HeURsDv3X4edgCILRTjv3nVuU+DGD
+Xd8CuPYmRei4eJ4nkzxY6fM7ticuArnyE+INVtA0T8yL4UbRxQV/f9jOZWJ1LXLr
+caxCOZP9YcDVG9JUK4WGUC3LVWfhJW+i51cLJk9iGZ8qDLSvgJhj+/7Ajsg6/4xO
+IPon0DVMD9jgMSWLdfpCPawyY+VLVH2CXB2z83c2818gAs85QGUlsW+xLkELSTIU
+6p+mtTF5B2IhsjEdMDAWOpAp/Gj/U9OKapTyE1sGxn66jG/UvxcgYqZo3JGjNaDE
+rMnBhOH4VQQ+FxCA6lXKYCcU1UEze5BuCzJCA7gmCceMlMe+1Car2F+nJCuLNtzB
+uJhlXDbIVhMb5cZBBd3LSjmuRZ/gWbMvV3UqoCROBXqLzVGTufpcn/MgYQKYYHkp
+I+vKDypj0a4IPovDdxg8aMKNn59mtvmMDyrt0716H9DP4SCU/nuxVSeT/HywRBo/
+53fxqtdH3hTAUXqcOLzHnvLUENiABKMeJOtGTV9MFCxgGsnzgYNXnB9hDhm84+IX
+JQdMjj+BNFE6
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/client_socket_add_close_error_test.dart b/tests/standalone/io/client_socket_add_close_error_test.dart
new file mode 100644
index 0000000..b7ebf2c
--- /dev/null
+++ b/tests/standalone/io/client_socket_add_close_error_test.dart
@@ -0,0 +1,51 @@
+// 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 socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketAddCloseErrorTest() {
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    var completer = new Completer();
+    server.listen((socket) {
+      completer.future.then((_) => socket.destroy());
+    });
+    Socket.connect("127.0.0.1", server.port).then((client) {
+      const int SIZE = 1024 * 1024;
+      int errors = 0;
+      client.listen((data) => Expect.fail("Unexpected data"), onError: (error) {
+        Expect.isTrue(error is SocketException);
+        errors++;
+      }, onDone: () {
+        // We get either a close or an error followed by a close
+        // on the socket.  Whether we get both depends on
+        // whether the system notices the error for the read
+        // event or only for the write event.
+        Expect.isTrue(errors <= 1);
+        server.close();
+      });
+      client.add(new List.filled(SIZE, 0));
+      // Destroy other socket now.
+      completer.complete(null);
+      client.done.then((_) {
+        Expect.fail("Expected error");
+      }, onError: (error) {
+        Expect.isTrue(error is SocketException);
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketAddCloseErrorTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/client_socket_add_close_no_error_test.dart b/tests/standalone/io/client_socket_add_close_no_error_test.dart
new file mode 100644
index 0000000..7b92acc
--- /dev/null
+++ b/tests/standalone/io/client_socket_add_close_no_error_test.dart
@@ -0,0 +1,39 @@
+// 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 socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketAddCloseNoErrorTest() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    var completer = new Completer();
+    server.listen((socket) {
+      // The socket is 'paused' until the future completes.
+      completer.future.then((_) => socket.cast<List<int>>().pipe(socket));
+    });
+    Socket.connect("127.0.0.1", server.port).then((client) {
+      const int SIZE = 1024 * 1024;
+      int count = 0;
+      client.listen((data) => count += data.length, onDone: () {
+        Expect.equals(SIZE, count);
+        server.close();
+      });
+      client.add(new List.filled(SIZE, 0));
+      client.close();
+      // Start piping now.
+      completer.complete(null);
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketAddCloseNoErrorTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/client_socket_add_close_result_error_test.dart b/tests/standalone/io/client_socket_add_close_result_error_test.dart
new file mode 100644
index 0000000..58ff72f
--- /dev/null
+++ b/tests/standalone/io/client_socket_add_close_result_error_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketAddCloseResultErrorTest() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    var completer = new Completer();
+    server.listen((socket) {
+      completer.future.then((_) => socket.destroy());
+    });
+    Socket.connect("127.0.0.1", server.port).then((client) {
+      const int SIZE = 1024 * 1024;
+      int errors = 0;
+      client.add(new List.filled(SIZE, 0));
+      client.close();
+      client.done.catchError((_) {}).whenComplete(() {
+        server.close();
+      });
+      // Destroy other socket now.
+      completer.complete(null);
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketAddCloseResultErrorTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/client_socket_add_destroy_no_error_test.dart b/tests/standalone/io/client_socket_add_destroy_no_error_test.dart
new file mode 100644
index 0000000..66d7da1
--- /dev/null
+++ b/tests/standalone/io/client_socket_add_destroy_no_error_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketAddDestroyNoErrorTest() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    server.listen((socket) {
+      // Passive block data by not subscribing to socket.
+    });
+    Socket.connect("127.0.0.1", server.port).then((client) {
+      client.listen((data) {}, onDone: server.close);
+      client.add(new List.filled(1024 * 1024, 0));
+      client.destroy();
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketAddDestroyNoErrorTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/client_socket_destory_no_error_test.dart b/tests/standalone/io/client_socket_destory_no_error_test.dart
new file mode 100644
index 0000000..37aaf49
--- /dev/null
+++ b/tests/standalone/io/client_socket_destory_no_error_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketDestroyNoErrorTest() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    server.listen((socket) {
+      socket.cast<List<int>>().pipe(socket);
+    });
+    Socket.connect("127.0.0.1", server.port).then((client) {
+      client.listen((data) {}, onDone: server.close);
+      client.destroy();
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketDestroyNoErrorTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/client_socket_exception_test.dart b/tests/standalone/io/client_socket_exception_test.dart
new file mode 100644
index 0000000..0d593ff
--- /dev/null
+++ b/tests/standalone/io/client_socket_exception_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void clientSocketExceptionTest() {
+  bool exceptionCaught = false;
+  bool wrongExceptionCaught = false;
+
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Expect.isNotNull(server);
+    int port = server.port;
+    Socket.connect("127.0.0.1", port).then((client) {
+      Expect.isNotNull(client);
+      client.close();
+      // First calls for which exceptions are note expected.
+      try {
+        client.close();
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isFalse(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+      try {
+        client.destroy();
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isFalse(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+      try {
+        List<int> buffer = new List<int>.filled(10, 0);
+        client.add(buffer);
+      } on StateError catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isTrue(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+
+      // From here exceptions are expected.
+      exceptionCaught = false;
+      try {
+        client.port;
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isTrue(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+      exceptionCaught = false;
+      try {
+        client.remotePort;
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isTrue(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+      exceptionCaught = false;
+      try {
+        client.address;
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isTrue(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+      exceptionCaught = false;
+      try {
+        client.remoteAddress;
+      } on SocketException catch (ex) {
+        exceptionCaught = true;
+      } catch (ex) {
+        wrongExceptionCaught = true;
+      }
+      Expect.isTrue(exceptionCaught);
+      Expect.isFalse(wrongExceptionCaught);
+
+      server.close();
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  clientSocketExceptionTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/compile_all_test.dart b/tests/standalone/io/compile_all_test.dart
new file mode 100644
index 0000000..f82e9af
--- /dev/null
+++ b/tests/standalone/io/compile_all_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 that ensures that the VM can compile all the code in the dart:io
+// library.
+//
+// VMOptions=--compile_all
+
+import "dart:io";
+
+main() => null;
diff --git a/tests/standalone/io/console_unicode_test.dart b/tests/standalone/io/console_unicode_test.dart
new file mode 100644
index 0000000..7284b5f
--- /dev/null
+++ b/tests/standalone/io/console_unicode_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 'dart:convert';
+import 'dart:io';
+
+// This test ensures that the VM will support string literals that have non
+// ascii characters. An unhandeld exception will be thrown if the VM fails
+// to support non ascii characters.
+
+main() {
+  String canary = "Canary";
+  String spades = "These are three black spades: ♠♠♠";
+  String german = "German characters: aäbcdefghijklmnoöpqrsßtuüvwxyz";
+
+  stdout.writeln(canary);
+  stdout.writeln(spades);
+  stdout.writeln(german);
+  print(spades);
+  print(german);
+
+  stdout.add(canary.runes.toList());
+  stdout.writeln();
+
+  stdout.writeln(canary);
+  stdout.writeln(spades);
+  stdout.writeln(german);
+  print(spades);
+  print(german);
+
+  stdout.add(canary.codeUnits);
+  stdout.writeln();
+}
diff --git a/tests/standalone/io/create_recursive_test.dart b/tests/standalone/io/create_recursive_test.dart
new file mode 100644
index 0000000..a4be850
--- /dev/null
+++ b/tests/standalone/io/create_recursive_test.dart
@@ -0,0 +1,140 @@
+// 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:io';
+import 'dart:async';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+main() {
+  testCreateDirectoryRecursiveSync();
+  testCreateLinkRecursiveSync();
+  testCreateFileRecursiveSync();
+  testCreateDirectoryRecursive();
+  testCreateLinkRecursive();
+  testCreateFileRecursive();
+}
+
+testCreateDirectoryRecursiveSync() {
+  var temp = Directory.systemTemp.createTempSync('directory_test');
+  try {
+    var dir = new Directory(join(temp.path, 'a', 'b', 'c'));
+    Expect.throws(() => dir.createSync());
+    dir.createSync(recursive: true);
+    Expect.isTrue(dir.existsSync());
+    // Test cases where the directory or parent directory already exists.
+    dir.deleteSync();
+    dir.createSync(recursive: true);
+    Expect.isTrue(dir.existsSync());
+    dir.createSync(recursive: true);
+    Expect.isTrue(dir.existsSync());
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
+testCreateFileRecursiveSync() {
+  var temp = Directory.systemTemp.createTempSync('directory_test');
+  try {
+    var file = new File(join(temp.path, 'a', 'b', 'c'));
+    Expect.throws(() => file.createSync());
+    file.createSync(recursive: true);
+    Expect.isTrue(file.existsSync());
+    // Test cases where the file or parent directory already exists.
+    file.deleteSync();
+    file.createSync(recursive: true);
+    Expect.isTrue(file.existsSync());
+    file.createSync(recursive: true);
+    Expect.isTrue(file.existsSync());
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
+testCreateLinkRecursiveSync() {
+  var temp = Directory.systemTemp.createTempSync('directory_test');
+  try {
+    var link = new Link(join(temp.path, 'a', 'b', 'c'));
+    Expect.throws(() => link.createSync(temp.path));
+    link.createSync(temp.path, recursive: true);
+    Expect.isTrue(link.existsSync());
+    Expect.isTrue(new Directory(link.targetSync()).existsSync());
+    // Test cases where the link or parent directory already exists.
+    link.deleteSync();
+    link.createSync(temp.path, recursive: true);
+    Expect.isTrue(link.existsSync());
+    Expect.throws(() => link.createSync(temp.path, recursive: true));
+    Expect.isTrue(link.existsSync());
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
+Future expectFutureIsTrue(Future future) =>
+    future.then((value) => Expect.isTrue(value));
+
+Future expectFileSystemException(Function f, String message) {
+  return f().then(
+      (_) => Expect.fail('Expected a FileSystemException: $message'),
+      onError: (e) => Expect.isTrue(e is FileSystemException));
+}
+
+testCreateDirectoryRecursive() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory').then((temp) {
+    var dir = new Directory(join(temp.path, 'a', 'b', 'c'));
+    return expectFileSystemException(() => dir.create(), 'dir.create')
+        .then((_) => dir.create(recursive: true))
+        .then((_) => expectFutureIsTrue(dir.exists()))
+        // Test cases where the directory or parent directory already exists.
+        .then((_) => dir.delete())
+        .then((_) => dir.create(recursive: true))
+        .then((_) => expectFutureIsTrue(dir.exists()))
+        .then((_) => dir.create(recursive: true))
+        .then((_) => expectFutureIsTrue(dir.exists()))
+        .then((_) => asyncEnd())
+        .whenComplete(() => temp.delete(recursive: true));
+  });
+}
+
+testCreateFileRecursive() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory').then((temp) {
+    var file = new File(join(temp.path, 'a', 'b', 'c'));
+    return expectFileSystemException(() => file.create(), 'file.create')
+        .then((_) => file.create(recursive: true))
+        .then((_) => expectFutureIsTrue(file.exists()))
+        // Test cases where the file or parent directory already exists.
+        .then((_) => file.delete())
+        .then((_) => file.create(recursive: true))
+        .then((_) => expectFutureIsTrue(file.exists()))
+        .then((_) => file.create(recursive: true))
+        .then((_) => expectFutureIsTrue(file.exists()))
+        .then((_) => asyncEnd())
+        .whenComplete(() => temp.delete(recursive: true));
+  });
+}
+
+testCreateLinkRecursive() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory').then((temp) {
+    var link = new Link(join(temp.path, 'a', 'b', 'c'));
+    return expectFileSystemException(
+            () => link.create(temp.path), 'link.create')
+        .then((_) => link.create(temp.path, recursive: true))
+        .then((_) => expectFutureIsTrue(link.exists()))
+        // Test cases where the link or parent directory already exists.
+        .then((_) => link.delete())
+        .then((_) => link.create(temp.path, recursive: true))
+        .then((_) => expectFutureIsTrue(link.exists()))
+        .then((_) => expectFileSystemException(
+            () => link.create(temp.path, recursive: true),
+            'existing link.create'))
+        .then((_) => expectFutureIsTrue(link.exists()))
+        .then((_) => asyncEnd())
+        .whenComplete(() => temp.delete(recursive: true));
+  });
+}
diff --git a/tests/standalone/io/create_sample_certificates.sh b/tests/standalone/io/create_sample_certificates.sh
new file mode 100755
index 0000000..c2060c1
--- /dev/null
+++ b/tests/standalone/io/create_sample_certificates.sh
@@ -0,0 +1,117 @@
+#!/usr/bin/env bash
+# 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.
+
+# Script to create sample certificates for the dart:io SecureSocket tests.
+# Creates a root certificate authority, an intermediate authority,
+# and a server certificate,
+
+password=pass:dartdart
+
+# We need a server certificate chain where we don't trust the root.  Take the
+# server certificate from the previous run of this script, for that purpose.
+if [ -d "certificates" ]; then
+  mv certificates/server_key.pem certificates/untrusted_server_key.pem
+  mv certificates/server_chain.pem certificates/untrusted_server_chain.pem
+else
+  mkdir certificates
+fi
+
+mkdir -p certificate_authority
+cd certificate_authority
+
+# Create a self-signed certificate authority.
+openssl req -subj /CN=rootauthority -set_serial 1 -batch -verbose \
+    -passout $password -new -x509 -keyout root_authority_key.pem \
+    -out root_authority.pem -days 3650
+
+# Create a certificate request for the intermediate authority.
+openssl req -subj /CN=intermediateauthority -batch -verbose \
+    -passout $password -new -keyout intermediate_authority_key.pem \
+    -out intermediate_authority_request.pem
+
+# Sign the certificate of the intermediate authority with the root authority.
+# Add the certificate extensions marking it as a certificate authority.
+openssl x509 -req -in intermediate_authority_request.pem \
+    -out intermediate_authority.pem -set_serial 2 \
+    -CA root_authority.pem -CAkey root_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions intermediate_authority -days 3650
+
+# Create a certificate request for the server certificate
+openssl req -subj /CN=localhost -batch -verbose -passout $password -new \
+    -keyout localhost_key.pem -out localhost_request.pem
+
+openssl req -subj /CN=badlocalhost -batch -verbose -passout $password -new \
+    -keyout badlocalhost_key.pem -out badlocalhost_request.pem
+
+# Sign the server certificate with the intermediate authority.  Add the
+# certificate extensions for SubjectAltName and that it is not a CA itself.
+openssl x509 -req -in localhost_request.pem -out localhost.pem -set_serial 1 \
+    -CA intermediate_authority.pem -CAkey intermediate_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions localhost -days 3650
+
+openssl x509 -req -in badlocalhost_request.pem -out badlocalhost.pem -set_serial 1 \
+    -CA intermediate_authority.pem -CAkey intermediate_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions badlocalhost -days 3650
+
+# Create a self-signed client certificate authority.
+openssl req -subj /CN=clientauthority -set_serial 1 -batch -verbose \
+    -passout $password -new -x509 -keyout client_authority_key.pem \
+    -out client_authority.pem -config ../sample_certificate_v3_extensions \
+    -extensions client_authority -days 3650
+
+# Create certificate requests for the client certificates
+openssl req -subj /CN=user1 -batch -verbose -passout $password -new \
+    -keyout client1_key.pem -out client1_request.pem
+openssl req -subj /CN=user2 -batch -verbose -passout $password -new \
+    -keyout client2_key.pem -out client2_request.pem
+
+# Sign the certificate requests with the client authority
+openssl x509 -req -in client1_request.pem -out client1.pem -set_serial 2 \
+    -CA client_authority.pem -CAkey client_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions client_certificate -days 3650
+openssl x509 -req -in client2_request.pem -out client2.pem -set_serial 3 \
+    -CA client_authority.pem -CAkey client_authority_key.pem \
+    -passin $password -extfile ../sample_certificate_v3_extensions \
+    -extensions client_certificate -days 3650
+
+# Copy the certificates we will use to the 'certificates' directory.
+CERTS=../certificates
+cat localhost.pem intermediate_authority.pem root_authority.pem \
+    > $CERTS/server_chain.pem
+
+cat badlocalhost.pem intermediate_authority.pem root_authority.pem \
+    > $CERTS/bad_server_chain.pem
+
+cat intermediate_authority.pem root_authority.pem client_authority.pem \
+    > $CERTS/server_trusted.pem
+
+# BoringSSL only accepts private keys signed with the PBE-SHA1-RC4-128 cipher.
+openssl pkcs8 -in localhost_key.pem -out $CERTS/server_key.pem \
+    -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
+openssl pkcs8 -in badlocalhost_key.pem -out $CERTS/bad_server_key.pem \
+    -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
+openssl pkcs8 -in client1_key.pem -out $CERTS/client1_key.pem \
+    -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
+openssl pkcs8 -in client2_key.pem -out $CERTS/client2_key.pem \
+    -topk8 -v1 PBE-SHA1-RC4-128 -passin $password -passout $password
+
+# Delete all the signing keys for the authorities, so testers that add
+# them as trusted are less vulnerable: only the sample server certificate
+# and client certificates will be signed by them. No more certificates
+# will ever be signed.
+rm root_authority_key.pem
+rm intermediate_authority.pem
+rm client_authority_key.pem
+
+cp root_authority.pem $CERTS/trusted_certs.pem
+cp client_authority.pem $CERTS
+cp client1.pem $CERTS
+cp client2.pem $CERTS
+
+cd ..
diff --git a/tests/standalone/io/dart_std_io_pipe_script.dart b/tests/standalone/io/dart_std_io_pipe_script.dart
new file mode 100644
index 0000000..1742df8
--- /dev/null
+++ b/tests/standalone/io/dart_std_io_pipe_script.dart
@@ -0,0 +1,34 @@
+// 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.
+//
+// Utility script to echo stdin to stdout or stderr or both.
+
+import "dart:io";
+
+main(List<String> arguments) {
+  if (stdioType(stdin) is! StdioType) exit(1);
+  if (stdioType(stdout) is! StdioType) exit(1);
+  if (stdioType(stderr) is! StdioType) exit(1);
+  if (stdioType(stdin).name != arguments[1]) {
+    throw stdioType(stdin).name;
+  }
+  if (stdioType(stdout).name != arguments[2]) {
+    throw stdioType(stdout).name;
+  }
+  if (stdioType(stderr).name != arguments[3]) {
+    throw stdioType(stderr).name;
+  }
+  if (arguments.length > 0) {
+    if (arguments[0] == "0") {
+      stdin.pipe(stdout);
+    } else if (arguments[0] == "1") {
+      stdin.pipe(stderr);
+    } else if (arguments[0] == "2") {
+      stdin.listen((data) {
+        stdout.add(data);
+        stderr.add(data);
+      });
+    }
+  }
+}
diff --git a/tests/standalone/io/dart_std_io_pipe_test.dart b/tests/standalone/io/dart_std_io_pipe_test.dart
new file mode 100644
index 0000000..7d3e6fc
--- /dev/null
+++ b/tests/standalone/io/dart_std_io_pipe_test.dart
@@ -0,0 +1,127 @@
+// 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 a dart sub-process handling stdio with different types of
+// redirection.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:io";
+import "process_test_util.dart";
+
+void checkFileEmpty(String fileName) {
+  RandomAccessFile pipeOut = new File(fileName).openSync();
+  Expect.equals(0, pipeOut.lengthSync());
+  pipeOut.closeSync();
+}
+
+void checkFileContent(String fileName, String content) {
+  RandomAccessFile pipeOut = new File(fileName).openSync();
+  int length = pipeOut.lengthSync();
+  var data = new List<int>.filled(length, 0);
+  pipeOut.readIntoSync(data, 0, length);
+  Expect.equals(content, new String.fromCharCodes(data));
+  pipeOut.closeSync();
+}
+
+void test(String shellScript, String dartScript, String type, bool devNull) {
+  Directory dir = Directory.systemTemp.createTempSync('dart_dart_std_io_pipe');
+
+  // The shell script will run the dart executable passed with a
+  // number of different redirections of stdio.
+  String pipeOutFile = "${dir.path}/pipe";
+  if (devNull) pipeOutFile = "/dev/null";
+  String redirectOutFile = "${dir.path}/redirect";
+  String executable = Platform.executable;
+  List<String> args = [
+    ([executable]..addAll(Platform.executableArguments)).join(' '),
+    dartScript,
+    type,
+    pipeOutFile,
+    redirectOutFile,
+    devNull ? "terminal" : "file"
+  ];
+  var future = Process.start(shellScript, args);
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(0, exitCode);
+
+      // Check the expected file contents.
+      if (type == "0") {
+        if (devNull) {
+          checkFileEmpty("${redirectOutFile}.stdout");
+        } else {
+          checkFileContent("${pipeOutFile}", "Hello\n");
+          checkFileContent("${redirectOutFile}.stdout", "Hello\nHello\n");
+        }
+        checkFileEmpty("${redirectOutFile}.stderr");
+      }
+      if (type == "1") {
+        if (devNull) {
+          checkFileEmpty("${redirectOutFile}.stderr");
+        } else {
+          checkFileContent("${pipeOutFile}", "Hello\n");
+          checkFileContent("${redirectOutFile}.stderr", "Hello\nHello\n");
+        }
+        checkFileEmpty("${redirectOutFile}.stdout");
+      }
+      if (type == "2") {
+        if (devNull) {
+          checkFileEmpty("${redirectOutFile}.stdout");
+          checkFileEmpty("${redirectOutFile}.stderr");
+        } else {
+          checkFileContent("${pipeOutFile}", "Hello\nHello\n");
+          checkFileContent(
+              "${redirectOutFile}.stdout", "Hello\nHello\nHello\nHello\n");
+          checkFileContent(
+              "${redirectOutFile}.stderr", "Hello\nHello\nHello\nHello\n");
+        }
+      }
+
+      // Cleanup test directory.
+      dir.deleteSync(recursive: true);
+    });
+    // Drain out and err streams so they close.
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+  });
+  future.catchError((error) {
+    dir.deleteSync(recursive: true);
+    Expect.fail(error.toString());
+  });
+}
+
+// This tests that the Dart standalone VM can handle piping to stdin
+// and can pipe to stdout.
+main() {
+  // Don't try to run shell scripts on Windows.
+  var os = Platform.operatingSystem;
+  if (os == 'windows') return;
+
+  // Get the shell script for testing the Standalone Dart VM with
+  // piping and redirections of stdio.
+  var shellScript = new File("tests/standalone_2/io/dart_std_io_pipe_test.sh");
+  if (!shellScript.existsSync()) {
+    shellScript = new File("../tests/standalone_2/io/dart_std_io_pipe_test.sh");
+  }
+  // Get the Dart script file which echoes stdin to stdout or stderr or both.
+  var scriptFile =
+      new File("tests/standalone_2/io/dart_std_io_pipe_script.dart");
+  if (!scriptFile.existsSync()) {
+    scriptFile =
+        new File("../tests/standalone_2/io/dart_std_io_pipe_script.dart");
+  }
+
+  // Run the shell script.
+  test(shellScript.path, scriptFile.path, "0", false); //# 01: ok
+  test(shellScript.path, scriptFile.path, "0", true); //# 02: ok
+  test(shellScript.path, scriptFile.path, "1", false); //# 03: ok
+  test(shellScript.path, scriptFile.path, "1", true); //# 04: ok
+  test(shellScript.path, scriptFile.path, "2", false); //# 05: ok
+  test(shellScript.path, scriptFile.path, "2", true); //# 06: ok
+}
diff --git a/tests/standalone/io/dart_std_io_pipe_test.sh b/tests/standalone/io/dart_std_io_pipe_test.sh
new file mode 100755
index 0000000..7caa1ed
--- /dev/null
+++ b/tests/standalone/io/dart_std_io_pipe_test.sh
@@ -0,0 +1,17 @@
+#! /bin/bash
+
+# This script expects the following arguments
+# $1: Path to dart executable
+# $2: Path to dart echoing script
+# $3: Argument to dart echoing script (0, 1 or 2)
+# $4: File for output from piping stdout and stderr
+# $5: File prefix for output from redirecting stdout and stderr to a file.
+# $6: Stdio type of stdin
+
+# Test piping and stdio file redirection.
+echo "Hello" | $1 $2 $3 pipe pipe pipe 2>&1 | cat - > $4
+$1 $2 $3 $6 file file < $4 > $5.stdout 2> $5.stderr
+$1 $2 $3 $6 file file < $4 >> $5.stdout 2>> $5.stderr
+$1 $2 $3 $6 terminal terminal < $4 > /dev/null 2> /dev/null
+$1 $2 $3 $6 terminal pipe < $4 2>&1 > /dev/null
+$1 $2 $3 $6 terminal terminal < $4 > /dev/null 2>&1
diff --git a/tests/standalone/io/delete_symlink_test.dart b/tests/standalone/io/delete_symlink_test.dart
new file mode 100644
index 0000000..1a8c149
--- /dev/null
+++ b/tests/standalone/io/delete_symlink_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 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  // temp/
+  //   a/
+  //     file.txt
+  //   b/
+  //     a_link -> a
+  var d = Directory.systemTemp.createTempSync('dart_delete_symlink');
+  var a = new Directory("${d.path}/a");
+  a.createSync();
+
+  var b = new Directory("${d.path}/b");
+  b.createSync();
+
+  var f = new File("${d.path}/a/file.txt");
+  f.createSync();
+  Expect.isTrue(f.existsSync());
+
+  // Create a symlink (or junction on Windows) from
+  // temp/b/a_link to temp/a.
+  var cmd = "ln";
+  var args = ['-s', "${d.path}/b/a_link", "${d.path}/a"];
+
+  if (Platform.operatingSystem == "windows") {
+    cmd = "cmd";
+    args = ["/c", "mklink", "/j", "${d.path}\\b\\a_link", "${d.path}\\a"];
+  }
+
+  asyncStart();
+
+  Process.run(cmd, args).then((_) {
+    // Delete the directory containing the junction.
+    b.deleteSync(recursive: true);
+
+    // We should not have recursed through a_link into a.
+    Expect.isTrue(f.existsSync());
+
+    // Clean up after ourselves.
+    d.deleteSync(recursive: true);
+
+    // Terminate now that we are done with everything.
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/directory_chdir_test.dart b/tests/standalone/io/directory_chdir_test.dart
new file mode 100644
index 0000000..fe0d1ac
--- /dev/null
+++ b/tests/standalone/io/directory_chdir_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.
+//
+// Directory listing test.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+testChangeDirectory() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory_chdir').then((temp) {
+    var initialCurrent = Directory.current;
+    Directory.current = temp;
+    var newCurrent = Directory.current;
+    new File("111").createSync();
+    var dir = new Directory(newCurrent.path + Platform.pathSeparator + "222");
+    dir.createSync();
+    Directory.current = dir;
+    new File("333").createSync();
+    Expect.isTrue(new File("333").existsSync());
+    Expect.isTrue(new File("../111").existsSync());
+    Directory.current = "..";
+    Expect.isTrue(new File("111").existsSync());
+    Expect.isTrue(new File("222/333").existsSync());
+    // Deleting the current working directory causes an error.
+    // On Windows, the deletion fails, and on non-Windows, the getter fails.
+    Expect.throws(() {
+      temp.deleteSync(recursive: true);
+      Directory.current;
+    }, (e) => e is FileSystemException);
+    Directory.current = initialCurrent;
+    Directory.current;
+    if (temp.existsSync()) temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+testChangeDirectoryIllegalArguments() {
+  Expect.throwsArgumentError(() => Directory.current = 1);
+  Expect.throwsArgumentError(() => Directory.current = 9223372036854775807);
+  Expect.throwsArgumentError(() => Directory.current = true);
+  Expect.throwsArgumentError(() => Directory.current = []);
+  Expect.throwsArgumentError(() => Directory.current = new File("xxx"));
+}
+
+main() {
+  testChangeDirectory();
+  testChangeDirectoryIllegalArguments();
+}
diff --git a/tests/standalone/io/directory_create_race_test.dart b/tests/standalone/io/directory_create_race_test.dart
new file mode 100644
index 0000000..973511c
--- /dev/null
+++ b/tests/standalone/io/directory_create_race_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.
+//
+// Test for a race condition that can occur when recursively creating
+// a directory multiple times simultaneously.  This consistently reproduces
+// issue https://code.google.com/p/dart/issues/detail?id=7679 in revisions
+// without the fix for this issue.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testCreateRecursiveRace() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('dart_directory_create_race');
+  var d = new Directory('${temp.path}/a/b/c/d/e');
+  Future.wait([
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true),
+    d.create(recursive: true)
+  ]).then((_) {
+    Expect.isTrue(new Directory('${temp.path}/a').existsSync());
+    Expect.isTrue(new Directory('${temp.path}/a/b').existsSync());
+    Expect.isTrue(new Directory('${temp.path}/a/b/c').existsSync());
+    Expect.isTrue(new Directory('${temp.path}/a/b/c/d').existsSync());
+    Expect.isTrue(new Directory('${temp.path}/a/b/c/d/e').existsSync());
+    temp.delete(recursive: true).then((_) {
+      asyncEnd();
+    });
+  });
+}
+
+void main() {
+  testCreateRecursiveRace();
+  testCreateRecursiveRace();
+}
diff --git a/tests/standalone/io/directory_error_test.dart b/tests/standalone/io/directory_error_test.dart
new file mode 100644
index 0000000..892b0a6
--- /dev/null
+++ b/tests/standalone/io/directory_error_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.
+//
+// Dart test program for testing error handling in directory I/O.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Directory tempDir() {
+  return Directory.systemTemp.createTempSync('dart_directory_error');
+}
+
+bool checkCreateInNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf("Creation failed") != -1);
+  if (Platform.operatingSystem == "linux") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "macos") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "windows") {
+    Expect.equals(3, e.osError.errorCode);
+  }
+
+  return true;
+}
+
+void testCreateInNonExistent(Directory temp, Function done) {
+  Directory inNonExistent = new Directory("${temp.path}/nonExistent/xxx");
+  Expect.throws(() => inNonExistent.createSync(),
+      (e) => checkCreateInNonExistentFileSystemException(e));
+
+  inNonExistent.create().catchError((error) {
+    checkCreateInNonExistentFileSystemException(error);
+    done();
+  });
+}
+
+bool checkCreateTempInNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  if (Platform.operatingSystem == "linux") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "macos") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "windows") {
+    Expect.equals(3, e.osError.errorCode);
+  }
+
+  return true;
+}
+
+void testCreateTempInNonExistent(Directory temp, Function done) {
+  Directory nonExistent = new Directory("${temp.path}/nonExistent/xxx");
+  Expect.throws(() => nonExistent.createTempSync('tempdir'),
+      (e) => checkCreateTempInNonExistentFileSystemException(e));
+
+  nonExistent.createTemp('tempdir').catchError((error) {
+    checkCreateTempInNonExistentFileSystemException(error);
+    done();
+  });
+}
+
+bool checkDeleteNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  // File not not found has error code 2 on all supported platforms.
+  Expect.equals(2, e.osError.errorCode);
+
+  return true;
+}
+
+void testDeleteNonExistent(Directory temp, Function done) {
+  Directory nonExistent = new Directory("${temp.path}/nonExistent");
+  Expect.throws(() => nonExistent.deleteSync(),
+      (e) => checkDeleteNonExistentFileSystemException(e));
+
+  nonExistent.delete().catchError((error) {
+    checkDeleteNonExistentFileSystemException(error);
+    done();
+  });
+}
+
+bool checkDeleteRecursivelyNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf("Deletion failed") != -1);
+  // File not not found has error code 2 on all supported platforms.
+  Expect.equals(2, e.osError.errorCode);
+
+  return true;
+}
+
+void testDeleteRecursivelyNonExistent(Directory temp, Function done) {
+  Directory nonExistent = new Directory("${temp.path}/nonExistent");
+  Expect.throws(() => nonExistent.deleteSync(recursive: true),
+      (e) => checkDeleteRecursivelyNonExistentFileSystemException(e));
+
+  nonExistent.delete(recursive: true).catchError((error) {
+    checkDeleteRecursivelyNonExistentFileSystemException(error);
+    done();
+  });
+}
+
+bool checkListNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf("Directory listing failed") != -1);
+  if (Platform.operatingSystem == "linux") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "macos") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "windows") {
+    Expect.equals(3, e.osError.errorCode);
+  }
+
+  return true;
+}
+
+bool checkAsyncListNonExistentFileSystemException(error) {
+  return checkListNonExistentFileSystemException(error);
+}
+
+void testListNonExistent(Directory temp, Function done) {
+  Directory nonExistent = new Directory("${temp.path}/nonExistent");
+  Expect.throws(() => nonExistent.listSync(), (e) => e is FileSystemException);
+  nonExistent.list().listen((_) => Expect.fail("listing should not succeed"),
+      onError: (e) {
+    checkAsyncListNonExistentFileSystemException(e);
+    done();
+  });
+}
+
+void testRenameNonExistent(Directory temp, Function done) {
+  Directory nonExistent = new Directory("${temp.path}/nonExistent");
+  var newPath = "${temp.path}/nonExistent2";
+  Expect.throws(
+      () => nonExistent.renameSync(newPath), (e) => e is FileSystemException);
+  var renameDone = nonExistent.rename(newPath);
+  renameDone
+      .then((ignore) => Expect.fail('rename non existent'))
+      .catchError((error) {
+    Expect.isTrue(error is FileSystemException);
+    done();
+  });
+}
+
+void testRenameFileAsDirectory(Directory temp, Function done) {
+  File f = new File("${temp.path}/file");
+  var newPath = "${temp.path}/file2";
+  f.createSync();
+  var d = new Directory(f.path);
+  Expect.throws(() => d.renameSync(newPath), (e) => e is FileSystemException);
+  var renameDone = d.rename(newPath);
+  renameDone
+      .then((ignore) => Expect.fail('rename file as directory'))
+      .catchError((error) {
+    Expect.isTrue(error is FileSystemException);
+    done();
+  });
+}
+
+testRenameOverwriteFile(Directory temp, Function done) {
+  var temp1 = Directory.systemTemp.createTempSync('dart_directory_error');
+  var fileName = '${temp.path}/x';
+  new File(fileName).createSync();
+  Expect.throws(
+      () => temp1.renameSync(fileName), (e) => e is FileSystemException);
+  var renameDone = temp1.rename(fileName);
+  renameDone
+      .then((ignore) => Expect.fail('rename dir overwrite file'))
+      .catchError((error) {
+    Expect.isTrue(error is FileSystemException);
+    temp1.deleteSync(recursive: true);
+    done();
+  });
+}
+
+void runTest(Function test) {
+  // Create a temporary directory for the test.
+  var temp = Directory.systemTemp.createTempSync('dart_directory_error');
+
+  // Wait for the test to finish and delete the temporary directory.
+  asyncStart();
+
+  // Run the test.
+  test(temp, () {
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+main() {
+  runTest(testCreateInNonExistent);
+  runTest(testCreateTempInNonExistent);
+  runTest(testDeleteNonExistent);
+  runTest(testDeleteRecursivelyNonExistent);
+  runTest(testListNonExistent);
+  runTest(testRenameNonExistent);
+  runTest(testRenameFileAsDirectory);
+  runTest(testRenameOverwriteFile);
+}
diff --git a/tests/standalone/io/directory_fuzz_test.dart b/tests/standalone/io/directory_fuzz_test.dart
new file mode 100644
index 0000000..f76fc79
--- /dev/null
+++ b/tests/standalone/io/directory_fuzz_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.
+
+// 'fuzz' test the directory APIs by providing unexpected type
+// arguments. The test passes if the VM does not crash.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+import 'fuzz_support.dart';
+
+fuzzSyncMethods() {
+  typeMapping.forEach((k, v) {
+    doItSync(() {
+      Directory.systemTemp.createTempSync(v as String?).deleteSync();
+    });
+    late Directory d;
+    doItSync(() => d = new Directory(v as String));
+    if (d == null) return;
+    doItSync(d.existsSync);
+    doItSync(d.createSync);
+    doItSync(d.deleteSync);
+    doItSync(d.listSync);
+    doItSync(() {
+      d.createTempSync('tempdir').deleteSync();
+    });
+    doItSync(() {
+      // Let's be a little careful. If the directory exists we don't
+      // want to delete it and all its contents.
+      if (!d.existsSync()) d.deleteSync(recursive: true);
+    });
+    typeMapping.forEach((k2, v2) {
+      doItSync(() => d.renameSync(v2 as String));
+      doItSync(() => d.listSync(recursive: v2 as bool));
+    });
+  });
+}
+
+fuzzAsyncMethods() {
+  asyncStart();
+  var futures = <Future>[];
+  typeMapping.forEach((k, v) {
+    futures.add(doItAsync(() {
+      Directory.systemTemp.createTempSync(v as String?).deleteSync();
+    }));
+    if (v is! String) {
+      return;
+    }
+    var d = new Directory(v);
+    futures.add(doItAsync(d.exists));
+    futures.add(doItAsync(d.create));
+    futures.add(doItAsync(d.delete));
+    futures.add(doItAsync(() {
+      return d.createTemp('tempdir').then((temp) {
+        return temp.delete();
+      });
+    }));
+    futures.add(doItAsync(() {
+      return d.exists().then((res) {
+        if (!res) return d.delete(recursive: true);
+        return new Future.value(true);
+      });
+    }));
+    typeMapping.forEach((k2, v2) {
+      futures.add(doItAsync(() => d.rename(v2 as String)));
+      futures.add(doItAsync(() {
+        d.list(recursive: v2 as bool).listen((_) {}, onError: (e) => null);
+      }));
+    });
+  });
+  Future.wait(futures).then((_) => asyncEnd());
+}
+
+main() {
+  fuzzSyncMethods();
+  fuzzAsyncMethods();
+}
diff --git a/tests/standalone/io/directory_list_nonexistent_test.dart b/tests/standalone/io/directory_list_nonexistent_test.dart
new file mode 100644
index 0000000..c3e92f1
--- /dev/null
+++ b/tests/standalone/io/directory_list_nonexistent_test.dart
@@ -0,0 +1,53 @@
+// 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.
+//
+// Directory listing test that tests listSync on a missing directory.
+//
+// TODO(7157): Merge this test into directory_test.dart testListNonExistent()
+// when it no longer crashes on Windows, when issue 7157 is resolved.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testListNonExistent() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory_list_nonexistent').then((d) {
+    d.delete().then((ignore) {
+      Expect.throws(() => d.listSync(), (e) => e is FileSystemException);
+      Expect.throws(
+          () => d.listSync(recursive: true), (e) => e is FileSystemException);
+      asyncEnd();
+    });
+  });
+}
+
+void testListTooLongName() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory_list_nonexistent').then((d) {
+    var subDirName = 'subdir';
+    var subDir = new Directory("${d.path}/$subDirName");
+    subDir.create().then((ignore) {
+      // Construct a long string of the form
+      // 'tempdir/subdir/../subdir/../subdir'.
+      var buffer = new StringBuffer();
+      buffer.write(subDir.path);
+      for (var i = 0; i < 1000; i++) {
+        buffer.write("/../${subDirName}");
+      }
+      var long = new Directory("${buffer.toString()}");
+      Expect.throws(() => long.listSync(), (e) => e is FileSystemException);
+      Expect.throws(() => long.listSync(recursive: true),
+          (e) => e is FileSystemException);
+      d.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void main() {
+  testListNonExistent();
+  testListTooLongName();
+}
diff --git a/tests/standalone/io/directory_list_pause_test.dart b/tests/standalone/io/directory_list_pause_test.dart
new file mode 100644
index 0000000..159b769
--- /dev/null
+++ b/tests/standalone/io/directory_list_pause_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testPauseList() {
+  asyncStart();
+  // TOTAL should be bigger the our directory listing buffer.
+  const int TOTAL = 128;
+  Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+    for (int i = 0; i < TOTAL; i++) {
+      new Directory("${d.path}/$i").createSync();
+      new File("${d.path}/$i/file").createSync();
+    }
+    bool first = true;
+    var subscription;
+    int count = 0;
+    subscription = d.list(recursive: true).listen((file) {
+      if (file is File) {
+        if (first) {
+          first = false;
+          subscription.pause();
+          Timer.run(() {
+            for (int i = 0; i < TOTAL; i++) {
+              new File("${d.path}/$i/file").deleteSync();
+            }
+            subscription.resume();
+          });
+        }
+        count++;
+      }
+    }, onDone: () {
+      Expect.notEquals(TOTAL, count);
+      Expect.isTrue(count > 0);
+      d.delete(recursive: true).then((ignore) => asyncEnd());
+    });
+  });
+}
+
+void testPauseResumeCancelList() {
+  asyncStart();
+  // TOTAL should be bigger the our directory listing buffer.
+  const int TOTAL = 128;
+  Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+    for (int i = 0; i < TOTAL; i++) {
+      new Directory("${d.path}/$i").createSync();
+      new File("${d.path}/$i/file").createSync();
+    }
+    var subscription;
+    subscription = d.list(recursive: true).listen((entity) {
+      subscription.pause();
+      subscription.resume();
+      void close() {
+        d.deleteSync(recursive: true);
+        asyncEnd();
+      }
+
+      var future = subscription.cancel();
+      if (future != null) {
+        future.whenComplete(close);
+      } else {
+        close();
+      }
+    }, onDone: () {
+      Expect.fail('the stream was canceled, onDone should not happen');
+    });
+  });
+}
+
+void testListIsEmpty() {
+  asyncStart();
+  // TOTAL should be bigger the our directory listing buffer.
+  const int TOTAL = 128;
+  Directory.systemTemp.createTemp('dart_directory_list_pause').then((d) {
+    for (int i = 0; i < TOTAL; i++) {
+      new Directory("${d.path}/$i").createSync();
+      new File("${d.path}/$i/file").createSync();
+    }
+    // isEmpty will cancel the stream after first data event.
+    d.list(recursive: true).isEmpty.then((empty) {
+      Expect.isFalse(empty);
+      d.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void main() {
+  testPauseList();
+  testPauseResumeCancelList();
+  testListIsEmpty();
+}
diff --git a/tests/standalone/io/directory_list_sync_test.dart b/tests/standalone/io/directory_list_sync_test.dart
new file mode 100644
index 0000000..2c99a67
--- /dev/null
+++ b/tests/standalone/io/directory_list_sync_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.
+
+import 'dart:io';
+
+void main() {
+  File script = new File.fromUri(Platform.script);
+  // tests/standalone/io/../..
+  Directory startingDir = script.parent.parent.parent;
+  print("Recursively listing entries in directory ${startingDir.path} ...");
+  List<FileSystemEntity> each =
+      startingDir.listSync(recursive: true, followLinks: false);
+  print("Found: ${each.length} entities");
+}
diff --git a/tests/standalone/io/directory_non_ascii_sync_test.dart b/tests/standalone/io/directory_non_ascii_sync_test.dart
new file mode 100644
index 0000000..df2283f
--- /dev/null
+++ b/tests/standalone/io/directory_non_ascii_sync_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";
+import 'dart:io';
+
+main() {
+  Directory tempDir =
+      Directory.systemTemp.createTempSync('dart_directory_non_ascii_sync');
+  var nonAsciiDir = new Directory("${tempDir.path}/æøå");
+  // On MacOS you get the decomposed utf8 form of file and directory
+  // names from the system. Therefore, we have to check for both here.
+  var precomposed = 'æøå';
+  var decomposed = new String.fromCharCodes([47, 230, 248, 97, 778]);
+  Expect.isFalse(nonAsciiDir.existsSync());
+  nonAsciiDir.createSync();
+  Expect.isTrue(nonAsciiDir.existsSync());
+  var temp = new Directory("${tempDir.path}/æøå").createTempSync('tempdir');
+  Expect.isTrue(
+      temp.path.contains(precomposed) || temp.path.contains(decomposed));
+  temp.deleteSync();
+  temp = tempDir.createTempSync('æøå');
+  Expect.isTrue(
+      temp.path.contains(precomposed) || temp.path.contains(decomposed));
+  temp.deleteSync();
+  tempDir.deleteSync(recursive: true);
+  Expect.isFalse(nonAsciiDir.existsSync());
+  Expect.isFalse(temp.existsSync());
+}
diff --git a/tests/standalone/io/directory_non_ascii_test.dart b/tests/standalone/io/directory_non_ascii_test.dart
new file mode 100644
index 0000000..dc2dcb1
--- /dev/null
+++ b/tests/standalone/io/directory_non_ascii_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:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+
+  // On MacOS you get the decomposed utf8 form of file and directory
+  // names from the system. Therefore, we have to check for both here.
+  var precomposed = 'æøå';
+  var decomposed = new String.fromCharCodes([47, 230, 248, 97, 778]);
+
+  Directory.systemTemp.createTemp('dart_directory_non_ascii').then((tempDir) {
+    var nonAsciiDir = new Directory("${tempDir.path}/æøå");
+    nonAsciiDir
+        .exists()
+        .then((e) => Expect.isFalse(e))
+        .then((_) => nonAsciiDir.create())
+        .then((_) => nonAsciiDir.exists())
+        .then((e) => Expect.isTrue(e))
+        .then((_) => new Directory("${tempDir.path}/æøå").createTemp('temp'))
+        .then((temp) {
+          Expect.isTrue(temp.path.contains(precomposed) ||
+              temp.path.contains(decomposed));
+          return temp.delete();
+        })
+        .then((_) => tempDir.createTemp('æøå'))
+        .then((temp) {
+          Expect.isTrue(temp.path.contains(precomposed) ||
+              temp.path.contains(decomposed));
+          return temp.delete();
+        })
+        .then((temp) => Expect.isFalse(temp.existsSync()))
+        .then((_) => tempDir.delete(recursive: true))
+        .then((_) {
+          Expect.isFalse(nonAsciiDir.existsSync());
+          asyncEnd();
+        });
+  });
+}
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart
new file mode 100644
index 0000000..ddd3760
--- /dev/null
+++ b/tests/standalone/io/directory_test.dart
@@ -0,0 +1,626 @@
+// 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.
+//
+// Directory listing test.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class DirectoryTest {
+  static void testListing() {
+    bool listedDir = false;
+    bool listedFile = false;
+
+    Directory directory =
+        Directory.systemTemp.createTempSync('dart_directory_test');
+    Directory subDirectory = new Directory("${directory.path}/subdir");
+    Expect.isTrue('$directory'.contains(directory.path));
+    Expect.isFalse(subDirectory.existsSync());
+    subDirectory.createSync();
+    Expect.isTrue(subDirectory.existsSync());
+    File f = new File('${subDirectory.path}/file.txt');
+    File fLong = new File('${directory.path}/subdir/../subdir/file.txt');
+    Expect.isFalse(f.existsSync());
+    f.createSync();
+
+    void testSyncListing(bool recursive) {
+      for (var entry in directory.listSync(recursive: recursive)) {
+        if (entry is File) {
+          Expect.isTrue(entry.path.contains(directory.path));
+          Expect.isTrue(entry.path.contains('subdir'));
+          Expect.isTrue(entry.path.contains('file.txt'));
+          Expect.isFalse(listedFile);
+          listedFile = true;
+        } else {
+          Expect.isTrue(entry is Directory);
+          Expect.isTrue(entry.path.contains(directory.path));
+          Expect.isTrue(entry.path.contains('subdir'));
+          Expect.isFalse(listedDir);
+          listedDir = true;
+        }
+      }
+      Expect.equals(listedFile, recursive);
+      Expect.isTrue(listedDir);
+      listedFile = false;
+      listedDir = false;
+    }
+
+    testSyncListing(true);
+    testSyncListing(false);
+    Expect.equals(
+        f.resolveSymbolicLinksSync(), fLong.resolveSymbolicLinksSync());
+
+    asyncStart();
+    directory.list(recursive: true).listen((FileSystemEntity entity) {
+      if (entity is File) {
+        var path = entity.path;
+        listedFile = true;
+        Expect.isTrue(path.contains(directory.path));
+        Expect.isTrue(path.contains('subdir'));
+        Expect.isTrue(path.contains('file.txt'));
+      } else {
+        var path = entity.path;
+        Expect.isTrue(entity is Directory);
+        listedDir = true;
+        Expect.isTrue(path.contains(directory.path));
+        Expect.isTrue(path.contains('subdir'));
+      }
+    }, onDone: () {
+      Expect.isTrue(listedDir, "directory not found");
+      Expect.isTrue(listedFile, "file not found");
+      directory.delete(recursive: true).then((ignore) {
+        f.exists().then((exists) => Expect.isFalse(exists));
+        directory.exists().then((exists) => Expect.isFalse(exists));
+        subDirectory.exists().then((exists) => Expect.isFalse(exists));
+        asyncEnd();
+      });
+    });
+
+    // Listing is asynchronous, so nothing should be listed at this
+    // point.
+    Expect.isFalse(listedDir);
+    Expect.isFalse(listedFile);
+  }
+
+  static void testListingTailingPaths() {
+    Directory directory =
+        Directory.systemTemp.createTempSync('dart_directory_test');
+    Directory subDirectory = new Directory("${directory.path}/subdir/");
+    subDirectory.createSync();
+    File f = new File('${subDirectory.path}/file.txt');
+    f.createSync();
+
+    void test(entry) {
+      Expect.isFalse(entry.path.contains(new RegExp('[\\/][\\/]')));
+    }
+
+    subDirectory.listSync().forEach(test);
+
+    subDirectory.list().listen(test, onDone: () {
+      directory.deleteSync(recursive: true);
+    });
+  }
+
+  static void testListNonExistent() {
+    setupListerHandlers(Stream<FileSystemEntity> stream) {
+      stream.listen(
+          (_) => Expect.fail("Listing of non-existing directory should fail"),
+          onError: (error) {
+        Expect.isTrue(error is FileSystemException);
+      });
+    }
+
+    Directory.systemTemp.createTemp('dart_directory').then((d) {
+      d.delete().then((ignore) {
+        setupListerHandlers(d.list());
+        setupListerHandlers(d.list(recursive: true));
+      });
+    });
+  }
+
+  static void testListTooLongName() {
+    asyncStart();
+    Directory.systemTemp.createTemp('dart_directory').then((d) {
+      var errors = 0;
+      setupListHandlers(Stream<FileSystemEntity> stream) {
+        stream.listen(
+            (_) => Expect.fail("Listing of non-existing directory should fail"),
+            onError: (error) {
+          Expect.isTrue(error is FileSystemException);
+          if (++errors == 2) {
+            d.delete(recursive: true).then((_) {
+              asyncEnd();
+            });
+          }
+        });
+      }
+
+      var subDirName = 'subdir';
+      var subDir = new Directory("${d.path}/$subDirName");
+      subDir.create().then((ignore) {
+        // Construct a long string of the form
+        // 'tempdir/subdir/../subdir/../subdir'.
+        var buffer = new StringBuffer();
+        buffer.write(subDir.path);
+        for (var i = 0; i < 1000; i++) {
+          buffer.write("/../${subDirName}");
+        }
+        var long = new Directory("${buffer.toString()}");
+        setupListHandlers(long.list());
+        setupListHandlers(long.list(recursive: true));
+      });
+    });
+  }
+
+  static void testDeleteNonExistent() {
+    // Test that deleting a non-existing directory fails.
+    setupFutureHandlers(future) {
+      future.then((ignore) {
+        Expect.fail("Deletion of non-existing directory should fail");
+      }).catchError((error) {
+        Expect.isTrue(error is FileSystemException);
+      });
+    }
+
+    Directory.systemTemp.createTemp('dart_directory').then((d) {
+      d.delete().then((ignore) {
+        setupFutureHandlers(d.delete());
+        setupFutureHandlers(d.delete(recursive: true));
+      });
+    });
+  }
+
+  static void testDeleteTooLongName() {
+    asyncStart();
+    Directory.systemTemp.createTemp('dart_directory').then((d) {
+      var subDirName = 'subdir';
+      var subDir = new Directory("${d.path}/$subDirName");
+      subDir.create().then((ignore) {
+        // Construct a long string of the form
+        // 'tempdir/subdir/../subdir/../subdir'.
+        var buffer = new StringBuffer();
+        buffer.write(subDir.path);
+        for (var i = 0; i < 1000; i++) {
+          buffer.write("/../${subDirName}");
+        }
+        var long = new Directory("${buffer.toString()}");
+        var errors = 0;
+        onError(error) {
+          Expect.isTrue(error is FileSystemException);
+          if (++errors == 2) {
+            d.delete(recursive: true).then((_) => asyncEnd());
+          }
+        }
+
+        long.delete().catchError(onError);
+        long.delete(recursive: true).catchError(onError);
+      });
+    });
+  }
+
+  static void testDeleteNonExistentSync() {
+    Directory d = Directory.systemTemp.createTempSync('dart_directory_test');
+    d.deleteSync();
+    Expect.throws(d.deleteSync);
+    Expect.throws(() => d.deleteSync(recursive: true));
+  }
+
+  static void testDeleteTooLongNameSync() {
+    Directory d = Directory.systemTemp.createTempSync('dart_directory_test');
+    var subDirName = 'subdir';
+    var subDir = new Directory("${d.path}/$subDirName");
+    subDir.createSync();
+    // Construct a long string of the form
+    // 'tempdir/subdir/../subdir/../subdir'.
+    var buffer = new StringBuffer();
+    buffer.write(subDir.path);
+    for (var i = 0; i < 1000; i++) {
+      buffer.write("/../${subDirName}");
+    }
+    var long = new Directory("${buffer.toString()}");
+    Expect.throws(long.deleteSync);
+    Expect.throws(() => long.deleteSync(recursive: true));
+    d.deleteSync(recursive: true);
+  }
+
+  static void testExistsCreateDelete() {
+    Directory.systemTemp.createTemp('dart_directory').then((d) {
+      d.exists().then((bool exists) {
+        Expect.isTrue(exists);
+        Directory created = new Directory("${d.path}/subdir");
+        created.create().then((ignore) {
+          created.exists().then((bool exists) {
+            Expect.isTrue(exists);
+            created.delete().then((ignore) {
+              created.exists().then((bool exists) {
+                Expect.isFalse(exists);
+                d.delete().then((ignore) {
+                  d.exists().then((bool exists) {
+                    Expect.isFalse(exists);
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testExistsCreateDeleteSync() {
+    Directory d = Directory.systemTemp.createTempSync('dart_directory_test');
+    Directory d2 = new Directory('${d.path}/');
+    Expect.isTrue(d.existsSync());
+    Expect.isTrue(d2.existsSync());
+    Directory created = new Directory("${d.path}/subdir");
+    created.createSync();
+    Expect.isTrue(created.existsSync());
+    created.deleteSync();
+    Expect.isFalse(created.existsSync());
+    d.deleteSync();
+    Expect.isFalse(d.existsSync());
+  }
+
+  static void testDeleteLinkSync() {
+    Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test');
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    Directory d = new Directory("${path}target");
+    d.createSync();
+    Link l = new Link("${path}symlink");
+    l.createSync("${path}target");
+    Expect.isTrue(d.existsSync());
+    Expect.isTrue(l.existsSync());
+    new Directory(l.path).deleteSync(recursive: true);
+    Expect.isTrue(d.existsSync());
+    Expect.isFalse(l.existsSync());
+    d.deleteSync();
+    Expect.isFalse(d.existsSync());
+    tmp.deleteSync();
+  }
+
+  static void testDeleteLinkAsFileSync() {
+    Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test');
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    Directory d = new Directory("${path}target");
+    d.createSync();
+    Link l = new Link("${path}symlink");
+    l.createSync("${path}target");
+    Expect.isTrue(d.existsSync());
+    Expect.isTrue(l.existsSync());
+    new Link(l.path).deleteSync();
+    Expect.isTrue(d.existsSync());
+    Expect.isFalse(l.existsSync());
+    d.deleteSync();
+    Expect.isFalse(d.existsSync());
+    tmp.deleteSync();
+  }
+
+  static void testDeleteBrokenLinkAsFileSync() {
+    Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test');
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    Directory d = new Directory("${path}target");
+    d.createSync();
+    Link l = new Link("${path}symlink");
+    l.createSync("${path}target");
+    d.deleteSync();
+    Expect.isFalse(d.existsSync());
+    Expect.isTrue(l.existsSync());
+    new Link(l.path).deleteSync();
+    Expect.isFalse(l.existsSync());
+    Expect.isFalse(d.existsSync());
+    tmp.deleteSync();
+  }
+
+  static void testListBrokenLinkSync() {
+    Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test');
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    Directory d = new Directory("${path}target");
+    d.createSync();
+    Link l = new Link("${path}symlink");
+    l.createSync("${path}target");
+    d.deleteSync();
+    int count = 0;
+    tmp.list(followLinks: true).listen((file) {
+      count++;
+      Expect.isTrue(file is Link);
+    }, onDone: () {
+      Expect.equals(1, count);
+      l.deleteSync();
+      tmp.deleteSync();
+    });
+  }
+
+  static void testListLinkSync() {
+    Directory tmp = Directory.systemTemp.createTempSync('dart_directory_test');
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    Directory d = new Directory("${path}target");
+    d.createSync();
+    Link l = new Link("${path}symlink");
+    l.createSync("${path}target");
+    int count = 0;
+    tmp.list(followLinks: true).listen((file) {
+      count++;
+      Expect.isTrue(file is Directory);
+    }, onDone: () {
+      Expect.equals(2, count);
+      l.deleteSync();
+      d.deleteSync();
+      tmp.deleteSync();
+    });
+  }
+
+  static void testCreateTemp() {
+    Directory base = new Directory('/tmp');
+    String template = 'dart_temp_dir';
+    if (base.existsSync()) {
+      asyncStart();
+      Future.wait([base.createTemp(template), base.createTemp(template)])
+          .then((tempDirs) {
+        Expect.notEquals(tempDirs[0].path, tempDirs[1].path);
+        for (Directory t in tempDirs) {
+          Expect.isTrue(t.existsSync());
+          t.deleteSync();
+          Expect.isFalse(t.existsSync());
+        }
+        asyncEnd();
+      });
+    }
+  }
+
+  static void testCreateSystemTemp() {
+    String template = 'dart_system_temp_dir';
+    asyncStart();
+    Future.wait([
+      Directory.systemTemp.createTemp(template),
+      Directory.systemTemp.createTemp(template)
+    ]).then((tempDirs) {
+      Expect.notEquals(tempDirs[0].path, tempDirs[1].path);
+      for (Directory t in tempDirs) {
+        Expect.isTrue(t.existsSync());
+        t.deleteSync();
+        Expect.isFalse(t.existsSync());
+      }
+      asyncEnd();
+    });
+  }
+
+  static void testCreateDeleteTemp() {
+    Directory.systemTemp.createTemp('dart_directory').then((tempDirectory) {
+      String filename =
+          "${tempDirectory.path}${Platform.pathSeparator}dart_testfile";
+      File file = new File(filename);
+      Expect.isFalse(file.existsSync());
+      file.create().then((ignore) {
+        file.exists().then((exists) {
+          Expect.isTrue(exists);
+          // Try to delete the directory containing the file - should throw.
+          Expect.throws(tempDirectory.deleteSync);
+          Expect.isTrue(tempDirectory.existsSync());
+
+          // Delete the file, and then delete the directory.
+          file.delete().then((ignore) {
+            tempDirectory.deleteSync();
+            Expect.isFalse(tempDirectory.existsSync());
+          });
+        });
+      });
+    });
+  }
+
+  static void testCurrent() {
+    Directory current = Directory.current;
+    if (Platform.operatingSystem != "windows") {
+      Expect.equals("/", current.path.substring(0, 1));
+    }
+  }
+
+  static void testEquals() {
+    var name = new File('.').resolveSymbolicLinksSync();
+    Directory current1 = new Directory(name);
+    Directory current2 = new Directory(name);
+    Expect.equals(current1.path, current2.path);
+    Expect.isTrue(current1.existsSync());
+  }
+
+  static void testMain() {
+    testListing();
+    testListingTailingPaths();
+    testListNonExistent();
+    testListTooLongName();
+    testDeleteNonExistent();
+    testDeleteTooLongName();
+    testDeleteNonExistentSync();
+    testDeleteTooLongNameSync();
+    testExistsCreateDelete();
+    testExistsCreateDeleteSync();
+    testDeleteLinkSync();
+    testDeleteLinkAsFileSync();
+    testDeleteBrokenLinkAsFileSync();
+    testListBrokenLinkSync();
+    testListLinkSync();
+    testCreateTemp();
+    testCreateSystemTemp();
+    testCreateDeleteTemp();
+    testCurrent();
+    testEquals();
+  }
+}
+
+class NestedTempDirectoryTest {
+  List<Directory> createdDirectories;
+
+  NestedTempDirectoryTest.run() : createdDirectories = new List<Directory>() {
+    Directory.systemTemp.createTemp('dart_directory').then(createPhaseCallback);
+  }
+
+  void createPhaseCallback(temp) {
+    createdDirectories.add(temp);
+    int nestingDepth = 6;
+    var os = Platform.operatingSystem;
+    if (os == "windows") nestingDepth = 2;
+    if (createdDirectories.length < nestingDepth) {
+      temp
+          .createTemp('nested_temp_dir_${createdDirectories.length}_')
+          .then(createPhaseCallback);
+    } else {
+      deletePhaseCallback();
+    }
+  }
+
+  void deletePhaseCallback() {
+    if (!createdDirectories.isEmpty) {
+      final current = createdDirectories.removeLast();
+      current.deleteSync();
+      deletePhaseCallback();
+    }
+  }
+
+  static void testMain() {
+    new NestedTempDirectoryTest.run();
+    new NestedTempDirectoryTest.run();
+  }
+}
+
+String? illegalTempDirectoryLocation() {
+  // Determine a platform specific illegal location for a temporary directory.
+  var os = Platform.operatingSystem;
+  if (os == "linux" || os == "macos") {
+    return "/dev/zero/";
+  }
+  if (os == "windows") {
+    return "*";
+  }
+  return null;
+}
+
+testCreateTempErrorSync() {
+  var location = illegalTempDirectoryLocation();
+  if (location != null) {
+    Expect.throws(() => new Directory(location).createTempSync('dart_tempdir'),
+        (e) => e is FileSystemException);
+  }
+}
+
+testCreateTempError() {
+  var location = illegalTempDirectoryLocation();
+  if (location == null) return;
+
+  asyncStart();
+  var future = new Directory(location).createTemp('dart_tempdir');
+  future.catchError((_) => asyncEnd());
+}
+
+testCreateExistingSync() {
+  // Test that creating an existing directory succeeds.
+  var temp = Directory.systemTemp.createTempSync('directory_test');
+  var subDir = new Directory('${temp.path}/flaf');
+  Expect.isFalse(subDir.existsSync());
+  subDir.createSync();
+  Expect.isTrue(subDir.existsSync());
+  subDir.createSync();
+  Expect.isTrue(subDir.existsSync());
+  temp.deleteSync(recursive: true);
+}
+
+testCreateExisting() {
+  // Test that creating an existing directory succeeds.
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory').then((temp) {
+    var subDir = new Directory('${temp.path}/flaf');
+    subDir.exists().then((dirExists) {
+      Expect.isFalse(dirExists);
+      subDir.create().then((_) {
+        subDir.exists().then((dirExists) {
+          Expect.isTrue(dirExists);
+          subDir.create().then((_) {
+            subDir.exists().then((dirExists) {
+              Expect.isTrue(dirExists);
+              temp.delete(recursive: true).then((_) {
+                asyncEnd();
+              });
+            });
+          });
+        });
+      });
+    });
+  });
+}
+
+testCreateDirExistingFileSync() {
+  // Test that creating an existing directory succeeds.
+  var temp = Directory.systemTemp.createTempSync('directory_test');
+  var path = '${temp.path}/flaf';
+  var file = new File(path);
+  file.createSync();
+  Expect.isTrue(file.existsSync());
+  Expect.throws(
+      new Directory(path).createSync, (e) => e is FileSystemException);
+  temp.deleteSync(recursive: true);
+}
+
+testCreateDirExistingFile() {
+  // Test that creating an existing directory succeeds.
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_directory').then((temp) {
+    var path = '${temp.path}/flaf';
+    var file = new File(path);
+    var subDir = new Directory(path);
+    file.create().then((_) {
+      subDir.create().then((_) {
+        Expect.fail("dir create should fail on existing file");
+      }).catchError((error) {
+        Expect.isTrue(error is FileSystemException);
+        temp.delete(recursive: true).then((_) {
+          asyncEnd();
+        });
+      });
+    });
+  });
+}
+
+testRename() {
+  var temp1 = Directory.systemTemp.createTempSync('directory_test');
+  var temp2 = Directory.systemTemp.createTempSync('directory_test');
+  var temp3 = temp1.renameSync(temp2.path);
+  Expect.isFalse(temp1.existsSync());
+  Expect.isTrue(temp2.existsSync());
+  Expect.equals(temp3.path, temp2.path);
+
+  var temp4 = temp2.renameSync(temp1.path);
+  Expect.isFalse(temp3.existsSync());
+  Expect.isFalse(temp2.existsSync());
+  Expect.isTrue(temp1.existsSync());
+  Expect.isTrue(temp4.existsSync());
+  Expect.equals(temp1.path, temp4.path);
+
+  String foo = '${temp4.path}/foo';
+  String bar = '${temp4.path}/bar';
+  new File(foo).createSync();
+  try {
+    new Directory(foo).renameSync(bar);
+    Expect.fail('Directory.rename should fail to rename a non-directory');
+  } catch (e) {
+    Expect.isTrue(e is FileSystemException);
+    if (Platform.isLinux || Platform.isMacOS) {
+      Expect.isTrue(e.osError.message.contains('Not a directory'));
+    }
+  }
+
+  temp1.deleteSync(recursive: true);
+}
+
+main() {
+  DirectoryTest.testMain();
+  NestedTempDirectoryTest.testMain();
+  testCreateTempErrorSync();
+  testCreateTempError();
+  testCreateExistingSync();
+  testCreateExisting();
+  testCreateDirExistingFileSync();
+  testCreateDirExistingFile();
+  testRename();
+}
diff --git a/tests/standalone/io/directory_uri_test.dart b/tests/standalone/io/directory_uri_test.dart
new file mode 100644
index 0000000..df94d95
--- /dev/null
+++ b/tests/standalone/io/directory_uri_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:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testFromUri() {
+  asyncStart();
+  Directory originalWorkingDirectory = Directory.current;
+  Directory.systemTemp.createTemp('directory_uri').then((temp) {
+    String dirname = temp.path + '/from_uri';
+    Uri dirUri = new Uri.file(dirname);
+    Directory dir = new Directory.fromUri(dirUri);
+    Expect.isTrue(dirUri.isAbsolute);
+    Expect.isTrue(dirUri.path.startsWith('/'));
+    dir.createSync();
+    Expect.isTrue(new Directory.fromUri(dirUri).existsSync());
+    Expect.isTrue(
+        new Directory.fromUri(Uri.base.resolveUri(dirUri)).existsSync());
+    Directory.current = temp.path;
+    Expect.isTrue(new Directory.fromUri(Uri.parse('from_uri')).existsSync());
+    Expect.isTrue(
+        new Directory.fromUri(Uri.base.resolve('from_uri')).existsSync());
+    Directory.current = originalWorkingDirectory;
+    dir.deleteSync();
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testFromUriUnsupported() {
+  Expect.throwsUnsupportedError(() =>
+      new Directory.fromUri(Uri.parse('http://localhost:8080/index.html')));
+  Expect.throwsUnsupportedError(
+      () => new Directory.fromUri(Uri.parse('ftp://localhost/tmp/xxx')));
+  Expect.throwsUnsupportedError(
+      () => new Directory.fromUri(Uri.parse('name#fragment')));
+}
+
+void main() {
+  testFromUri();
+  testFromUriUnsupported();
+}
diff --git a/tests/standalone/io/disable_exit_test.dart b/tests/standalone/io/disable_exit_test.dart
new file mode 100644
index 0000000..f9d467d
--- /dev/null
+++ b/tests/standalone/io/disable_exit_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.
+// VMOptions=--disable-exit
+
+import "dart:io" as io;
+
+import "package:expect/expect.dart";
+
+void main() {
+  Expect.throws(() {
+    io.exit(-1);
+  }, (e) => (e is UnsupportedError));
+}
diff --git a/tests/standalone/io/echo_server_stream_test.dart b/tests/standalone/io/echo_server_stream_test.dart
new file mode 100644
index 0000000..6da8ca2
--- /dev/null
+++ b/tests/standalone/io/echo_server_stream_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// Echo server test program to test socket streams.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+library ServerTest;
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+part "testing_server.dart";
+
+class EchoServerGame {
+  static const MSGSIZE = 10;
+  static const MESSAGES = 100;
+  static const FIRSTCHAR = 65;
+
+  EchoServerGame.start() {
+    for (int i = 0; i < MSGSIZE; i++) {
+      _buffer[i] = FIRSTCHAR + i;
+    }
+    initialize();
+  }
+
+  void sendData() {
+    int offset = 0;
+    List<int> data;
+
+    void onData(List<int> data) {
+      int bytesRead = data.length;
+      for (int i = 0; i < data.length; i++) {
+        Expect.equals(FIRSTCHAR + i + offset, data[i]);
+      }
+      offset += bytesRead;
+    }
+
+    void onClosed() {
+      Expect.equals(MSGSIZE, offset);
+      _messages++;
+      if (_messages < MESSAGES) {
+        sendData();
+      } else {
+        shutdown();
+      }
+    }
+
+    void errorHandler(e, trace) {
+      String msg = "Socket error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    }
+
+    void connectHandler() {
+      _socket.listen(onData, onError: errorHandler, onDone: onClosed);
+      _socket.add(_buffer);
+      _socket.close();
+      data = new List<int>.filled(MSGSIZE, 0);
+    }
+
+    Socket.connect(TestingServer.HOST, _port).then((s) {
+      _socket = s;
+      connectHandler();
+    });
+  }
+
+  void initialize() {
+    var receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startEchoServer, receivePort.sendPort);
+    receivePort.first.then((msg) {
+      this._port = msg[0];
+      this._closeSendPort = msg[1];
+      sendData();
+    });
+  }
+
+  void shutdown() {
+    _closeSendPort.send(null);
+    asyncEnd();
+  }
+
+  late int _port;
+  late SendPort _closeSendPort;
+  late Socket _socket;
+  final _buffer = new List<int>.filled(MSGSIZE, 0);
+  int _messages = 0;
+}
+
+void startEchoServer(Object replyPortObj) {
+  SendPort replyPort = replyPortObj as SendPort;
+  var server = new EchoServer();
+  server.init().then((port) {
+    replyPort.send([port, server.closeSendPort]);
+  });
+}
+
+class EchoServer extends TestingServer {
+  static const int MSGSIZE = EchoServerGame.MSGSIZE;
+
+  void onConnection(Socket connection) {
+    List<int> buffer = new List<int>.filled(MSGSIZE, 0);
+    int offset = 0;
+
+    void dataReceived(List<int> data) {
+      int bytesRead;
+      bytesRead = data.length;
+      if (bytesRead > 0) {
+        buffer.setRange(offset, offset + data.length, data);
+        offset += bytesRead;
+        for (int i = 0; i < offset; i++) {
+          Expect.equals(EchoServerGame.FIRSTCHAR + i, buffer[i]);
+        }
+        if (offset == MSGSIZE) {
+          connection.add(buffer);
+          connection.close();
+        }
+      }
+    }
+
+    void errorHandler(e, trace) {
+      String msg = "Socket error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    }
+
+    connection.listen(dataReceived, onError: errorHandler);
+  }
+}
+
+main() {
+  asyncStart();
+  EchoServerGame echoServerGame = new EchoServerGame.start();
+}
diff --git a/tests/standalone/io/empty_file b/tests/standalone/io/empty_file
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/standalone/io/empty_file
diff --git a/tests/standalone/io/file_absolute_path_test.dart b/tests/standalone/io/file_absolute_path_test.dart
new file mode 100644
index 0000000..bd5d97e
--- /dev/null
+++ b/tests/standalone/io/file_absolute_path_test.dart
@@ -0,0 +1,68 @@
+// 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 program for testing FileSystemEntity.absolute
+
+import "package:expect/expect.dart";
+import 'dart:io';
+
+main() {
+  if (Platform.isWindows) {
+    testWindows();
+    try {
+      Directory.current = 'C:\\';
+    } catch (e) {
+      return;
+    }
+    testWindows();
+  } else {
+    testPosix();
+    Directory.current = '.';
+    testPosix();
+    Directory.current = '/';
+    testPosix();
+  }
+}
+
+testWindows() {
+  String current = Directory.current.path;
+  for (String relative in ['abd', '..', '.', 'efg/hij', 'abc/']) {
+    if (current.endsWith('\\')) {
+      Expect.equals(new File(relative).absolute.path, '$current$relative');
+    } else {
+      Expect.equals(new File(relative).absolute.path, '$current\\$relative');
+    }
+    Expect.isTrue(new File(relative).absolute.isAbsolute);
+  }
+  for (String absolute in [
+    'c:/abd',
+    'D:\\rf',
+    '\\\\a_share\\folder',
+    '\\\\?\\c:\\prefixed\path\\'
+  ]) {
+    Expect.isTrue(new File(absolute).absolute.path == absolute);
+    Expect.isTrue(new File(absolute).absolute.isAbsolute);
+  }
+}
+
+testPosix() {
+  String current = Directory.current.path;
+  for (String relative in ['abd', '..', '.', 'efg/hij', 'abc/']) {
+    if (current.endsWith('/')) {
+      Expect.equals(new File(relative).absolute.path, '$current$relative');
+    } else {
+      Expect.equals(new File(relative).absolute.path, '$current/$relative');
+    }
+    Expect.isTrue(new File(relative).absolute.isAbsolute);
+    Expect.equals(new Directory(relative).absolute.path,
+        new Link(relative).absolute.path);
+    Expect.isTrue(new File(relative).absolute is File);
+    Expect.isTrue(new Directory(relative).absolute is Directory);
+    Expect.isTrue(new Link(relative).absolute is Link);
+  }
+  for (String absolute in ['/abd', '/', '/./..\\', '/efg/hij', '/abc/']) {
+    Expect.equals(new File(absolute).absolute.path, absolute);
+    Expect.isTrue(new File(absolute).absolute.isAbsolute);
+  }
+}
diff --git a/tests/standalone/io/file_blocking_lock_script.dart b/tests/standalone/io/file_blocking_lock_script.dart
new file mode 100644
index 0000000..00f8bb5
--- /dev/null
+++ b/tests/standalone/io/file_blocking_lock_script.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.
+//
+// Script used by the file_lock_test.dart test.
+
+import "dart:async";
+import "dart:io";
+
+Future<int> testLockWholeFile(File file, int len) async {
+  var raf = await file.open(mode: FileMode.append);
+  await raf.setPosition(0);
+  int nextToWrite = 1;
+  await raf.lock(FileLock.blockingExclusive, 0, len);
+
+  // Make sure the peer fails a non-blocking lock at some point.
+  await new Future.delayed(const Duration(seconds: 1));
+
+  int p = 0;
+  while (p < len) {
+    await raf.writeByte(1);
+    p++;
+  }
+  await raf.unlock(0, len);
+  await raf.close();
+  return 0;
+}
+
+main(List<String> args) async {
+  File file = new File(args[0]);
+  int len = int.parse(args[1]);
+  exit(await testLockWholeFile(file, len));
+}
diff --git a/tests/standalone/io/file_blocking_lock_test.dart b/tests/standalone/io/file_blocking_lock_test.dart
new file mode 100644
index 0000000..85e58ce
--- /dev/null
+++ b/tests/standalone/io/file_blocking_lock_test.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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=file_blocking_lock_script.dart
+
+// This test works by spawning a new process running
+// file_blocking_lock_script.dart, trading the file lock back and forth,
+// writing bytes 1 ... 25 in order to the file. There are checks to ensure
+// that the bytes are written in order, that one process doesn't write all the
+// bytes and that a non-blocking lock fails such that a blocking lock must
+// be taken, which succeeds.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+// Check whether the file is locked or not.
+runPeer(String path, int len, FileLock mode) {
+  var script =
+      Platform.script.resolve('file_blocking_lock_script.dart').toFilePath();
+  var arguments = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..add(script)
+    ..add(path)
+    ..add(len.toString());
+  return Process.start(Platform.executable, arguments).then((process) {
+    process.stdout.transform(utf8.decoder).listen((data) {
+      print(data);
+    });
+    process.stderr.transform(utf8.decoder).listen((data) {
+      print(data);
+    });
+    return process;
+  });
+}
+
+const int peerTimeoutMilliseconds = 30000;
+
+Future<bool> waitForPeer(RandomAccessFile raf, int length) async {
+  Stopwatch s = new Stopwatch();
+  s.start();
+  while (true) {
+    await raf.unlock(0, length);
+    if (s.elapsedMilliseconds > peerTimeoutMilliseconds) {
+      s.stop();
+      return false;
+    }
+    try {
+      await raf.lock(FileLock.exclusive, 0, length);
+    } catch (_) {
+      await raf.lock(FileLock.blockingExclusive, 0, length);
+      break;
+    }
+  }
+  s.stop();
+  return true;
+}
+
+testLockWholeFile() async {
+  const int length = 25;
+  Directory directory = await Directory.systemTemp.createTemp('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  await file.writeAsBytes(new List.filled(length, 0));
+  var raf = await file.open(mode: FileMode.append);
+  await raf.lock(FileLock.blockingExclusive, 0, length);
+  Process peer = await runPeer(file.path, length, FileLock.blockingExclusive);
+
+  // If the peer doesn't come up within the timeout, then give up on the test
+  // to avoid the test being flaky.
+  if (!await waitForPeer(raf, length)) {
+    await raf.close();
+    await directory.delete(recursive: true);
+    return;
+  }
+
+  // Check that the peer wrote to the file.
+  int p = 0;
+  await raf.setPosition(0);
+  while (p < length) {
+    int at = await raf.readByte();
+    Expect.equals(1, at);
+    p++;
+  }
+  await raf.unlock(0, length);
+
+  // Check that the peer exited successfully.
+  int v = await peer.exitCode;
+  Expect.equals(0, v);
+  await raf.close();
+  await directory.delete(recursive: true);
+}
+
+main() async {
+  asyncStart();
+  await testLockWholeFile();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/file_constructor_test.dart b/tests/standalone/io/file_constructor_test.dart
new file mode 100644
index 0000000..364460d
--- /dev/null
+++ b/tests/standalone/io/file_constructor_test.dart
@@ -0,0 +1,16 @@
+// 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 'dart:io';
+
+void main() {
+  new File('blåbærgrød');
+  new File('foo.txt');
+  try {
+    dynamic one = 1;
+    new File(one);
+    Expect.fail('Error expected.');
+  } on TypeError catch (e) {}
+}
diff --git a/tests/standalone/io/file_copy_test.dart b/tests/standalone/io/file_copy_test.dart
new file mode 100644
index 0000000..2302a4a
--- /dev/null
+++ b/tests/standalone/io/file_copy_test.dart
@@ -0,0 +1,79 @@
+// 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 program for testing File.copy*
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+const FILE_CONTENT1 = 'some string';
+const FILE_CONTENT2 = 'some other string';
+
+void testCopySync() {
+  var tmp = Directory.systemTemp.createTempSync('dart-file-copy');
+
+  var file1 = new File('${tmp.path}/file1');
+  file1.writeAsStringSync(FILE_CONTENT1);
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+
+  // Copy to new file works.
+  var file2 = file1.copySync('${tmp.path}/file2');
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+  Expect.equals(FILE_CONTENT1, file2.readAsStringSync());
+
+  // Override works for files.
+  file2.writeAsStringSync(FILE_CONTENT2);
+  file2.copySync(file1.path);
+  Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+  Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
+
+  // Fail when coping to directory.
+  var dir = new Directory('${tmp.path}/dir')..createSync();
+  Expect.throws(() => file1.copySync(dir.path));
+  Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+
+  tmp.deleteSync(recursive: true);
+}
+
+void testCopy() {
+  asyncStart();
+  var tmp = Directory.systemTemp.createTempSync('dart-file-copy');
+
+  var file1 = new File('${tmp.path}/file1');
+  file1.writeAsStringSync(FILE_CONTENT1);
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+
+  // Copy to new file works.
+  file1.copy('${tmp.path}/file2').then((file2) {
+    Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+    Expect.equals(FILE_CONTENT1, file2.readAsStringSync());
+
+    // Override works for files.
+    file2.writeAsStringSync(FILE_CONTENT2);
+    return file2.copy(file1.path).then((_) {
+      Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+      Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
+
+      // Fail when coping to directory.
+      var dir = new Directory('${tmp.path}/dir')..createSync();
+
+      return file1
+          .copy(dir.path)
+          .then((_) => Expect.fail('expected error'), onError: (_) {})
+          .then((_) {
+        Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+      });
+    });
+  }).whenComplete(() {
+    tmp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+main() {
+  testCopySync();
+  testCopy();
+}
diff --git a/tests/standalone/io/file_create_test.dart b/tests/standalone/io/file_create_test.dart
new file mode 100644
index 0000000..126ac4a
--- /dev/null
+++ b/tests/standalone/io/file_create_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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 file creation.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+testCreate() async {
+  Directory tmp = await Directory.systemTemp.createTemp('file_test_create');
+  Expect.isTrue(await tmp.exists());
+  String filePath = "${tmp.path}/foo";
+  File file = new File(filePath);
+  File createdFile = await file.create();
+  Expect.equals(file, createdFile);
+  Expect.isTrue(await createdFile.exists());
+  await tmp.delete(recursive: true);
+}
+
+testBadCreate() async {
+  Directory tmp = await Directory.systemTemp.createTemp('file_test_create');
+  Expect.isTrue(await tmp.exists());
+  Directory tmp2 = await tmp.createTemp('file_test_create');
+  Expect.isTrue(await tmp2.exists());
+  String badFilePath = tmp2.path;
+  File badFile = new File(badFilePath);
+  try {
+    await badFile.create();
+    Expect.fail('Should be unreachable');
+  } catch (e) {
+    Expect.isTrue(e is FileSystemException);
+    Expect.isNotNull(e.osError);
+  }
+  await tmp.delete(recursive: true);
+}
+
+main() async {
+  await testCreate();
+  await testBadCreate();
+}
diff --git a/tests/standalone/io/file_error2_test.dart b/tests/standalone/io/file_error2_test.dart
new file mode 100644
index 0000000..e8751c8
--- /dev/null
+++ b/tests/standalone/io/file_error2_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.
+//
+// Dart test program for testing error handling in file I/O.
+//
+// Customize ASAN options for this test with 'allocator_may_return_null=1' as
+// it tries to allocate a large memory buffer.
+// Environment=ASAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
+// Environment=LSAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
+// Environment=MSAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
+
+import "dart:io";
+
+import "file_error_test.dart" show createTestFile;
+import "package:expect/expect.dart";
+
+testReadSyncBigInt() {
+  createTestFile((file, done) {
+    var bigint = 9223372036854775807;
+    var openedFile = file.openSync();
+    Expect.throws(
+        () => openedFile.readSync(bigint), (e) => e is FileSystemException);
+    openedFile.closeSync();
+    done();
+  });
+}
+
+main() {
+  testReadSyncBigInt();
+}
diff --git a/tests/standalone/io/file_error_test.dart b/tests/standalone/io/file_error_test.dart
new file mode 100644
index 0000000..27733f7
--- /dev/null
+++ b/tests/standalone/io/file_error_test.dart
@@ -0,0 +1,427 @@
+// 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 program for testing error handling in file I/O.
+
+import "dart:convert";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Directory tempDir() {
+  return Directory.systemTemp.createTempSync('dart_file_error');
+}
+
+bool checkNonExistentFileSystemException(e, str) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf(str) != -1);
+  // File not not found has error code 2 on all supported platforms.
+  Expect.equals(2, e.osError.errorCode);
+  return true;
+}
+
+bool checkOpenNonExistentFileSystemException(e) {
+  return checkNonExistentFileSystemException(e, "Cannot open file");
+}
+
+bool checkDeleteNonExistentFileSystemException(e) {
+  return checkNonExistentFileSystemException(e, "Cannot delete file");
+}
+
+bool checkLengthNonExistentFileSystemException(e) {
+  return checkNonExistentFileSystemException(
+      e, "Cannot retrieve length of file");
+}
+
+void testOpenNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile");
+
+  // Non-existing file should throw exception.
+  Expect.throws(
+      () => file.openSync(), (e) => checkOpenNonExistentFileSystemException(e));
+
+  var openFuture = file.open(mode: FileMode.read);
+  openFuture.then((raf) => Expect.fail("Unreachable code")).catchError((error) {
+    checkOpenNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testDeleteNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile");
+
+  // Non-existing file should throw exception.
+  Expect.throws(() => file.deleteSync(),
+      (e) => checkDeleteNonExistentFileSystemException(e));
+
+  var delete = file.delete();
+  delete.then((ignore) => Expect.fail("Unreachable code")).catchError((error) {
+    checkDeleteNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLengthNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile");
+
+  // Non-existing file should throw exception.
+  Expect.throws(() => file.lengthSync(),
+      (e) => checkLengthNonExistentFileSystemException(e));
+
+  var lenFuture = file.length();
+  lenFuture.then((len) => Expect.fail("Unreachable code")).catchError((error) {
+    checkLengthNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+bool checkCreateInNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf("Cannot create file") != -1);
+  if (Platform.operatingSystem == "linux") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "macos") {
+    Expect.equals(2, e.osError.errorCode);
+  } else if (Platform.operatingSystem == "windows") {
+    Expect.equals(3, e.osError.errorCode);
+  }
+
+  return true;
+}
+
+void testCreateInNonExistentDirectory() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentDirectory/newFile");
+
+  // Create in non-existent directory should throw exception.
+  Expect.throws(() => file.createSync(),
+      (e) => checkCreateInNonExistentFileSystemException(e));
+
+  var create = file.create();
+  create.then((ignore) => Expect.fail("Unreachable code")).catchError((error) {
+    checkCreateInNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+bool checkResolveSymbolicLinksOnNonExistentFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.toString().indexOf("Cannot resolve symbolic links") != -1);
+  // File not not found has error code 2 on all supported platforms.
+  Expect.equals(2, e.osError.errorCode);
+
+  return true;
+}
+
+void testResolveSymbolicLinksOnNonExistentDirectory() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentDirectory");
+
+  // Full path non-existent directory should throw exception.
+  Expect.throws(() => file.resolveSymbolicLinksSync(),
+      (e) => checkResolveSymbolicLinksOnNonExistentFileSystemException(e));
+
+  var resolvedFuture = file.resolveSymbolicLinks();
+  resolvedFuture
+      .then((path) => Expect.fail("Unreachable code $path"))
+      .catchError((error) {
+    checkResolveSymbolicLinksOnNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testReadAsBytesNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile3");
+
+  // Non-existing file should throw exception.
+  Expect.throws(() => file.readAsBytesSync(),
+      (e) => checkOpenNonExistentFileSystemException(e));
+
+  var readAsBytesFuture = file.readAsBytes();
+  readAsBytesFuture
+      .then((data) => Expect.fail("Unreachable code"))
+      .catchError((error) {
+    checkOpenNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testReadAsTextNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile4");
+
+  // Non-existing file should throw exception.
+  Expect.throws(() => file.readAsStringSync(),
+      (e) => checkOpenNonExistentFileSystemException(e));
+
+  var readAsStringFuture = file.readAsString(encoding: ascii);
+  readAsStringFuture
+      .then((data) => Expect.fail("Unreachable code"))
+      .catchError((error) {
+    checkOpenNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+testReadAsLinesNonExistent() {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/nonExistentFile5");
+
+  // Non-existing file should throw exception.
+  Expect.throws(() => file.readAsLinesSync(),
+      (e) => checkOpenNonExistentFileSystemException(e));
+
+  var readAsLinesFuture = file.readAsLines(encoding: ascii);
+  readAsLinesFuture
+      .then((data) => Expect.fail("Unreachable code"))
+      .catchError((error) {
+    checkOpenNonExistentFileSystemException(error);
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+bool checkWriteReadOnlyFileSystemException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.osError != null);
+  Expect.isTrue(e.osError.errorCode != OSError.noErrorCode);
+  return true;
+}
+
+// Create a test file in a temporary directory. Setup a port to signal
+// when the temporary directory should be deleted. Pass the file and
+// the port to the callback argument.
+createTestFile(callback) {
+  asyncStart();
+  Directory temp = tempDir();
+  var file = new File("${temp.path}/test_file");
+  file.createSync();
+  callback(file, () {
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+testWriteByteToReadOnlyFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync(mode: FileMode.read);
+
+    // Writing to read only file should throw an exception.
+    Expect.throws(() => openedFile.writeByteSync(0),
+        (e) => checkWriteReadOnlyFileSystemException(e));
+
+    var writeByteFuture = openedFile.writeByte(0);
+    writeByteFuture.catchError((error) {
+      checkWriteReadOnlyFileSystemException(error);
+      openedFile.close().then((_) => done());
+    });
+  });
+}
+
+testWriteFromToReadOnlyFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync(mode: FileMode.read);
+
+    List data = [0, 1, 2, 3];
+    // Writing to read only file should throw an exception.
+    Expect.throws(() => openedFile.writeFromSync(data, 0, data.length),
+        (e) => checkWriteReadOnlyFileSystemException(e));
+
+    var writeFromFuture = openedFile.writeFrom(data, 0, data.length);
+    writeFromFuture.catchError((error) {
+      checkWriteReadOnlyFileSystemException(error);
+      openedFile.close().then((_) => done());
+    });
+  });
+}
+
+testTruncateReadOnlyFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeByteSync(0);
+    openedFile.closeSync();
+    openedFile = file.openSync(mode: FileMode.read);
+
+    // Truncating read only file should throw an exception.
+    Expect.throws(() => openedFile.truncateSync(0),
+        (e) => checkWriteReadOnlyFileSystemException(e));
+
+    var truncateFuture = openedFile.truncate(0);
+    truncateFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError((error) {
+      checkWriteReadOnlyFileSystemException(error);
+      openedFile.close().then((_) => done());
+    });
+  });
+}
+
+bool checkFileClosedException(e) {
+  Expect.isTrue(e is FileSystemException);
+  Expect.isTrue(e.toString().indexOf("File closed") != -1);
+  Expect.isTrue(e.osError == null);
+  return true;
+}
+
+testOperateOnClosedFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync(mode: FileMode.read);
+    openedFile.closeSync();
+
+    List data = [0, 1, 2, 3];
+    Expect.throws(
+        () => openedFile.readByteSync(), (e) => checkFileClosedException(e));
+    Expect.throws(
+        () => openedFile.writeByteSync(0), (e) => checkFileClosedException(e));
+    Expect.throws(() => openedFile.writeFromSync(data, 0, data.length),
+        (e) => checkFileClosedException(e));
+    Expect.throws(() => openedFile.readIntoSync(data, 0, data.length),
+        (e) => checkFileClosedException(e));
+    Expect.throws(() => openedFile.writeStringSync("Hello"),
+        (e) => checkFileClosedException(e));
+    Expect.throws(
+        () => openedFile.positionSync(), (e) => checkFileClosedException(e));
+    Expect.throws(() => openedFile.setPositionSync(0),
+        (e) => checkFileClosedException(e));
+    Expect.throws(
+        () => openedFile.truncateSync(0), (e) => checkFileClosedException(e));
+    Expect.throws(
+        () => openedFile.lengthSync(), (e) => checkFileClosedException(e));
+    Expect.throws(
+        () => openedFile.flushSync(), (e) => checkFileClosedException(e));
+
+    var errorCount = 0;
+
+    _errorHandler(error) {
+      checkFileClosedException(error);
+      if (--errorCount == 0) {
+        done();
+      }
+    }
+
+    var readByteFuture = openedFile.readByte();
+    readByteFuture
+        .then((byte) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var writeByteFuture = openedFile.writeByte(0);
+    writeByteFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var readIntoFuture = openedFile.readInto(data, 0, data.length);
+    readIntoFuture
+        .then((bytesRead) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var writeFromFuture = openedFile.writeFrom(data, 0, data.length);
+    writeFromFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var writeStringFuture = openedFile.writeString("Hello");
+    writeStringFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var positionFuture = openedFile.position();
+    positionFuture
+        .then((position) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var setPositionFuture = openedFile.setPosition(0);
+    setPositionFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var truncateFuture = openedFile.truncate(0);
+    truncateFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var lenFuture = openedFile.length();
+    lenFuture
+        .then((length) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+    var flushFuture = openedFile.flush();
+    flushFuture
+        .then((ignore) => Expect.fail("Unreachable code"))
+        .catchError(_errorHandler);
+    errorCount++;
+  });
+}
+
+testRepeatedlyCloseFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync();
+    openedFile.close().then((ignore) {
+      var closeFuture = openedFile.close();
+      closeFuture.then((ignore) => null).catchError((error) {
+        Expect.isTrue(error is FileSystemException);
+        done();
+      });
+    });
+  });
+}
+
+testRepeatedlyCloseFileSync() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync();
+    openedFile.closeSync();
+    Expect.throws(openedFile.closeSync, (e) => e is FileSystemException);
+    done();
+  });
+}
+
+testReadSyncClosedFile() {
+  createTestFile((file, done) {
+    var openedFile = file.openSync();
+    openedFile.closeSync();
+    Expect.throws(
+        () => openedFile.readSync(1), (e) => e is FileSystemException);
+    done();
+  });
+}
+
+main() {
+  testOpenNonExistent();
+  testDeleteNonExistent();
+  testLengthNonExistent();
+  testCreateInNonExistentDirectory();
+  testResolveSymbolicLinksOnNonExistentDirectory();
+  testReadAsBytesNonExistent();
+  testReadAsTextNonExistent();
+  testReadAsLinesNonExistent();
+  testWriteByteToReadOnlyFile();
+  testWriteFromToReadOnlyFile();
+  testTruncateReadOnlyFile();
+  testOperateOnClosedFile();
+  testRepeatedlyCloseFile();
+  testRepeatedlyCloseFileSync();
+  testReadSyncClosedFile();
+}
diff --git a/tests/standalone/io/file_fuzz_test.dart b/tests/standalone/io/file_fuzz_test.dart
new file mode 100644
index 0000000..82dd4ac
--- /dev/null
+++ b/tests/standalone/io/file_fuzz_test.dart
@@ -0,0 +1,126 @@
+// 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.
+
+// 'fuzz' test the file APIs by providing unexpected type arguments. The test
+// passes if the VM does not crash.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'fuzz_support.dart';
+
+import "package:async_helper/async_helper.dart";
+
+fuzzSyncMethods() {
+  typeMapping.forEach((k, v) {
+    late File f;
+    doItSync(() => f = new File(v as String));
+    if (f == null) return;
+    doItSync(f.existsSync);
+    doItSync(f.createSync);
+    doItSync(f.deleteSync);
+    doItSync(f.lengthSync);
+    doItSync(f.lastModifiedSync);
+    doItSync(() => f.path);
+    doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
+    doItSync(f.readAsBytesSync);
+    doItSync(f.readAsStringSync);
+    doItSync(f.readAsLinesSync);
+    typeMapping.forEach((k2, v2) {
+      doItSync(() => f.openSync(mode: v2 as FileMode));
+      doItSync(() => f.openWrite(mode: v2 as FileMode));
+      doItSync(() => f.readAsStringSync(encoding: v2 as Encoding));
+      doItSync(() => f.readAsLinesSync(encoding: v2 as Encoding));
+    });
+  });
+}
+
+fuzzAsyncMethods() {
+  asyncStart();
+  var futures = <Future>[];
+  typeMapping.forEach((k, v) {
+    late File f;
+    doItSync(() => f = new File(v as String));
+    if (f == null) return;
+    futures.add(doItAsync(f.exists));
+    futures.add(doItAsync(f.delete));
+    futures.add(doItAsync(() => f.parent));
+    futures.add(doItAsync(f.length));
+    futures.add(doItAsync(f.lastModified));
+    futures.add(doItAsync(f.open));
+    futures.add(doItAsync(() => f.path));
+    futures.add(doItAsync(f.readAsBytes));
+    futures.add(doItAsync(f.readAsLines));
+    futures.add(doItAsync(f.readAsString));
+    typeMapping.forEach((k2, v2) {
+      futures.add(doItAsync(() => f.open(mode: v2 as FileMode)));
+      futures.add(doItAsync(() => f.readAsString(encoding: v2 as Encoding)));
+      futures.add(doItAsync(() => f.readAsLines(encoding: v2 as Encoding)));
+    });
+  });
+  Future.wait(futures).then((_) => asyncEnd());
+}
+
+fuzzSyncRandomAccessMethods() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
+  var file = new File('${temp.path}/x');
+  file.createSync();
+  var modes = [FileMode.read, FileMode.write, FileMode.append];
+  for (var m in modes) {
+    var opened = file.openSync(mode: m);
+    typeMapping.forEach((k, v) {
+      doItSync(() => opened.setPositionSync(v as int));
+      doItSync(() => opened.truncateSync(v as int));
+      doItSync(() => opened.writeByteSync(v as int));
+    });
+    for (var p in typePermutations(2)) {
+      doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
+    }
+    for (var p in typePermutations(3)) {
+      doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
+      doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
+    }
+    opened.closeSync();
+  }
+  temp.deleteSync(recursive: true);
+}
+
+fuzzAsyncRandomAccessMethods() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
+  var file = new File('${temp.path}/x');
+  file.createSync();
+  var modes = [FileMode.read, FileMode.write, FileMode.append];
+  var futures = <Future>[];
+  var openedFiles = [];
+  for (var m in modes) {
+    var opened = file.openSync(mode: m);
+    openedFiles.add(opened);
+    typeMapping.forEach((k, v) {
+      futures.add(doItAsync(() => opened.setPosition(v as int)));
+      futures.add(doItAsync(() => opened.truncate(v as int)));
+      futures.add(doItAsync(() => opened.writeByte(v as int)));
+    });
+    for (var p in typePermutations(2)) {
+      futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
+    }
+    for (var p in typePermutations(3)) {
+      futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
+      futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
+    }
+  }
+  Future.wait(futures).then((ignore) {
+    for (var opened in openedFiles) {
+      opened.closeSync();
+    }
+    temp.deleteSync(recursive: true);
+  });
+}
+
+main() {
+  fuzzSyncMethods();
+  fuzzAsyncMethods();
+  fuzzSyncRandomAccessMethods();
+  fuzzAsyncRandomAccessMethods();
+}
diff --git a/tests/standalone/io/file_input_stream_test.dart b/tests/standalone/io/file_input_stream_test.dart
new file mode 100644
index 0000000..30ddab7
--- /dev/null
+++ b/tests/standalone/io/file_input_stream_test.dart
@@ -0,0 +1,249 @@
+// 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.
+// Testing file input stream, VM-only, standalone test.
+//
+// OtherResources=readuntil_test.dat
+// OtherResources=readline_test1.dat
+// OtherResources=readline_test2.dat
+
+import "dart:convert";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+String getFilename(String path) {
+  return Platform.script.resolve(path).toFilePath();
+}
+
+void testStringLineSplitter() {
+  String fileName = getFilename("readuntil_test.dat");
+  // File contains "Hello Dart\nwassup!\n"
+  File file = new File(fileName);
+  int linesRead = 0;
+  var lineStream = file
+      .openRead()
+      .cast<List<int>>()
+      .transform(utf8.decoder)
+      .transform(new LineSplitter());
+  lineStream.listen((line) {
+    linesRead++;
+    if (linesRead == 1) {
+      Expect.equals("Hello Dart", line);
+    } else if (linesRead == 2) {
+      Expect.equals("wassup!", line);
+    } else {
+      Expect.fail("More or less than 2 lines read ($linesRead lines read).");
+    }
+  });
+}
+
+void testOpenStreamAsync() {
+  asyncStart();
+  String fileName = getFilename("readuntil_test.dat");
+  // File contains "Hello Dart\nwassup!\n"
+  var expected = "Hello Dart\nwassup!\n".codeUnits;
+  var byteCount = 0;
+  (new File(fileName)).openRead().listen((d) => byteCount += d.length,
+      onDone: () {
+    Expect.equals(expected.length, byteCount);
+    asyncEnd();
+  });
+}
+
+// Create a file that is big enough that a file stream will
+// read it in multiple chunks.
+int writeLongFileSync(File file) {
+  file.createSync();
+  StringBuffer buffer = new StringBuffer();
+  for (var i = 0; i < 50000; i++) {
+    buffer.write("Hello, world");
+  }
+  file.writeAsStringSync(buffer.toString());
+  var length = file.lengthSync();
+  Expect.equals(buffer.length, length);
+  return length;
+}
+
+void testInputStreamTruncate() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
+  var file = new File('${temp.path}/input_stream_truncate.txt');
+  var originalLength = writeLongFileSync(file);
+  // Start streaming the file. Pause after first chunk. Truncate
+  // underlying file and check that the streaming stops with or
+  // without getting all data.
+  var streamedBytes = 0;
+  var subscription;
+  subscription = file.openRead().listen((d) {
+    if (streamedBytes == 0) {
+      subscription.pause();
+      // Truncate the file by opening it for writing.
+      file.open(mode: FileMode.write).then((opened) {
+        opened.close().then((_) {
+          Expect.equals(0, file.lengthSync());
+          subscription.resume();
+        });
+      });
+    }
+    streamedBytes += d.length;
+  }, onDone: () {
+    Expect.isTrue(streamedBytes > 0 && streamedBytes <= originalLength);
+    temp.delete(recursive: true).then((_) => asyncEnd());
+  }, onError: (e) {
+    Expect.fail("Unexpected error");
+  });
+}
+
+void testInputStreamDelete() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
+  var file = new File('${temp.path}/input_stream_delete.txt');
+  var originalLength = writeLongFileSync(file);
+  // Start streaming the file. Pause after first chunk. Truncate
+  // underlying file and check that the streaming stops with or
+  // without getting all data.
+  var streamedBytes = 0;
+  var subscription;
+  subscription = file.openRead().listen((d) {
+    if (streamedBytes == 0) {
+      subscription.pause();
+      // Delete the underlying file by opening it for writing.
+      file.delete().then((deleted) {
+        Expect.isFalse(deleted.existsSync());
+        subscription.resume();
+      }).catchError((e) {
+        // On Windows, you cannot delete a file that is open
+        // somewhere else. The stream has this file open
+        // and therefore we get an error on deletion on Windows.
+        Expect.equals('windows', Platform.operatingSystem);
+        subscription.resume();
+      });
+    }
+    streamedBytes += d.length;
+  }, onDone: () {
+    Expect.equals(originalLength, streamedBytes);
+    temp.delete(recursive: true).then((_) => asyncEnd());
+  }, onError: (e) {
+    Expect.fail("Unexpected error");
+  });
+}
+
+void testInputStreamAppend() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
+  var file = new File('${temp.path}/input_stream_append.txt');
+  var originalLength = writeLongFileSync(file);
+  // Start streaming the file. Pause after first chunk. Append to
+  // underlying file and check that the stream gets all the data.
+  var streamedBytes = 0;
+  var subscription;
+  subscription = file.openRead().listen((d) {
+    if (streamedBytes == 0) {
+      subscription.pause();
+      // Double the length of the underlying file.
+      file.readAsBytes().then((bytes) {
+        file.writeAsBytes(bytes, mode: FileMode.append).then((_) {
+          Expect.equals(2 * originalLength, file.lengthSync());
+          subscription.resume();
+        });
+      });
+    }
+    streamedBytes += d.length;
+  }, onDone: () {
+    Expect.equals(2 * originalLength, streamedBytes);
+    temp.delete(recursive: true).then((_) => asyncEnd());
+  }, onError: (e) {
+    Expect.fail("Unexpected error");
+  });
+}
+
+void testInputStreamOffset() {
+  void test(int? start, int? end, int expectedBytes) {
+    asyncStart();
+    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
+    var file = new File('${temp.path}/input_stream_offset.txt');
+    var originalLength = writeLongFileSync(file);
+    var streamedBytes = 0;
+    if (expectedBytes < 0) expectedBytes = originalLength + expectedBytes;
+    file.openRead(start, end).listen((d) {
+      streamedBytes += d.length;
+    }, onDone: () {
+      Expect.equals(expectedBytes, streamedBytes);
+      temp.delete(recursive: true).then((_) => asyncEnd());
+    }, onError: (e) {
+      Expect.fail("Unexpected error");
+    });
+  }
+
+  test(10, 20, 10);
+  test(10, 11, 1);
+  test(10, 10, 0);
+  test(100000000, null, 0);
+  test(null, 0, 0);
+  test(null, 1, 1);
+  test(1, null, -1);
+  test(20, null, -20);
+}
+
+void testInputStreamBadOffset() {
+  void test(int? start, int? end) {
+    asyncStart();
+    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
+    var file = new File('${temp.path}/input_stream_bad_offset.txt');
+    var originalLength = writeLongFileSync(file);
+    var streamedBytes = 0;
+    bool error = false;
+    file.openRead(start, end).listen((d) {
+      streamedBytes += d.length;
+    }, onDone: () {
+      Expect.isTrue(error);
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    }, onError: (e) {
+      error = true;
+    });
+  }
+
+  test(-1, null);
+  test(100, 99);
+  test(null, -1);
+}
+
+void testStringLineSplitterEnding(String name, int length) {
+  String fileName = getFilename(name);
+  // File contains 10 lines.
+  File file = new File(fileName);
+  Expect.equals(length, file.lengthSync());
+  var lineStream = file
+      .openRead()
+      .cast<List<int>>()
+      .transform(utf8.decoder)
+      .transform(new LineSplitter());
+  int lineCount = 0;
+  lineStream.listen((line) {
+    lineCount++;
+    Expect.isTrue(lineCount <= 10);
+    if (line[0] != "#") {
+      Expect.equals("Line $lineCount", line);
+    }
+  }, onDone: () {
+    Expect.equals(10, lineCount);
+  });
+}
+
+main() {
+  testStringLineSplitter();
+  testOpenStreamAsync();
+  testInputStreamTruncate();
+  testInputStreamDelete();
+  testInputStreamAppend();
+  testInputStreamOffset();
+  testInputStreamBadOffset();
+  // Check the length of these files as both are text files where one
+  // is without a terminating line separator which can easily be added
+  // back if accidentally opened in a text editor.
+  testStringLineSplitterEnding("readline_test1.dat", 111);
+  testStringLineSplitterEnding("readline_test2.dat", 114);
+}
diff --git a/tests/standalone/io/file_lock_script.dart b/tests/standalone/io/file_lock_script.dart
new file mode 100644
index 0000000..052ae50
--- /dev/null
+++ b/tests/standalone/io/file_lock_script.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Script used by the file_lock_test.dart test.
+
+import "dart:io";
+
+main(List<String> args) {
+  File file = new File(args[0]);
+  int start = 0;
+  int end = -1;
+  var mode = FileLock.exclusive;
+  if (args[1] == 'SHARED') {
+    mode = FileLock.shared;
+  }
+  if (args[2] != 'null') {
+    start = int.parse(args[2]);
+  }
+  if (args[3] != 'null') {
+    end = int.parse(args[3]);
+  }
+  var raf = file.openSync(mode: FileMode.write);
+  try {
+    raf.lockSync(mode, start, end);
+    print('LOCK SUCCEEDED');
+  } catch (e) {
+    print('LOCK FAILED');
+  } finally {
+    raf.closeSync();
+  }
+}
diff --git a/tests/standalone/io/file_lock_test.dart b/tests/standalone/io/file_lock_test.dart
new file mode 100644
index 0000000..88cab1d
--- /dev/null
+++ b/tests/standalone/io/file_lock_test.dart
@@ -0,0 +1,317 @@
+// 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.
+
+// OtherResources=file_lock_script.dart
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+// Check whether the file is locked or not.
+check(String path, int start, int end, FileLock mode, {required bool locked}) {
+  // Client process returns either 'LOCK FAILED' or 'LOCK SUCCEEDED'.
+  var expected = locked ? 'LOCK FAILED' : 'LOCK SUCCEEDED';
+  var arguments = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..add(Platform.script.resolve('file_lock_script.dart').toFilePath())
+    ..add(path)
+    ..add(mode == FileLock.exclusive ? 'EXCLUSIVE' : 'SHARED')
+    ..add('$start')
+    ..add('$end');
+  var stacktrace = StackTrace.current;
+  return Process.run(Platform.executable, arguments)
+      .then((ProcessResult result) {
+    if (result.exitCode != 0 || !result.stdout.contains(expected)) {
+      print("Client failed, exit code ${result.exitCode}");
+      print("  stdout:");
+      print(result.stdout);
+      print("  stderr:");
+      print(result.stderr);
+      print("  arguments:");
+      print(arguments);
+      print("  call stack:");
+      print(stacktrace);
+      Expect.fail('Client subprocess exit code: ${result.exitCode}');
+    }
+  });
+}
+
+checkLocked(String path,
+        [int start = 0, int end = -1, FileLock mode = FileLock.exclusive]) =>
+    check(path, start, end, mode, locked: true);
+
+checkNotLocked(String path,
+        [int start = 0, int end = -1, FileLock mode = FileLock.exclusive]) =>
+    check(path, start, end, mode, locked: false);
+
+void testLockWholeFile() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.write);
+  raf.lockSync();
+  asyncStart();
+  checkLocked(file.path).then((_) {
+    return checkLocked(file.path, 0, 2).then((_) {
+      raf.unlockSync();
+      return checkNotLocked(file.path).then((_) {});
+    });
+  }).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockWholeFileAsync() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.write);
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lock(),
+    () => checkLocked(file.path, 0, 2),
+    () => checkLocked(file.path),
+    () => raf.unlock(),
+    () => checkNotLocked(file.path),
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockRange() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf1 = file.openSync(mode: FileMode.write);
+  var raf2 = file.openSync(mode: FileMode.write);
+  asyncStart();
+  var tests = [
+    () => raf1.lockSync(FileLock.exclusive, 2, 3),
+    () => raf2.lockSync(FileLock.exclusive, 5, 7),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkNotLocked(file.path, 4, 5),
+    () => checkLocked(file.path, 4, 6),
+    () => checkLocked(file.path, 6),
+    () => checkNotLocked(file.path, 7),
+    () => raf1.unlockSync(2, 3),
+    () => checkNotLocked(file.path, 0, 5),
+    () => checkLocked(file.path, 4, 6),
+    () => checkLocked(file.path, 6),
+    () => checkNotLocked(file.path, 7),
+  ];
+  // On Windows regions unlocked must match regions locked.
+  if (!Platform.isWindows) {
+    tests.addAll([
+      () => raf1.unlockSync(5, 6),
+      () => checkNotLocked(file.path, 0, 6),
+      () => checkLocked(file.path, 6),
+      () => checkNotLocked(file.path, 7),
+      () => raf2.unlockSync(6, 7),
+      () => checkNotLocked(file.path)
+    ]);
+  } else {
+    tests
+        .addAll([() => raf2.unlockSync(5, 7), () => checkNotLocked(file.path)]);
+  }
+  Future.forEach<Function>(tests, (f) => f()).whenComplete(() {
+    raf1.closeSync();
+    raf2.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockRangeAsync() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf1 = file.openSync(mode: FileMode.write);
+  var raf2 = file.openSync(mode: FileMode.write);
+  asyncStart();
+  var tests = [
+    () => raf1.lock(FileLock.exclusive, 2, 3),
+    () => raf2.lock(FileLock.exclusive, 5, 7),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkNotLocked(file.path, 4, 5),
+    () => checkLocked(file.path, 4, 6),
+    () => checkLocked(file.path, 6),
+    () => checkNotLocked(file.path, 7),
+    () => raf1.unlock(2, 3),
+    () => checkNotLocked(file.path, 0, 5),
+    () => checkLocked(file.path, 4, 6),
+    () => checkLocked(file.path, 6),
+    () => checkNotLocked(file.path, 7),
+  ];
+  // On Windows regions unlocked must match regions locked.
+  if (!Platform.isWindows) {
+    tests.addAll([
+      () => raf1.unlock(5, 6),
+      () => checkNotLocked(file.path, 0, 6),
+      () => checkLocked(file.path, 6),
+      () => checkNotLocked(file.path, 7),
+      () => raf2.unlock(6, 7),
+      () => checkNotLocked(file.path)
+    ]);
+  } else {
+    tests.addAll([() => raf2.unlock(5, 7), () => checkNotLocked(file.path)]);
+  }
+  Future.forEach<Function>(tests, (f) => f()).whenComplete(() {
+    raf1.closeSync();
+    raf2.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockEnd() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.append);
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lockSync(FileLock.exclusive, 2),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkLocked(file.path, 9),
+    () => raf.writeFromSync(new List.filled(10, 0)),
+    () => checkLocked(file.path, 10),
+    () => checkLocked(file.path, 19),
+    () => raf.unlockSync(2),
+    () => checkNotLocked(file.path)
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockEndAsync() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.append);
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lock(FileLock.exclusive, 2),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkLocked(file.path, 9),
+    () => raf.writeFromSync(new List.filled(10, 0)),
+    () => checkLocked(file.path, 10),
+    () => checkLocked(file.path, 19),
+    () => raf.unlock(2),
+    () => checkNotLocked(file.path)
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockShared() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync();
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lock(FileLock.shared),
+    () => checkLocked(file.path),
+    () => checkLocked(file.path, 0, 2),
+    () => checkNotLocked(file.path, 0, 2, FileLock.shared)
+  ], (f) => f()).then((_) {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockSharedAsync() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync();
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lock(FileLock.shared),
+    () => checkLocked(file.path),
+    () => checkLocked(file.path, 0, 2),
+    () => checkNotLocked(file.path, 0, 2, FileLock.shared)
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockAfterLength() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.append);
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lockSync(FileLock.exclusive, 2, 15),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkLocked(file.path, 9),
+    () => checkLocked(file.path, 14),
+    () => raf.writeFromSync(new List.filled(10, 0)),
+    () => checkLocked(file.path, 10),
+    () => checkNotLocked(file.path, 15),
+    () => raf.unlockSync(2, 15),
+    () => checkNotLocked(file.path)
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testLockAfterLengthAsync() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
+  File file = new File(join(directory.path, "file"));
+  file.writeAsBytesSync(new List.filled(10, 0));
+  var raf = file.openSync(mode: FileMode.append);
+  asyncStart();
+  Future.forEach<Function>([
+    () => raf.lock(FileLock.exclusive, 2, 15),
+    () => checkNotLocked(file.path, 0, 2),
+    () => checkLocked(file.path, 0, 3),
+    () => checkLocked(file.path, 9),
+    () => checkLocked(file.path, 14),
+    () => raf.writeFromSync(new List.filled(10, 0)),
+    () => checkLocked(file.path, 10),
+    () => checkNotLocked(file.path, 15),
+    () => raf.unlock(2, 15),
+    () => checkNotLocked(file.path)
+  ], (f) => f()).whenComplete(() {
+    raf.closeSync();
+    directory.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void main() {
+  testLockWholeFile();
+  testLockWholeFileAsync();
+  testLockRange();
+  testLockRangeAsync();
+  testLockEnd();
+  testLockEndAsync();
+  testLockShared();
+  testLockSharedAsync();
+  testLockAfterLength();
+  testLockAfterLengthAsync();
+}
diff --git a/tests/standalone/io/file_non_ascii_sync_test.dart b/tests/standalone/io/file_non_ascii_sync_test.dart
new file mode 100644
index 0000000..f664797
--- /dev/null
+++ b/tests/standalone/io/file_non_ascii_sync_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";
+import 'dart:io';
+
+main() {
+  Directory tempDir =
+      Directory.systemTemp.createTempSync('dart_file_non_ascii_sync');
+  Directory nonAsciiDir = new Directory('${tempDir.path}/æøå');
+  nonAsciiDir.createSync();
+  Expect.isTrue(nonAsciiDir.existsSync());
+  File nonAsciiFile = new File('${nonAsciiDir.path}/æøå.txt');
+  nonAsciiFile.writeAsStringSync('æøå');
+  Expect.isTrue(nonAsciiFile.existsSync());
+  // On MacOS you get the decomposed utf8 form of file and directory
+  // names from the system. Therefore, we have to check for both here.
+  var precomposed = 'æøå';
+  var decomposed = new String.fromCharCodes([47, 230, 248, 97, 778]);
+  // The contents of the file is precomposed utf8.
+  Expect.equals(precomposed, nonAsciiFile.readAsStringSync());
+  nonAsciiFile.createSync();
+  var path = nonAsciiFile.parent.path;
+  Expect.isTrue(path.endsWith(precomposed) || path.endsWith(decomposed));
+  Expect.equals(6, nonAsciiFile.lengthSync());
+  nonAsciiFile.lastModifiedSync();
+  path = nonAsciiFile.resolveSymbolicLinksSync();
+  Expect.isTrue(path.endsWith('${precomposed}.txt') ||
+      path.endsWith('${decomposed}.txt'));
+  tempDir.deleteSync(recursive: true);
+}
diff --git a/tests/standalone/io/file_non_ascii_test.dart b/tests/standalone/io/file_non_ascii_test.dart
new file mode 100644
index 0000000..cc465d8
--- /dev/null
+++ b/tests/standalone/io/file_non_ascii_test.dart
@@ -0,0 +1,55 @@
+// 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:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+
+  // On MacOS you get the decomposed utf8 form of file and directory
+  // names from the system. Therefore, we have to check for both here.
+  var precomposed = 'æøå';
+  var decomposed = new String.fromCharCodes([47, 230, 248, 97, 778]);
+
+  Directory.systemTemp.createTemp('dart_file_non_ascii').then((tempDir) {
+    Directory nonAsciiDir = new Directory('${tempDir.path}/æøå');
+    nonAsciiDir.create().then((nonAsciiDir) {
+      nonAsciiDir.exists().then((result) {
+        Expect.isTrue(result);
+        File nonAsciiFile = new File('${nonAsciiDir.path}/æøå.txt');
+        nonAsciiFile.writeAsString('æøå').then((_) {
+          nonAsciiFile.exists().then((result) {
+            Expect.isTrue(result);
+            nonAsciiFile.readAsString().then((contents) {
+              // The contents of the file is precomposed utf8.
+              Expect.equals(precomposed, contents);
+              nonAsciiFile.create().then((_) {
+                var d = nonAsciiFile.parent;
+                Expect.isTrue(d.path.endsWith(precomposed) ||
+                    d.path.endsWith(decomposed));
+                nonAsciiFile.length().then((length) {
+                  Expect.equals(6, length);
+                  nonAsciiFile.lastModified().then((_) {
+                    nonAsciiFile.resolveSymbolicLinks().then((path) {
+                      Expect.isTrue(path.endsWith('${precomposed}.txt') ||
+                          path.endsWith('${decomposed}.txt'));
+                      tempDir.delete(recursive: true).then((_) {
+                        asyncEnd();
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }).catchError((e) {
+    Expect.fail("File not found");
+  });
+}
diff --git a/tests/standalone/io/file_output_stream_test.dart b/tests/standalone/io/file_output_stream_test.dart
new file mode 100644
index 0000000..dfd9aa0
--- /dev/null
+++ b/tests/standalone/io/file_output_stream_test.dart
@@ -0,0 +1,33 @@
+// 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.
+// Testing file input stream, VM-only, standalone test.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testOpenOutputStreamSync() {
+  Directory tempDirectory =
+      Directory.systemTemp.createTempSync('dart_file_output_stream');
+
+  asyncStart();
+  String fileName = "${tempDirectory.path}/test";
+  File file = new File(fileName);
+  file.createSync();
+  IOSink x = file.openWrite();
+  var data = [65, 66, 67];
+  x.add(data);
+  x.close();
+  x.done.then((_) {
+    Expect.listEquals(file.readAsBytesSync(), data);
+    file.deleteSync();
+    tempDirectory.deleteSync();
+    asyncEnd();
+  });
+}
+
+main() {
+  testOpenOutputStreamSync();
+}
diff --git a/tests/standalone/io/file_read_encoded_test.dart b/tests/standalone/io/file_read_encoded_test.dart
new file mode 100644
index 0000000..984b366
--- /dev/null
+++ b/tests/standalone/io/file_read_encoded_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.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import 'dart:io';
+
+void testReadAsString() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_read_encoded');
+
+  var file = new File('${tmp.path}/file');
+  file.createSync();
+
+  file.writeAsBytesSync([0xb0]);
+
+  Expect.throws(file.readAsStringSync, (e) => e is FileSystemException);
+
+  asyncStart();
+  file.readAsString().then((_) {
+    Expect.fail("expected exception");
+  }).catchError((e) {
+    tmp.deleteSync(recursive: true);
+    asyncEnd();
+  }, test: (e) => e is FileSystemException);
+}
+
+void testReadAsLines() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_read_encoded');
+
+  var file = new File('${tmp.path}/file');
+  file.createSync();
+
+  file.writeAsBytesSync([0xb0]);
+
+  Expect.throws(file.readAsLinesSync, (e) => e is FileSystemException);
+
+  asyncStart();
+  file.readAsLines().then((_) {
+    Expect.fail("expected exception");
+  }).catchError((e) {
+    tmp.deleteSync(recursive: true);
+    asyncEnd();
+  }, test: (e) => e is FileSystemException);
+}
+
+void main() {
+  testReadAsString();
+  testReadAsLines();
+}
diff --git a/tests/standalone/io/file_read_special_device_test.dart b/tests/standalone/io/file_read_special_device_test.dart
new file mode 100644
index 0000000..fcfd9cb
--- /dev/null
+++ b/tests/standalone/io/file_read_special_device_test.dart
@@ -0,0 +1,34 @@
+// 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.
+
+// OtherResources=file_read_stdio_script.dart
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart';
+import 'dart:io';
+
+void openAndWriteScript(String script) {
+  script = Platform.script.resolve(script).toFilePath();
+  var executable = Platform.executable;
+  var file = script; // Use script as file.
+  Process.start("bash", [
+    "-c",
+    "$executable ${Platform.executableArguments.join(' ')} $script < $file"
+  ]).then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(0, exitCode);
+    });
+  });
+}
+
+void testReadStdio() {
+  openAndWriteScript("file_read_stdio_script.dart");
+}
+
+void main() {
+  // Special unix devices do not exist on Windows.
+  if (Platform.operatingSystem != 'windows') {
+    testReadStdio();
+  }
+}
diff --git a/tests/standalone/io/file_read_stdio_script.dart b/tests/standalone/io/file_read_stdio_script.dart
new file mode 100644
index 0000000..948a0ec
--- /dev/null
+++ b/tests/standalone/io/file_read_stdio_script.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.
+
+import 'dart:io';
+
+void main() {
+  var expected = new File(Platform.script.toFilePath()).readAsStringSync();
+  var stdin = new File('/dev/fd/0').readAsStringSync();
+  if (expected != stdin) {
+    throw "stdin not equal expected file";
+  }
+}
diff --git a/tests/standalone/io/file_stat_test.dart b/tests/standalone/io/file_stat_test.dart
new file mode 100644
index 0000000..86054da
--- /dev/null
+++ b/tests/standalone/io/file_stat_test.dart
@@ -0,0 +1,119 @@
+// 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 program for testing dart:io FileSystemEntity.Stat().
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+void testStat() {
+  Directory directory = Directory.systemTemp.createTempSync('dart_file_stat');
+  File file = new File(join(directory.path, "file"));
+  FileStat fileStat = FileStat.statSync(file.path);
+  FileStat fileStatDirect = file.statSync();
+  Expect.equals(FileSystemEntityType.notFound, fileStat.type);
+  Expect.equals(FileSystemEntityType.notFound, fileStatDirect.type);
+  file.writeAsStringSync("Dart IO library test of FileStat");
+  new Timer(const Duration(seconds: 2), () {
+    file.readAsStringSync();
+    directory.listSync();
+    FileStat fileStat = FileStat.statSync(file.path);
+    FileStat fileStatDirect = file.statSync();
+    Expect.equals(FileSystemEntityType.file, fileStat.type);
+    Expect.equals(32, fileStat.size);
+    Expect.equals(FileSystemEntityType.file, fileStatDirect.type);
+    Expect.equals(32, fileStatDirect.size);
+    if (Platform.operatingSystem != 'windows') {
+      Expect.isTrue(fileStat.modified.compareTo(fileStat.accessed) < 0);
+      Expect.isTrue(fileStat.changed.compareTo(fileStat.accessed) < 0);
+    }
+    Expect.equals(6 << 6, fileStat.mode & (6 << 6)); // Mode includes +urw.
+    FileStat directoryStat = FileStat.statSync(directory.path);
+    FileStat directoryStatDirect = directory.statSync();
+    Expect.equals(FileSystemEntityType.directory, directoryStat.type);
+    Expect.equals(FileSystemEntityType.directory, directoryStatDirect.type);
+    if (Platform.operatingSystem != 'windows') {
+      Expect.isTrue(
+          directoryStat.modified.compareTo(directoryStat.accessed) < 0);
+      Expect.isTrue(
+          directoryStat.changed.compareTo(directoryStat.accessed) < 0);
+    }
+    Expect.equals(7 << 6, directoryStat.mode & (7 << 6)); // Includes +urwx.
+    directory.deleteSync(recursive: true);
+  });
+}
+
+Future testStatAsync() {
+  return Directory.systemTemp.createTemp('dart_file_stat').then((directory) {
+    File file = new File(join(directory.path, "file"));
+    return FileStat.stat(file.path)
+        .then((fileStat) =>
+            Expect.equals(FileSystemEntityType.notFound, fileStat.type))
+        .then((_) => file.stat())
+        .then((fileStat) =>
+            Expect.equals(FileSystemEntityType.notFound, fileStat.type))
+        .then((_) => file.writeAsString("Dart IO library test of FileStat"))
+        .then((_) => new Future.delayed(const Duration(seconds: 2)))
+        .then((_) => file.readAsString())
+        .then((_) => directory.list().last)
+        .then((_) => FileStat.stat(file.path))
+        .then((FileStat fileStat) {
+      Expect.equals(FileSystemEntityType.file, fileStat.type);
+      Expect.equals(32, fileStat.size);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(fileStat.modified.compareTo(fileStat.accessed) < 0);
+        Expect.isTrue(fileStat.changed.compareTo(fileStat.accessed) < 0);
+      }
+      Expect.equals(6 << 6, fileStat.mode & (6 << 6)); // Mode includes +urw.
+      return file.stat();
+    }).then((FileStat fileStat) {
+      Expect.equals(FileSystemEntityType.file, fileStat.type);
+      Expect.equals(32, fileStat.size);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(fileStat.modified.compareTo(fileStat.accessed) < 0);
+        Expect.isTrue(fileStat.changed.compareTo(fileStat.accessed) < 0);
+      }
+      Expect.equals(6 << 6, fileStat.mode & (6 << 6)); // Mode includes +urw.
+      return FileStat.stat(directory.path);
+    }).then((FileStat directoryStat) {
+      Expect.equals(FileSystemEntityType.directory, directoryStat.type);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(
+            directoryStat.modified.compareTo(directoryStat.accessed) < 0);
+        Expect.isTrue(
+            directoryStat.changed.compareTo(directoryStat.accessed) < 0);
+      }
+      Expect.equals(7 << 6, directoryStat.mode & (7 << 6)); // Includes +urwx.
+      return directory.stat();
+    }).then((FileStat directoryStat) {
+      Expect.equals(FileSystemEntityType.directory, directoryStat.type);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(
+            directoryStat.modified.compareTo(directoryStat.accessed) < 0);
+        Expect.isTrue(
+            directoryStat.changed.compareTo(directoryStat.accessed) < 0);
+      }
+      Expect.equals(7 << 6, directoryStat.mode & (7 << 6)); // Includes +urwx.
+      return new Link(directory.path).stat();
+    }).then((FileStat linkStat) {
+      Expect.equals(FileSystemEntityType.directory, linkStat.type);
+      if (Platform.operatingSystem != 'windows') {
+        Expect.isTrue(linkStat.modified.compareTo(linkStat.accessed) < 0);
+        Expect.isTrue(linkStat.changed.compareTo(linkStat.accessed) < 0);
+      }
+      Expect.equals(7 << 6, linkStat.mode & (7 << 6)); // Includes +urwx.
+      return directory.delete(recursive: true);
+    });
+  });
+}
+
+void main() {
+  asyncStart();
+  testStat();
+  testStatAsync().then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/file_stream_test.dart b/tests/standalone/io/file_stream_test.dart
new file mode 100644
index 0000000..2d3577e
--- /dev/null
+++ b/tests/standalone/io/file_stream_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testPauseResumeCancelStream() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_file_stream').then((d) {
+    var file = new File("${d.path}/file");
+    new File(Platform.executable)
+        .openRead()
+        .cast<List<int>>()
+        .pipe(file.openWrite())
+        .then((_) {
+      var subscription;
+      subscription = file.openRead().listen((data) {
+        subscription.pause();
+        subscription.resume();
+        void close() {
+          d.deleteSync(recursive: true);
+          asyncEnd();
+        }
+
+        var future = subscription.cancel();
+        if (future != null) {
+          future.whenComplete(close);
+        } else {
+          close();
+        }
+      }, onDone: () {
+        Expect.fail('the stream was canceled, onDone should not happen');
+      });
+    });
+  });
+}
+
+void testStreamIsEmpty() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_file_stream').then((d) {
+    var file = new File("${d.path}/file");
+    new File(Platform.executable)
+        .openRead()
+        .cast<List<int>>()
+        .pipe(file.openWrite())
+        .then((_) {
+      // isEmpty will cancel the stream after first data event.
+      file.openRead().isEmpty.then((empty) {
+        Expect.isFalse(empty);
+        d.deleteSync(recursive: true);
+        asyncEnd();
+      });
+    });
+  });
+}
+
+void main() {
+  testPauseResumeCancelStream();
+  testStreamIsEmpty();
+}
diff --git a/tests/standalone/io/file_system_async_links_test.dart b/tests/standalone/io/file_system_async_links_test.dart
new file mode 100644
index 0000000..efd820a
--- /dev/null
+++ b/tests/standalone/io/file_system_async_links_test.dart
@@ -0,0 +1,234 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class FutureExpect {
+  static Future isTrue(Future<bool> result) =>
+      result.then((value) => Expect.isTrue(value));
+  static Future isFalse(Future<bool> result) =>
+      result.then((value) => Expect.isFalse(value));
+  static Future equals(expected, Future result) =>
+      result.then((value) => Expect.equals(expected, value));
+  static Future listEquals(expected, Future result) =>
+      result.then((value) => Expect.listEquals(expected, value));
+  static Future throws(Future result) => result.then((value) {
+        throw new ExpectException(
+            "FutureExpect.throws received $value instead of an exception");
+      }, onError: (_) => null);
+}
+
+Future testFileExistsCreate() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var y = '${temp.path}${Platform.pathSeparator}y';
+    return new Link(y)
+        .create(x)
+        .then((link) => Expect.equals(y, link.path))
+        .then((_) => FutureExpect.isFalse(new File(y).exists()))
+        .then((_) => FutureExpect.isFalse(new File(x).exists()))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.notFound,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+        .then((_) => new File(y).create())
+        .then((yFile) => Expect.equals(y, yFile.path))
+        .then((_) => FutureExpect.isTrue(new File(y).exists()))
+        .then((_) => FutureExpect.isTrue(new File(x).exists()))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isFile(y)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isFile(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.file, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.file, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.file,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+        .then((_) => new File(x).delete())
+        .then((xDeletedFile) => Expect.equals(x, xDeletedFile.path))
+        .then((_) => new Directory(x).create())
+        .then((xCreatedDirectory) => Expect.equals(x, xCreatedDirectory.path))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isDirectory(y)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isDirectory(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+        .then((_) => new Link(y).delete())
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(y)))
+        .then(
+            (_) => FutureExpect.equals(FileSystemEntityType.directory, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.throws(new Link(y).target()))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+Future testFileDelete() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var y = '${temp.path}${Platform.pathSeparator}y';
+    return new File(x)
+        .create()
+        .then((_) => new Link(y).create(x))
+        .then((_) => FutureExpect.isTrue(new File(x).exists()))
+        .then((_) => FutureExpect.isTrue(new File(y).exists()))
+        .then((_) => new File(y).delete())
+        .then((_) => FutureExpect.isTrue(new File(x).exists()))
+        .then((_) => FutureExpect.isFalse(new File(y).exists()))
+        .then((_) => new Link(y).create(x))
+        .then((_) => FutureExpect.isTrue(new File(x).exists()))
+        .then((_) => FutureExpect.isTrue(new File(y).exists()))
+        .then((_) => new File(y).delete())
+        .then((_) => FutureExpect.isTrue(new File(x).exists()))
+        .then((_) => FutureExpect.isFalse(new File(y).exists()))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+Future testFileWriteRead() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var y = '${temp.path}${Platform.pathSeparator}y';
+    var data = "asdf".codeUnits;
+    return new File(x)
+        .create()
+        .then((_) => new Link(y).create(x))
+        .then((_) =>
+            (new File(y).openWrite(mode: FileMode.write)..add(data)).close())
+        .then((_) => FutureExpect.listEquals(data, new File(y).readAsBytes()))
+        .then((_) => FutureExpect.listEquals(data, new File(x).readAsBytes()))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+Future testDirectoryExistsCreate() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var y = '${temp.path}${Platform.pathSeparator}y';
+    return new Link(y)
+        .create(x)
+        .then((_) => FutureExpect.isFalse(new Directory(x).exists()))
+        .then((_) => FutureExpect.isFalse(new Directory(y).exists()))
+        .then((_) => FutureExpect.throws(new Directory(y).create()))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+Future testDirectoryDelete() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    return Directory.systemTemp
+        .createTemp('dart_file_system_async')
+        .then((temp2) {
+      var y = '${temp.path}${Platform.pathSeparator}y';
+      var x = '${temp2.path}${Platform.pathSeparator}x';
+      var link = new Directory(y);
+      return new File(x)
+          .create()
+          .then((_) => new Link(y).create(temp2.path))
+          .then((_) => FutureExpect.isTrue(link.exists()))
+          .then((_) => FutureExpect.isTrue(temp2.exists()))
+          .then((_) => link.delete())
+          .then((_) => FutureExpect.isFalse(link.exists()))
+          .then((_) => FutureExpect.isTrue(temp2.exists()))
+          .then((_) => new Link(y).create(temp2.path))
+          .then((_) => FutureExpect.isTrue(link.exists()))
+          .then((_) => temp.delete(recursive: true))
+          .then((_) => FutureExpect.isFalse(link.exists()))
+          .then((_) => FutureExpect.isFalse(temp.exists()))
+          .then((_) => FutureExpect.isTrue(temp2.exists()))
+          .then((_) => FutureExpect.isTrue(new File(x).exists()))
+          .then((_) => temp2.delete(recursive: true));
+    });
+  });
+}
+
+Future testDirectoryListing() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    return Directory.systemTemp
+        .createTemp('dart_file_system_async_links')
+        .then((temp2) {
+      var sep = Platform.pathSeparator;
+      var y = '${temp.path}${sep}y';
+      var x = '${temp2.path}${sep}x';
+      return new File(x)
+          .create()
+          .then((_) => new Link(y).create(temp2.path))
+          .then((_) =>
+              temp.list(recursive: true).singleWhere((entry) => entry is File))
+          .then((file) => Expect.isTrue(file.path.endsWith('$y${sep}x')))
+          .then((_) => temp
+              .list(recursive: true)
+              .singleWhere((entry) => entry is Directory))
+          .then((dir) => Expect.isTrue(dir.path.endsWith('y')))
+          .then((_) => temp.delete(recursive: true))
+          .then((_) => temp2.delete(recursive: true));
+    });
+  });
+}
+
+Future testDirectoryListingBrokenLink() {
+  return Directory.systemTemp.createTemp('dart_file_system_async').then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var link = '${temp.path}${Platform.pathSeparator}link';
+    var doesNotExist = 'this_thing_does_not_exist';
+    bool sawFile = false;
+    bool sawLink = false;
+    return new File(x)
+        .create()
+        .then((_) => new Link(link).create(doesNotExist))
+        .then((_) => temp.list(recursive: true).forEach((entity) {
+              if (entity is File) {
+                Expect.isFalse(sawFile);
+                sawFile = true;
+                Expect.isTrue(entity.path.endsWith(x));
+              } else {
+                Expect.isTrue(entity is Link);
+                Expect.isFalse(sawLink);
+                sawLink = true;
+                Expect.isTrue(entity.path.endsWith(link));
+              }
+            }))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+main() {
+  // Links on Windows are tested by windows_file_system_[async_]links_test.
+  if (Platform.operatingSystem != 'windows') {
+    asyncStart();
+    testFileExistsCreate()
+        .then((_) => testFileDelete())
+        .then((_) => testFileWriteRead())
+        .then((_) => testDirectoryExistsCreate())
+        .then((_) => testDirectoryDelete())
+        .then((_) => testDirectoryListing())
+        .then((_) => testDirectoryListingBrokenLink())
+        .then((_) => asyncEnd());
+  }
+}
diff --git a/tests/standalone/io/file_system_delete_test.dart b/tests/standalone/io/file_system_delete_test.dart
new file mode 100644
index 0000000..7602c69
--- /dev/null
+++ b/tests/standalone/io/file_system_delete_test.dart
@@ -0,0 +1,371 @@
+// 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 "dart:async";
+import "dart:io";
+
+Future throws(callback()) {
+  return new Future.value().then((_) => callback()).then((_) {
+    throw "Expected error";
+  }, onError: (_) {});
+}
+
+void testDeleteFileSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_delete');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var file = new File("${path}myFile");
+
+  file.createSync();
+
+  Expect.isTrue(file.existsSync());
+  new File(file.path).deleteSync();
+  Expect.isFalse(file.existsSync());
+
+  file.createSync();
+
+  Expect.isTrue(file.existsSync());
+  new Directory(file.path).deleteSync(recursive: true);
+  Expect.isFalse(file.existsSync());
+
+  file.createSync();
+
+  Expect.isTrue(file.existsSync());
+  Expect.throws(() => new Directory(file.path).deleteSync());
+  Expect.isTrue(file.existsSync());
+
+  Expect.isTrue(file.existsSync());
+  Expect.throws(() => new Link(file.path).deleteSync());
+  Expect.isTrue(file.existsSync());
+
+  file.deleteSync();
+  Expect.isFalse(file.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDeleteFile() {
+  Directory.systemTemp.createTemp('dart_file_system_delete').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var file = new File("${path}myFile");
+    return file
+        .create()
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => new File(file.path).delete())
+        .then((_) => file.exists().then(Expect.isFalse))
+        .then((_) => file.create())
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => new Directory(file.path).delete(recursive: true))
+        .then((_) => file.exists().then(Expect.isFalse))
+        .then((_) => file.create())
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new Directory(file.path).delete()))
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new Link(file.path).delete()))
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => file.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDeleteDirectorySync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_delete');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var dir = new Directory("${path}myDirectory");
+
+  dir.createSync();
+
+  Expect.isTrue(dir.existsSync());
+  new Directory(dir.path).deleteSync();
+  Expect.isFalse(dir.existsSync());
+
+  dir.createSync();
+
+  Expect.isTrue(dir.existsSync());
+  new Directory(dir.path).deleteSync(recursive: true);
+  Expect.isFalse(dir.existsSync());
+
+  dir.createSync();
+
+  Expect.isTrue(dir.existsSync());
+  Expect.throws(() => new File(dir.path).deleteSync());
+  Expect.isTrue(dir.existsSync());
+
+  Expect.isTrue(dir.existsSync());
+  Expect.throws(() => new Link(dir.path).deleteSync());
+  Expect.isTrue(dir.existsSync());
+
+  dir.deleteSync();
+  Expect.isFalse(dir.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDeleteDirectory() {
+  Directory.systemTemp.createTemp('dart_file_system_delete').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDirectory");
+    return dir
+        .create()
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => new Directory(dir.path).delete())
+        .then((_) => dir.exists().then(Expect.isFalse))
+        .then((_) => dir.create())
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => new Directory(dir.path).delete(recursive: true))
+        .then((_) => dir.exists().then(Expect.isFalse))
+        .then((_) => dir.create())
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new File(dir.path).delete()))
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new Link(dir.path).delete()))
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => dir.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDeleteFileLinkSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_delete');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var file = new File("${path}myFile");
+  file.createSync();
+
+  var link = new Link("${path}myLink");
+
+  link.createSync(file.path);
+
+  Expect.isTrue(link.existsSync());
+  new File(link.path).deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(file.path);
+
+  Expect.isTrue(link.existsSync());
+  new Link(link.path).deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(file.path);
+
+  Expect.isTrue(link.existsSync());
+  new Directory(link.path).deleteSync(recursive: true);
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(file.path);
+
+  Expect.isTrue(link.existsSync());
+  Expect.throws(() => new Directory(link.path).deleteSync());
+  Expect.isTrue(link.existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  Expect.isTrue(file.existsSync());
+  file.deleteSync();
+  Expect.isFalse(file.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDeleteFileLink() {
+  Directory.systemTemp.createTemp('dart_file_system_delete').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var file = new File("${path}myFile");
+    var link = new Link("${path}myLink");
+    return file
+        .create()
+        .then((_) => link.create(file.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new File(link.path).delete())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(file.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Link(link.path).delete())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(file.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Directory(link.path).delete(recursive: true))
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(file.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new Directory(link.path).delete()))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => link.deleteSync())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => file.exists().then(Expect.isTrue))
+        .then((_) => file.delete())
+        .then((_) => file.exists().then(Expect.isFalse))
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDeleteDirectoryLinkSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_delete');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var directory = new Directory("${path}myDirectory");
+  directory.createSync();
+
+  var link = new Link("${path}myLink");
+
+  link.createSync(directory.path);
+
+  Expect.isTrue(link.existsSync());
+  new Link(link.path).deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(directory.path);
+
+  Expect.isTrue(link.existsSync());
+  new Directory(link.path).deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(directory.path);
+
+  Expect.isTrue(link.existsSync());
+  new Directory(link.path).deleteSync(recursive: true);
+  Expect.isFalse(link.existsSync());
+
+  link.createSync(directory.path);
+
+  Expect.isTrue(link.existsSync());
+  Expect.throws(() => new File(link.path).deleteSync());
+  Expect.isTrue(link.existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  Expect.isTrue(directory.existsSync());
+  directory.deleteSync();
+  Expect.isFalse(directory.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDeleteDirectoryLink() {
+  Directory.systemTemp.createTemp('dart_file_system_delete').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDir");
+    var link = new Link("${path}myLink");
+    return dir
+        .create()
+        .then((_) => link.create(dir.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Directory(link.path).delete())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(dir.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Directory(link.path).delete(recursive: true))
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(dir.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Link(link.path).delete())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => link.create(dir.path))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new File(link.path).delete()))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => link.deleteSync())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => dir.exists().then(Expect.isTrue))
+        .then((_) => dir.delete())
+        .then((_) => dir.exists().then(Expect.isFalse))
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDeleteBrokenLinkSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_delete');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var directory = new Directory("${path}myDirectory");
+  directory.createSync();
+
+  var link = new Link("${path}myLink");
+
+  link.createSync(directory.path);
+  directory.deleteSync();
+
+  Expect.isTrue(link.existsSync());
+  new Link(link.path).deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  directory.createSync();
+  link.createSync(directory.path);
+  directory.deleteSync();
+
+  Expect.isTrue(link.existsSync());
+  new Directory(link.path).deleteSync(recursive: true);
+  Expect.isFalse(link.existsSync());
+
+  directory.createSync();
+  link.createSync(directory.path);
+  directory.deleteSync();
+
+  Expect.isTrue(link.existsSync());
+  Expect.throws(() => new Directory(link.path).deleteSync());
+  Expect.isTrue(link.existsSync());
+
+  Expect.isTrue(link.existsSync());
+  Expect.throws(() => new File(link.path).deleteSync());
+  Expect.isTrue(link.existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDeleteBrokenLink() {
+  Directory.systemTemp.createTemp('dart_file_system_delete').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDir");
+    var link = new Link("${path}myLink");
+    return dir
+        .create()
+        .then((_) => link.create(dir.path))
+        .then((_) => dir.delete())
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Link(link.path).delete())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => dir.create())
+        .then((_) => link.create(dir.path))
+        .then((_) => dir.delete())
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => new Directory(link.path).delete(recursive: true))
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => dir.create())
+        .then((_) => link.create(dir.path))
+        .then((_) => dir.delete())
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new Directory(link.path).delete()))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => throws(() => new File(link.path).delete()))
+        .then((_) => link.exists().then(Expect.isTrue))
+        .then((_) => link.deleteSync())
+        .then((_) => link.exists().then(Expect.isFalse))
+        .then((_) => tmp.delete());
+  });
+}
+
+void main() {
+  testDeleteFileSync();
+  testDeleteFile();
+  testDeleteDirectorySync();
+  testDeleteDirectory();
+  if (Platform.operatingSystem != 'windows') {
+    testDeleteFileLinkSync();
+    testDeleteFileLink();
+  }
+  testDeleteDirectoryLinkSync();
+  testDeleteDirectoryLink();
+  testDeleteBrokenLinkSync();
+  testDeleteBrokenLink();
+}
diff --git a/tests/standalone/io/file_system_exists_test.dart b/tests/standalone/io/file_system_exists_test.dart
new file mode 100644
index 0000000..12a7f19
--- /dev/null
+++ b/tests/standalone/io/file_system_exists_test.dart
@@ -0,0 +1,201 @@
+// 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 "dart:io";
+
+void testFileExistsSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_exists');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var file = new File("${path}myFile");
+  file.createSync();
+
+  Expect.isTrue(new File(file.path).existsSync());
+  Expect.isFalse(new Directory(file.path).existsSync());
+  Expect.isFalse(new Link(file.path).existsSync());
+
+  file.deleteSync();
+  Expect.isFalse(file.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testFileExists() {
+  Directory.systemTemp.createTemp('dart_file_system_exists').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var file = new File("${path}myFile");
+    return file
+        .create()
+        .then((_) => new File(file.path).exists().then(Expect.isTrue))
+        .then((_) => new Directory(file.path).exists().then(Expect.isFalse))
+        .then((_) => new Link(file.path).exists().then(Expect.isFalse))
+        .then((_) => file.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDirectoryExistsSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_exists');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var dir = new Directory("${path}myDirectory");
+  dir.createSync();
+
+  Expect.isFalse(new File(dir.path).existsSync());
+  Expect.isTrue(new Directory(dir.path).existsSync());
+  Expect.isFalse(new Link(dir.path).existsSync());
+
+  dir.deleteSync();
+  Expect.isFalse(dir.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDirectoryExists() {
+  Directory.systemTemp.createTemp('dart_file_system_exists').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDirectory");
+    return dir
+        .create()
+        .then((_) => new File(dir.path).exists().then(Expect.isFalse))
+        .then((_) => new Directory(dir.path).exists().then(Expect.isTrue))
+        .then((_) => new Link(dir.path).exists().then(Expect.isFalse))
+        .then((_) => dir.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testFileLinkExistsSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_exists');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var file = new File("${path}myFile");
+  file.createSync();
+
+  var link = new Link("${path}myLink");
+  link.createSync(file.path);
+
+  Expect.isTrue(new File(link.path).existsSync());
+  Expect.isFalse(new Directory(link.path).existsSync());
+  Expect.isTrue(new Link(link.path).existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  file.deleteSync();
+  Expect.isFalse(file.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testFileLinkExists() {
+  Directory.systemTemp.createTemp('dart_file_system_exists').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var file = new File("${path}myFile");
+    var link = new Link("${path}myLink");
+    return file
+        .create()
+        .then((_) => link.create(file.path))
+        .then((_) => new File(link.path).exists().then(Expect.isTrue))
+        .then((_) => new Directory(link.path).exists().then(Expect.isFalse))
+        .then((_) => new Link(link.path).exists().then(Expect.isTrue))
+        .then((_) => link.delete())
+        .then((_) => file.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testDirectoryLinkExistsSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_exists');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var directory = new Directory("${path}myDirectory");
+  directory.createSync();
+
+  var link = new Link("${path}myLink");
+  link.createSync(directory.path);
+
+  Expect.isFalse(new File(link.path).existsSync());
+  Expect.isTrue(new Directory(link.path).existsSync());
+  Expect.isTrue(new Link(link.path).existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  directory.deleteSync();
+  Expect.isFalse(directory.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testDirectoryLinkExists() {
+  Directory.systemTemp.createTemp('dart_file_system_exists').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDir");
+    var link = new Link("${path}myLink");
+    return dir
+        .create()
+        .then((_) => link.create(dir.path))
+        .then((_) => new File(link.path).exists().then(Expect.isFalse))
+        .then((_) => new Directory(link.path).exists().then(Expect.isTrue))
+        .then((_) => new Link(link.path).exists().then(Expect.isTrue))
+        .then((_) => link.delete())
+        .then((_) => dir.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void testBrokenLinkExistsSync() {
+  var tmp = Directory.systemTemp.createTempSync('dart_file_system_exists');
+  var path = "${tmp.path}${Platform.pathSeparator}";
+
+  var directory = new Directory("${path}myDirectory");
+  directory.createSync();
+
+  var link = new Link("${path}myLink");
+  link.createSync(directory.path);
+  directory.deleteSync();
+
+  Expect.isFalse(new File(link.path).existsSync());
+  Expect.isFalse(new Directory(link.path).existsSync());
+  Expect.isTrue(new Link(link.path).existsSync());
+
+  link.deleteSync();
+  Expect.isFalse(link.existsSync());
+
+  tmp.deleteSync();
+}
+
+void testBrokenLinkExists() {
+  Directory.systemTemp.createTemp('dart_file_system_exists').then((tmp) {
+    var path = "${tmp.path}${Platform.pathSeparator}";
+    var dir = new Directory("${path}myDir");
+    var link = new Link("${path}myLink");
+    return dir
+        .create()
+        .then((_) => link.create(dir.path))
+        .then((_) => dir.delete())
+        .then((_) => new File(link.path).exists().then(Expect.isFalse))
+        .then((_) => new Directory(link.path).exists().then(Expect.isFalse))
+        .then((_) => new Link(link.path).exists().then(Expect.isTrue))
+        .then((_) => link.delete())
+        .then((_) => tmp.delete());
+  });
+}
+
+void main() {
+  testFileExistsSync();
+  testFileExists();
+  testDirectoryExistsSync();
+  testDirectoryExists();
+  if (Platform.operatingSystem != 'windows') {
+    testFileLinkExistsSync();
+    testFileLinkExists();
+  }
+  testDirectoryLinkExistsSync();
+  testDirectoryLinkExists();
+  testBrokenLinkExistsSync();
+  testBrokenLinkExists();
+}
diff --git a/tests/standalone/io/file_system_links_test.dart b/tests/standalone/io/file_system_links_test.dart
new file mode 100644
index 0000000..9af7296
--- /dev/null
+++ b/tests/standalone/io/file_system_links_test.dart
@@ -0,0 +1,242 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+createLink(String dst, String link, void callback()) {
+  new Link(link).create(dst).then((_) => callback());
+}
+
+testFileExistsCreate() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  createLink(x, y, () {
+    Expect.isFalse(new File(y).existsSync());
+    Expect.isFalse(new File(x).existsSync());
+    Expect.isTrue(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.equals(FileSystemEntityType.notFound, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.notFound, FileSystemEntity.typeSync(x));
+    Expect.equals(FileSystemEntityType.link,
+        FileSystemEntity.typeSync(y, followLinks: false));
+    Expect.equals(FileSystemEntityType.notFound,
+        FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
+    new File(y).createSync();
+    Expect.isTrue(new File(y).existsSync());
+    Expect.isTrue(new File(x).existsSync());
+    Expect.isTrue(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.isTrue(FileSystemEntity.isFileSync(y));
+    Expect.isTrue(FileSystemEntity.isFileSync(x));
+    Expect.equals(FileSystemEntityType.file, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.file, FileSystemEntity.typeSync(x));
+    Expect.equals(FileSystemEntityType.link,
+        FileSystemEntity.typeSync(y, followLinks: false));
+    Expect.equals(FileSystemEntityType.file,
+        FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
+    new File(x).deleteSync();
+    new Directory(x).createSync();
+    Expect.isTrue(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(y));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(x));
+    Expect.equals(FileSystemEntityType.directory, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.directory, FileSystemEntity.typeSync(x));
+    Expect.equals(FileSystemEntityType.link,
+        FileSystemEntity.typeSync(y, followLinks: false));
+    Expect.equals(FileSystemEntityType.directory,
+        FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
+    new Link(y).deleteSync();
+    Expect.isFalse(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.equals(FileSystemEntityType.notFound, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.directory, FileSystemEntity.typeSync(x));
+    Expect.throws(() => new Link(y).targetSync());
+
+    temp.deleteSync(recursive: true);
+  });
+}
+
+testFileDelete() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  new File(x).createSync();
+  createLink(x, y, () {
+    Expect.isTrue(new File(x).existsSync());
+    Expect.isTrue(new File(y).existsSync());
+    new File(y).deleteSync();
+    Expect.isTrue(new File(x).existsSync());
+    Expect.isFalse(new File(y).existsSync());
+    createLink(x, y, () {
+      Expect.isTrue(new File(x).existsSync());
+      Expect.isTrue(new File(y).existsSync());
+      new File(y).deleteSync();
+      Expect.isTrue(new File(x).existsSync());
+      Expect.isFalse(new File(y).existsSync());
+      temp.deleteSync(recursive: true);
+    });
+  });
+}
+
+testFileWriteRead() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  new File(x).createSync();
+  createLink(x, y, () {
+    var data = "asdf".codeUnits;
+    var output = new File(y).openWrite(mode: FileMode.write);
+    output.add(data);
+    output.close();
+    output.done.then((_) {
+      var read = new File(y).readAsBytesSync();
+      Expect.listEquals(data, read);
+      var read2 = new File(x).readAsBytesSync();
+      Expect.listEquals(data, read2);
+      temp.deleteSync(recursive: true);
+    });
+  });
+}
+
+testDirectoryExistsCreate() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  createLink(x, y, () {
+    Expect.isFalse(new Directory(x).existsSync());
+    Expect.isFalse(new Directory(y).existsSync());
+    Expect.throws(new Directory(y).createSync);
+    temp.deleteSync(recursive: true);
+  });
+}
+
+testDirectoryDelete() {
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var temp2 = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  var x = '${temp2.path}${Platform.pathSeparator}x';
+  new File(x).createSync();
+  createLink(temp2.path, y, () {
+    var link = new Directory(y);
+    Expect.isTrue(link.existsSync());
+    Expect.isTrue(temp2.existsSync());
+    link.deleteSync();
+    Expect.isFalse(link.existsSync());
+    Expect.isTrue(temp2.existsSync());
+    createLink(temp2.path, y, () {
+      Expect.isTrue(link.existsSync());
+      temp.deleteSync(recursive: true);
+      Expect.isFalse(link.existsSync());
+      Expect.isTrue(temp2.existsSync());
+      Expect.isTrue(new File(x).existsSync());
+      temp2.deleteSync(recursive: true);
+    });
+  });
+}
+
+testDirectoryListing() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var temp2 = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var y = '${temp.path}${Platform.pathSeparator}y';
+  var x = '${temp2.path}${Platform.pathSeparator}x';
+  new File(x).createSync();
+  createLink(temp2.path, y, () {
+    var files = [];
+    var dirs = [];
+    for (var entry in temp.listSync(recursive: true)) {
+      if (entry is File) {
+        files.add(entry.path);
+      } else {
+        Expect.isTrue(entry is Directory);
+        dirs.add(entry.path);
+      }
+    }
+    Expect.equals(1, files.length);
+    Expect.isTrue(files[0].endsWith('$y${Platform.pathSeparator}x'));
+    Expect.equals(1, dirs.length);
+    Expect.isTrue(dirs[0].endsWith(y));
+
+    files = [];
+    dirs = [];
+    var lister = temp.list(recursive: true).listen((entity) {
+      if (entity is File) {
+        files.add(entity.path);
+      } else {
+        Expect.isTrue(entity is Directory);
+        dirs.add(entity.path);
+      }
+    }, onDone: () {
+      Expect.equals(1, files.length);
+      Expect.isTrue(files[0].endsWith('$y${Platform.pathSeparator}x'));
+      Expect.equals(1, dirs.length);
+      Expect.isTrue(dirs[0].endsWith(y));
+      temp.deleteSync(recursive: true);
+      temp2.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+testDirectoryListingBrokenLink() {
+  asyncStart();
+  var temp = Directory.systemTemp.createTempSync('dart_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var link = '${temp.path}${Platform.pathSeparator}link';
+  var doesNotExist = 'this_thing_does_not_exist';
+  new File(x).createSync();
+  createLink(doesNotExist, link, () {
+    temp.listSync(recursive: true); // No exceptions.
+    var files = [];
+    var dirs = [];
+    var links = [];
+    var errors = [];
+    temp.list(recursive: true).listen(
+        (entity) {
+          if (entity is File) {
+            files.add(entity.path);
+          } else if (entity is Link) {
+            links.add(entity.path);
+          } else {
+            Expect.isTrue(entity is Directory);
+            dirs.add(entity.path);
+          }
+        },
+        onError: (e) => errors.add(e),
+        onDone: () {
+          Expect.equals(1, files.length);
+          Expect.isTrue(files[0].endsWith(x));
+          Expect.equals(1, links.length);
+          Expect.isTrue(links[0].endsWith(link));
+          Expect.equals(0, dirs.length);
+          Expect.equals(0, errors.length);
+          temp.deleteSync(recursive: true);
+          asyncEnd();
+        });
+  });
+}
+
+main() {
+  // Links on Windows are tested by windows_file_system_[async_]links_test.
+  if (Platform.operatingSystem != 'windows') {
+    testFileExistsCreate();
+    testFileDelete();
+    testFileWriteRead();
+    testDirectoryExistsCreate();
+    testDirectoryDelete();
+    testDirectoryListing();
+    testDirectoryListingBrokenLink();
+  }
+}
diff --git a/tests/standalone/io/file_system_uri_test.dart b/tests/standalone/io/file_system_uri_test.dart
new file mode 100644
index 0000000..a17caaf
--- /dev/null
+++ b/tests/standalone/io/file_system_uri_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+import "package:expect/expect.dart";
+
+testFile(String input) {
+  if (Platform.isWindows) {
+    input = input.replaceAll('/', '\\');
+  }
+  var file = new File(input);
+  var uri = file.uri;
+  var file2 = new File.fromUri(uri);
+  Expect.equals(file.path, file2.path, input);
+}
+
+testDirectory(String input, [String? output]) {
+  if (output == null) output = input;
+  if (Platform.isWindows) {
+    input = input.replaceAll('/', '\\');
+    output = output.replaceAll('/', '\\');
+  }
+  var dir = new Directory(input);
+  var uri = dir.uri;
+  var dir2 = new Directory.fromUri(uri);
+  Expect.equals(output, dir2.path, input);
+}
+
+void main() {
+  testFile("");
+  testFile("/");
+  testFile("foo/bar");
+  testFile("/foo/bar");
+  testFile("/foo/bar/");
+
+  testDirectory("");
+  testDirectory("/");
+  testDirectory("foo/bar", "foo/bar/");
+  testDirectory("/foo/bar", "/foo/bar/");
+  testDirectory("/foo/bar/");
+}
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
new file mode 100644
index 0000000..3ef4175
--- /dev/null
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -0,0 +1,480 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+void testWatchCreateFile() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemCreateEvent && event.path.endsWith('file')) {
+      Expect.isFalse(event.isDirectory);
+      asyncEnd();
+      sub.cancel();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.createSync();
+}
+
+void testWatchCreateDir() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var subdir = new Directory(join(dir.path, 'dir'));
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemCreateEvent && event.path.endsWith('dir')) {
+      Expect.isTrue(event.isDirectory);
+      asyncEnd();
+      sub.cancel();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  subdir.createSync();
+}
+
+void testWatchModifyFile() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+  file.createSync();
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemModifyEvent) {
+      Expect.isTrue(event.path.endsWith('file'));
+      sub.cancel();
+      asyncEnd();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.writeAsStringSync('a');
+}
+
+void testWatchMoveFile() {
+  // Mac OS doesn't report move events.
+  if (Platform.isMacOS) return;
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+  file.createSync();
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemMoveEvent) {
+      Expect.isTrue(event.path.endsWith('file'));
+      final destination = event.destination;
+      if (destination != null) {
+        Expect.isTrue(destination.endsWith('file2'));
+      }
+      sub.cancel();
+      asyncEnd();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.renameSync(join(dir.path, 'file2'));
+}
+
+void testWatchDeleteFile() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+  file.createSync();
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event is FileSystemDeleteEvent) {
+      Expect.isTrue(event.path.endsWith('file'));
+      sub.cancel();
+      asyncEnd();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.deleteSync();
+}
+
+void testWatchDeleteDir() {
+  // Windows keeps the directory handle open, even though it's deleted. It'll
+  // be flushed completely, once the watcher is closed as well.
+  if (Platform.isWindows) return;
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var watcher = dir.watch(events: 0);
+
+  asyncStart();
+  watcher.listen((event) {
+    if (event is FileSystemDeleteEvent) {
+      Expect.isTrue(event.path == dir.path);
+    }
+  }, onDone: () {
+    asyncEnd();
+  });
+
+  dir.deleteSync();
+}
+
+void testWatchOnlyModifyFile() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+
+  var watcher = dir.watch(events: FileSystemEvent.modify);
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    Expect.isTrue(event is FileSystemModifyEvent);
+    Expect.isTrue(event.path.endsWith('file'));
+    sub.cancel();
+    asyncEnd();
+    dir.deleteSync(recursive: true);
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.createSync();
+  file.writeAsStringSync('a');
+}
+
+void testMultipleEvents() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+  var file2 = new File(join(dir.path, 'file2'));
+
+  var watcher = dir.watch();
+
+  asyncStart();
+  int state = 0;
+  var sub;
+  sub = watcher.listen((event) {
+    int newState = 0;
+    switch (event.type) {
+      case FileSystemEvent.create:
+        newState = 1;
+        break;
+
+      case FileSystemEvent.modify:
+        newState = 2;
+        break;
+
+      case FileSystemEvent.move:
+        newState = 3;
+        break;
+
+      case FileSystemEvent.delete:
+        newState = 4;
+        sub.cancel();
+        asyncEnd();
+        dir.deleteSync();
+        break;
+    }
+    if (!Platform.isMacOS) {
+      if (newState < state) throw "Bad state";
+    }
+    state = newState;
+  });
+
+  file.createSync();
+  file.writeAsStringSync('a');
+  file.renameSync(file2.path);
+  file2.deleteSync();
+}
+
+void testWatchRecursive() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  if (Platform.isLinux) {
+    Expect.throws(() => dir.watch(recursive: true));
+    return;
+  }
+  var dir2 = new Directory(join(dir.path, 'dir'));
+  dir2.createSync();
+  var file = new File(join(dir.path, 'dir/file'));
+
+  var watcher = dir.watch(recursive: true);
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event.path.endsWith('file')) {
+      sub.cancel();
+      asyncEnd();
+      dir.deleteSync(recursive: true);
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.createSync();
+}
+
+void testWatchNonRecursive() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var dir2 = new Directory(join(dir.path, 'dir'));
+  dir2.createSync();
+  var file = new File(join(dir.path, 'dir/file'));
+
+  var watcher = dir.watch(recursive: false);
+
+  asyncStart();
+  var sub;
+  sub = watcher.listen((event) {
+    if (event.path.endsWith('file')) {
+      throw "File change event not expected";
+    }
+  }, onError: (e) {
+    dir.deleteSync(recursive: true);
+    throw e;
+  });
+
+  file.createSync();
+
+  new Timer(const Duration(milliseconds: 300), () {
+    sub.cancel();
+    asyncEnd();
+    dir.deleteSync(recursive: true);
+  });
+}
+
+void testWatchNonExisting() {
+  // MacOS allows listening on non-existing paths.
+  if (Platform.isMacOS) return;
+  asyncStart();
+  new Directory('__some_none_existing_dir__').watch().listen((_) {
+    Expect.fail('unexpected error');
+  }, onError: (e) {
+    asyncEnd();
+    Expect.isTrue(e is FileSystemException);
+  });
+}
+
+void testWatchMoveSelf() {
+  // Windows keeps the directory handle open, even though it's deleted. It'll
+  // be flushed completely, once the watcher is closed as well.
+  if (Platform.isWindows) return;
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var dir2 = new Directory(join(dir.path, 'dir'))..createSync();
+
+  var watcher = dir2.watch();
+
+  asyncStart();
+  bool gotDelete = false;
+  watcher.listen((event) {
+    if (event is FileSystemDeleteEvent) {
+      Expect.isTrue(event.path.endsWith('dir'));
+      gotDelete = true;
+    }
+  }, onDone: () {
+    Expect.isTrue(gotDelete);
+    dir.deleteSync(recursive: true);
+    asyncEnd();
+  });
+
+  dir2.renameSync(join(dir.path, 'new_dir'));
+}
+
+testWatchConsistentModifiedFile() async {
+  // When file modification starts before the watcher listen() is called and the first event
+  // happens in a very short period of time the modifying event will be missed before the
+  // stream listen has been set up and the watcher will hang forever.
+  // Bug: https://github.com/dart-lang/sdk/issues/37233
+  // Bug: https://github.com/dart-lang/sdk/issues/37909
+  asyncStart();
+  ReceivePort receivePort = ReceivePort();
+  Completer<bool> exiting = Completer<bool>();
+
+  late Directory dir;
+  Completer<bool> modificationEventReceived = Completer<bool>();
+
+  late StreamSubscription receiverSubscription;
+  late SendPort workerSendPort;
+  receiverSubscription = receivePort.listen((object) async {
+    if (object == 'modification_started') {
+      var watcher = dir.watch();
+      var subscription;
+      // Wait for event and check the type
+      subscription = watcher.listen((data) async {
+        if (data is FileSystemModifyEvent) {
+          Expect.isTrue(data.path.endsWith('file'));
+          await subscription.cancel();
+          modificationEventReceived.complete(true);
+        }
+      });
+      return;
+    }
+    if (object == 'end') {
+      await receiverSubscription.cancel();
+      exiting.complete(true);
+      return;
+    }
+    // init event
+    workerSendPort = object[0];
+    dir = new Directory(object[1]);
+  });
+
+  Completer<bool> workerExitedCompleter = Completer();
+  RawReceivePort exitReceivePort = RawReceivePort((object) {
+    workerExitedCompleter.complete(true);
+  });
+  RawReceivePort errorReceivePort = RawReceivePort((object) {
+    print('worker errored: $object');
+  });
+  Isolate isolate = await Isolate.spawn(modifyFiles, receivePort.sendPort,
+      onExit: exitReceivePort.sendPort, onError: errorReceivePort.sendPort);
+
+  await modificationEventReceived.future;
+  workerSendPort.send('end');
+
+  await exiting.future;
+  await workerExitedCompleter.future;
+  exitReceivePort.close();
+  errorReceivePort.close();
+  // Stop modifier isolate
+  isolate.kill();
+  asyncEnd();
+}
+
+void modifyFiles(SendPort sendPort) async {
+  // Send sendPort back to listen for modification signal.
+  ReceivePort receivePort = ReceivePort();
+  var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
+
+  // Create file within the directory and keep modifying.
+  var file = new File(join(dir.path, 'file'));
+  file.createSync();
+  bool done = false;
+  var subscription;
+  subscription = receivePort.listen((object) async {
+    if (object == 'end') {
+      await subscription.cancel();
+      done = true;
+    }
+  });
+  sendPort.send([receivePort.sendPort, dir.path]);
+  bool notificationSent = false;
+  while (!done) {
+    // Start modifying the file continuously before watcher start watching.
+    for (int i = 0; i < 100; i++) {
+      file.writeAsStringSync('a');
+    }
+    if (!notificationSent) {
+      sendPort.send('modification_started');
+      notificationSent = true;
+    }
+    await Future.delayed(Duration());
+  }
+  // Clean up the directory and files
+  dir.deleteSync(recursive: true);
+  sendPort.send('end');
+}
+
+testWatchOverflow() async {
+  // When underlying buffer for ReadDirectoryChangesW overflows(on Windows),
+  // it will send an exception to Stream which has been listened.
+  // Bug: https://github.com/dart-lang/sdk/issues/37233
+  asyncStart();
+  ReceivePort receivePort = ReceivePort();
+  Completer<bool> exiting = Completer<bool>();
+
+  Directory dir =
+      Directory.systemTemp.createTempSync('dart_file_system_watcher');
+  var file = new File(join(dir.path, 'file'));
+  file.createSync();
+
+  Isolate isolate =
+      await Isolate.spawn(watcher, receivePort.sendPort, paused: true);
+
+  var subscription;
+  subscription = receivePort.listen((object) async {
+    if (object == 'end') {
+      exiting.complete(true);
+      subscription.cancel();
+      // Clean up the directory and files
+      dir.deleteSync(recursive: true);
+      asyncEnd();
+    } else if (object == 'start') {
+      isolate.pause(isolate.pauseCapability);
+      // Populate the buffer to overflows and check for exception
+      for (int i = 0; i < 2000; i++) {
+        file.writeAsStringSync('a');
+      }
+      isolate.resume(isolate.pauseCapability!);
+    }
+  });
+  // Resume paused isolate to create watcher
+  isolate.resume(isolate.pauseCapability!);
+
+  await exiting.future;
+  isolate.kill();
+}
+
+void watcher(SendPort sendPort) async {
+  runZoned(() {
+    var watcher = Directory.systemTemp.watch(recursive: true);
+    watcher.listen((data) async {});
+    sendPort.send('start');
+  }, onError: (error) {
+    print(error);
+    sendPort.send('end');
+  });
+}
+
+void main() {
+  if (!FileSystemEntity.isWatchSupported) return;
+  testWatchCreateFile();
+  testWatchCreateDir();
+  testWatchModifyFile();
+  testWatchMoveFile();
+  testWatchDeleteFile();
+  testWatchDeleteDir();
+  testWatchOnlyModifyFile();
+  testMultipleEvents();
+  testWatchNonRecursive();
+  testWatchNonExisting();
+  testWatchMoveSelf();
+  testWatchConsistentModifiedFile();
+  if (Platform.isWindows) testWatchOverflow();
+}
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
new file mode 100644
index 0000000..7583b71
--- /dev/null
+++ b/tests/standalone/io/file_test.dart
@@ -0,0 +1,1684 @@
+// 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 program for testing file I/O.
+
+// OtherResources=empty_file
+// OtherResources=file_test.txt
+// OtherResources=fixed_length_file
+// OtherResources=read_as_text.dat
+// OtherResources=readline_test1.dat
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:collection';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+class MyListOfOneElement extends Object
+    with ListMixin<int>
+    implements List<int> {
+  int _value;
+  MyListOfOneElement(this._value);
+  int get length => 1;
+  operator [](int index) => _value;
+  void set length(int index) {
+    throw "Unsupported";
+  }
+
+  operator []=(int index, value) {
+    if (index != 0) {
+      throw "Unsupported";
+    } else {
+      _value = value;
+    }
+  }
+}
+
+class FileTest {
+  static late Directory tempDirectory;
+  static int numLiveAsyncTests = 0;
+
+  static void asyncTestStarted() {
+    asyncStart();
+    ++numLiveAsyncTests;
+  }
+
+  static void asyncTestDone(String name) {
+    asyncEnd();
+    --numLiveAsyncTests;
+    if (numLiveAsyncTests == 0) {
+      deleteTempDirectory();
+    }
+  }
+
+  static void createTempDirectory(Function doNext) {
+    Directory.systemTemp.createTemp('dart_file').then((temp) {
+      tempDirectory = temp;
+      doNext();
+    });
+  }
+
+  static void deleteTempDirectory() {
+    tempDirectory.deleteSync(recursive: true);
+  }
+
+  // Test for file read functionality.
+  static void testReadStream() {
+    // Read a file and check part of it's contents.
+    String filename = getFilename("file_test.txt");
+    File file = new File(filename);
+    Expect.isTrue('$file'.contains(file.path));
+    var subscription;
+    List<int> buffer = new List<int>();
+    subscription = file.openRead().listen((d) {
+      buffer.addAll(d);
+      if (buffer.length >= 12) {
+        subscription.cancel();
+        Expect.equals(47, buffer[0]); // represents '/' in the file.
+        Expect.equals(47, buffer[1]); // represents '/' in the file.
+        Expect.equals(32, buffer[2]); // represents ' ' in the file.
+        Expect.equals(67, buffer[3]); // represents 'C' in the file.
+        Expect.equals(111, buffer[4]); // represents 'o' in the file.
+        Expect.equals(112, buffer[5]); // represents 'p' in the file.
+        Expect.equals(121, buffer[6]); // represents 'y' in the file.
+        Expect.equals(114, buffer[7]); // represents 'r' in the file.
+        Expect.equals(105, buffer[8]); // represents 'i' in the file.
+        Expect.equals(103, buffer[9]); // represents 'g' in the file.
+        Expect.equals(104, buffer[10]); // represents 'h' in the file.
+        Expect.equals(116, buffer[11]); // represents 't' in the file.
+      }
+    });
+  }
+
+  // Test for file read and write functionality.
+  static void testReadWriteStream() {
+    asyncTestStarted();
+
+    // Read a file.
+    String inFilename = getFilename("fixed_length_file");
+    File file;
+    int bytesRead;
+
+    var file1 = new File(inFilename);
+    List<int> buffer = new List<int>();
+    file1.openRead().listen((d) {
+      buffer.addAll(d);
+    }, onDone: () {
+      Expect.equals(42, buffer.length);
+      // Write the contents of the file just read into another file.
+      String outFilename = tempDirectory.path + "/out_read_write_stream";
+      var file2 = new File(outFilename);
+      var output = file2.openWrite();
+      output.add(buffer);
+      output.flush().then((_) => output.close());
+      output.done.then((_) {
+        // Now read the contents of the file just written.
+        List<int> buffer2 = new List<int>();
+        new File(outFilename).openRead().listen((d) {
+          buffer2.addAll(d);
+        }, onDone: () {
+          Expect.equals(42, buffer2.length);
+          // Now compare the two buffers to check if they are
+          // identical.
+          for (int i = 0; i < buffer.length; i++) {
+            Expect.equals(buffer[i], buffer2[i]);
+          }
+          // Delete the output file.
+          file2.deleteSync();
+          Expect.isFalse(file2.existsSync());
+          asyncTestDone("testReadWriteStream");
+        });
+      });
+    });
+  }
+
+  // Test for file stream buffered handling of large files.
+  static void testReadWriteStreamLargeFile() {
+    // Create the test data - arbitrary binary data.
+    List<int> buffer = new List<int>.filled(100000, 0);
+    for (var i = 0; i < buffer.length; ++i) {
+      buffer[i] = i % 256;
+    }
+    String filename = tempDirectory.path + "/out_read_write_stream_large_file";
+    File file = new File(filename);
+    IOSink output = file.openWrite();
+    output.add(buffer);
+    output.add(buffer);
+    output.flush().then((_) => output.close());
+
+    asyncTestStarted();
+    output.done
+        .then((_) {
+          final input = file.openRead();
+          int position = 0;
+          final int expectedLength = 200000;
+
+          // Start an independent asynchronous check on the length.
+          Future lengthTest() {
+            asyncTestStarted();
+            return file.length().then((len) {
+              Expect.equals(expectedLength, len);
+              asyncTestDone('testReadWriteStreamLargeFile: length check');
+            });
+          }
+
+          // Immediate read should read 0 bytes.
+          Future contentTest() {
+            asyncTestStarted();
+            var completer = new Completer();
+            input.listen((List<int> data) {
+              for (int i = 0; i < data.length; ++i) {
+                Expect.equals(buffer[(i + position) % buffer.length], data[i]);
+              }
+              position += data.length;
+            }, onError: (error, trace) {
+              print('Error on input in testReadWriteStreamLargeFile');
+              print('with error $error');
+              if (trace != null) print("StackTrace: $trace");
+              throw error;
+            }, onDone: () {
+              Expect.equals(expectedLength, position);
+              testPipe(file, buffer).then((_) {
+                asyncTestDone('testReadWriteStreamLargeFile: main test');
+              }).catchError((error, trace) {
+                print('Exception while deleting ReadWriteStreamLargeFile file');
+                print('Exception $error');
+                if (trace != null) print("StackTrace: $trace");
+                throw error;
+              }).whenComplete(completer.complete);
+            });
+            return completer.future;
+          }
+
+          return Future.forEach<Function>(
+              [lengthTest, contentTest], (test) => test());
+        })
+        .whenComplete(file.delete)
+        .whenComplete(() {
+          asyncTestDone('testReadWriteStreamLargeFile finished');
+        });
+  }
+
+  static Future testPipe(File file, buffer) {
+    String outputFilename = '${file.path}_copy';
+    File outputFile = new File(outputFilename);
+    var input = file.openRead();
+    var output = outputFile.openWrite();
+    Completer done = new Completer();
+    input.cast<List<int>>().pipe(output).then((_) {
+      var copy = outputFile.openRead();
+      int position = 0;
+      copy.listen((d) {
+        for (int i = 0; i < d.length; i++) {
+          Expect.equals(buffer[(position + i) % buffer.length], d[i]);
+        }
+        position += d.length;
+      }, onDone: () {
+        Expect.equals(2 * buffer.length, position);
+        outputFile.delete().then((ignore) {
+          done.complete();
+        });
+      });
+    });
+    return done.future;
+  }
+
+  static void testRead() {
+    asyncStart();
+    // Read a file and check part of it's contents.
+    String filename = getFilename("file_test.txt");
+    File file = new File(filename);
+    file.open(mode: FileMode.read).then((RandomAccessFile file) {
+      List<int> buffer = new List<int>.filled(10, 0);
+      file.readInto(buffer, 0, 5).then((bytes_read) {
+        Expect.equals(5, bytes_read);
+        file.readInto(buffer, 5, 10).then((bytes_read) {
+          Expect.equals(5, bytes_read);
+          Expect.equals(47, buffer[0]); // represents '/' in the file.
+          Expect.equals(47, buffer[1]); // represents '/' in the file.
+          Expect.equals(32, buffer[2]); // represents ' ' in the file.
+          Expect.equals(67, buffer[3]); // represents 'C' in the file.
+          Expect.equals(111, buffer[4]); // represents 'o' in the file.
+          Expect.equals(112, buffer[5]); // represents 'p' in the file.
+          Expect.equals(121, buffer[6]); // represents 'y' in the file.
+          Expect.equals(114, buffer[7]); // represents 'r' in the file.
+          Expect.equals(105, buffer[8]); // represents 'i' in the file.
+          Expect.equals(103, buffer[9]); // represents 'g' in the file.
+          file.close().then((ignore) => asyncEnd());
+        });
+      });
+    });
+  }
+
+  static void testReadSync() {
+    // Read a file and check part of it's contents.
+    String filename = getFilename("file_test.txt");
+    RandomAccessFile raf = (new File(filename)).openSync();
+    List<int> buffer = new List<int>.filled(42, 0);
+    int bytes_read = 0;
+    bytes_read = raf.readIntoSync(buffer, 0, 12);
+    Expect.equals(12, bytes_read);
+    bytes_read = raf.readIntoSync(buffer, 12, 42);
+    Expect.equals(30, bytes_read);
+    Expect.equals(47, buffer[0]); // represents '/' in the file.
+    Expect.equals(47, buffer[1]); // represents '/' in the file.
+    Expect.equals(32, buffer[2]); // represents ' ' in the file.
+    Expect.equals(67, buffer[3]); // represents 'C' in the file.
+    Expect.equals(111, buffer[4]); // represents 'o' in the file.
+    Expect.equals(112, buffer[5]); // represents 'p' in the file.
+    Expect.equals(121, buffer[6]); // represents 'y' in the file.
+    Expect.equals(114, buffer[7]); // represents 'r' in the file.
+    Expect.equals(105, buffer[8]); // represents 'i' in the file.
+    Expect.equals(103, buffer[9]); // represents 'g' in the file.
+    Expect.equals(104, buffer[10]); // represents 'h' in the file.
+    Expect.equals(116, buffer[11]); // represents 't' in the file.
+    raf.closeSync();
+
+    filename = getFilename("fixed_length_file");
+    File file = new File(filename);
+    int len = file.lengthSync();
+    int read(int length) {
+      var f = file.openSync();
+      int res = f.readSync(length).length;
+      f.closeSync();
+      return res;
+    }
+
+    Expect.equals(0, read(0));
+    Expect.equals(1, read(1));
+    Expect.equals(len - 1, read(len - 1));
+    Expect.equals(len, read(len));
+    Expect.equals(len, read(len + 1));
+    Expect.equals(len, read(len * 2));
+    Expect.equals(len, read(len * 10));
+  }
+
+  // Test for file read and write functionality.
+  static void testReadWrite() {
+    asyncTestStarted();
+    // Read a file.
+    String inFilename = getFilename("fixed_length_file");
+    final File file = new File(inFilename);
+    file.open(mode: FileMode.read).then((openedFile) {
+      List<int> buffer1 = new List<int>.filled(42, 0);
+      openedFile.readInto(buffer1, 0, 42).then((bytes_read) {
+        Expect.equals(42, bytes_read);
+        openedFile.close().then((ignore) {
+          // Write the contents of the file just read into another file.
+          String outFilename = tempDirectory.path + "/out_read_write";
+          final File file2 = new File(outFilename);
+          file2.create().then((ignore) {
+            file2.resolveSymbolicLinks().then((s) {
+              Expect.isTrue(new File(s).existsSync());
+              if (s[0] != '/' && s[0] != '\\' && s[1] != ':') {
+                Expect.fail("Not a full path");
+              }
+              file2.open(mode: FileMode.write).then((openedFile2) {
+                openedFile2.writeFrom(buffer1, 0, bytes_read).then((ignore) {
+                  openedFile2.close().then((ignore) {
+                    List<int> buffer2 = new List<int>.filled(bytes_read, 0);
+                    final File file3 = new File(outFilename);
+                    file3.open(mode: FileMode.read).then((openedFile3) {
+                      openedFile3.readInto(buffer2, 0, 42).then((bytes_read) {
+                        Expect.equals(42, bytes_read);
+                        openedFile3.close().then((ignore) {
+                          // Now compare the two buffers to check if they
+                          // are identical.
+                          Expect.equals(buffer1.length, buffer2.length);
+                          for (int i = 0; i < buffer1.length; i++) {
+                            Expect.equals(buffer1[i], buffer2[i]);
+                          }
+                          // Delete the output file.
+                          final file4 = file3;
+                          file4.delete().then((ignore) {
+                            file4.exists().then((exists) {
+                              Expect.isFalse(exists);
+                              asyncTestDone("testReadWrite");
+                            });
+                          });
+                        });
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testWriteAppend() {
+    String content = "foobar";
+    String filename = tempDirectory.path + "/write_append";
+    File file = new File(filename);
+    file.createSync();
+    Expect.isTrue(new File(filename).existsSync());
+    List<int> buffer = content.codeUnits;
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeFromSync(buffer, 0, buffer.length);
+    openedFile.closeSync();
+    // Reopen the file in write mode to ensure that we overwrite the content.
+    openedFile = (new File(filename)).openSync(mode: FileMode.write);
+    openedFile.writeFromSync(buffer, 0, buffer.length);
+    Expect.equals(content.length, openedFile.lengthSync());
+    openedFile.closeSync();
+    // Open the file in append mode and ensure that we do not overwrite
+    // the existing content.
+    openedFile = (new File(filename)).openSync(mode: FileMode.append);
+    openedFile.writeFromSync(buffer, 2, buffer.length - 2);
+    Expect.equals(content.length + content.length - 4, openedFile.lengthSync());
+    Expect.equals(content + content.substring(2, content.length - 2),
+        file.readAsStringSync());
+    openedFile.closeSync();
+    file.deleteSync();
+  }
+
+  static void testOutputStreamWriteAppend() {
+    asyncTestStarted();
+    String content = "foobar";
+    String filename = tempDirectory.path + "/outstream_write_append";
+    File file = new File(filename);
+    file.createSync();
+    List<int> buffer = content.codeUnits;
+    var output = file.openWrite();
+    output.add(buffer);
+    output.close();
+    output.done.then((_) {
+      File file2 = new File(filename);
+      var appendingOutput = file2.openWrite(mode: FileMode.append);
+      appendingOutput.add(buffer);
+      appendingOutput.close();
+      appendingOutput.done.then((_) {
+        File file3 = new File(filename);
+        file3.open(mode: FileMode.read).then((RandomAccessFile openedFile) {
+          openedFile.length().then((int length) {
+            Expect.equals(content.length * 2, length);
+            openedFile.close().then((ignore) {
+              file3.delete().then((ignore) {
+                asyncTestDone("testOutputStreamWriteAppend");
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  // Test for file read and write functionality.
+  static void testOutputStreamWriteString() {
+    asyncTestStarted();
+    String content = "foobar";
+    String filename = tempDirectory.path + "/outstream_write_string";
+    File file = new File(filename);
+    file.createSync();
+    List<int> buffer = content.codeUnits;
+    var output = file.openWrite();
+    output.write("abcdABCD");
+    output.encoding = utf8;
+    output.write("abcdABCD");
+    output.encoding = latin1;
+    output.write("abcdABCD");
+    output.encoding = ascii;
+    output.write("abcdABCD");
+    output.encoding = utf8;
+    output.write("æøå");
+    output.close();
+    output.done.then((_) {
+      RandomAccessFile raf = file.openSync();
+      Expect.equals(38, raf.lengthSync());
+      raf.close().then((ignore) {
+        asyncTestDone("testOutputStreamWriteString");
+      });
+    });
+  }
+
+  static void testReadWriteSync() {
+    // Read a file.
+    String inFilename = getFilename("fixed_length_file");
+    RandomAccessFile file = (new File(inFilename)).openSync();
+    List<int> buffer1 = new List<int>.filled(42, 0);
+    int bytes_read = 0;
+    int bytes_written = 0;
+    bytes_read = file.readIntoSync(buffer1, 0, 42);
+    Expect.equals(42, bytes_read);
+    file.closeSync();
+    // Write the contents of the file just read into another file.
+    String outFilename = tempDirectory.path + "/out_read_write_sync";
+    File outFile = new File(outFilename);
+    outFile.createSync();
+    String path = outFile.resolveSymbolicLinksSync();
+    if (path[0] != '/' && path[0] != '\\' && path[1] != ':') {
+      Expect.fail("Not a full path");
+    }
+    Expect.isTrue(new File(path).existsSync());
+    RandomAccessFile openedFile = outFile.openSync(mode: FileMode.write);
+    openedFile.writeFromSync(buffer1, 0, bytes_read);
+    openedFile.closeSync();
+    // Now read the contents of the file just written.
+    List<int> buffer2 = new List<int>.filled(bytes_read, 0);
+    openedFile = (new File(outFilename)).openSync();
+    bytes_read = openedFile.readIntoSync(buffer2, 0, 42);
+    Expect.equals(42, bytes_read);
+    openedFile.closeSync();
+    // Now compare the two buffers to check if they are identical.
+    Expect.equals(buffer1.length, buffer2.length);
+    for (int i = 0; i < buffer1.length; i++) {
+      Expect.equals(buffer1[i], buffer2[i]);
+    }
+    // Delete the output file.
+    outFile.deleteSync();
+    Expect.isFalse(outFile.existsSync());
+  }
+
+  static void testReadWriteNoArgsSync() {
+    // Read a file.
+    String inFilename = getFilename("fixed_length_file");
+    RandomAccessFile file = (new File(inFilename)).openSync();
+    List<int> buffer1 = new List<int>.filled(42, 0);
+    int bytes_read = 0;
+    int bytes_written = 0;
+    bytes_read = file.readIntoSync(buffer1);
+    Expect.equals(42, bytes_read);
+    file.closeSync();
+    // Write the contents of the file just read into another file.
+    String outFilename = tempDirectory.path + "/out_read_write_sync";
+    File outFile = new File(outFilename);
+    outFile.createSync();
+    String path = outFile.resolveSymbolicLinksSync();
+    if (path[0] != '/' && path[0] != '\\' && path[1] != ':') {
+      Expect.fail("Not a full path");
+    }
+    Expect.isTrue(new File(path).existsSync());
+    RandomAccessFile openedFile = outFile.openSync(mode: FileMode.write);
+    openedFile.writeFromSync(buffer1);
+    openedFile.closeSync();
+    // Now read the contents of the file just written.
+    List<int> buffer2 = new List<int>.filled(bytes_read, 0);
+    openedFile = (new File(outFilename)).openSync();
+    bytes_read = openedFile.readIntoSync(buffer2, 0);
+    Expect.equals(42, bytes_read);
+    openedFile.closeSync();
+    // Now compare the two buffers to check if they are identical.
+    Expect.equals(buffer1.length, buffer2.length);
+    for (int i = 0; i < buffer1.length; i++) {
+      Expect.equals(buffer1[i], buffer2[i]);
+    }
+    // Delete the output file.
+    outFile.deleteSync();
+    Expect.isFalse(outFile.existsSync());
+  }
+
+  static void testReadEmptyFileSync() {
+    String fileName = tempDirectory.path + "/empty_file_sync";
+    File file = new File(fileName);
+    file.createSync();
+    RandomAccessFile openedFile = file.openSync();
+    Expect.equals(-1, openedFile.readByteSync());
+    openedFile.closeSync();
+    file.deleteSync();
+  }
+
+  static void testReadEmptyFile() {
+    String fileName = tempDirectory.path + "/empty_file";
+    File file = new File(fileName);
+    asyncTestStarted();
+    file.create().then((ignore) {
+      file.open(mode: FileMode.read).then((RandomAccessFile openedFile) {
+        var readByteFuture = openedFile.readByte();
+        readByteFuture.then((int byte) {
+          Expect.equals(-1, byte);
+          openedFile.close().then((ignore) {
+            asyncTestDone("testReadEmptyFile");
+          });
+        });
+      });
+    });
+  }
+
+  // Test for file write of different types of lists.
+  static void testWriteVariousLists() {
+    asyncTestStarted();
+    final String fileName = "${tempDirectory.path}/testWriteVariousLists";
+    final File file = new File(fileName);
+    file.create().then((ignore) {
+      file.open(mode: FileMode.write).then((RandomAccessFile openedFile) {
+        // Write bytes from 0 to 7.
+        openedFile.writeFromSync([0], 0, 1);
+        openedFile.writeFromSync(const [1], 0, 1);
+        openedFile.writeFromSync(new MyListOfOneElement(2), 0, 1);
+        var x = -259;
+        var y = 0;
+        openedFile.writeFromSync([y - x], 0, 1);
+        openedFile.writeFromSync([260], 0, 1); // 260 = 256 + 4 = 0x104.
+        openedFile.writeFromSync(const [261], 0, 1);
+        openedFile.writeFromSync(new MyListOfOneElement(262), 0, 1);
+        x = 0;
+        y = 263;
+        openedFile.writeFrom([y - x], 0, 1).then((ignore) {
+          openedFile.close().then((ignore) {
+            // Check the written bytes.
+            final File file2 = new File(fileName);
+            var openedFile2 = file2.openSync();
+            var length = openedFile2.lengthSync();
+            Expect.equals(8, length);
+            var data = new List<int>.filled(length, 0);
+            openedFile2.readIntoSync(data, 0, length);
+            for (var i = 0; i < data.length; i++) {
+              Expect.equals(i, data[i]);
+            }
+            openedFile2.closeSync();
+            file2.deleteSync();
+            asyncTestDone("testWriteVariousLists");
+          });
+        });
+      });
+    });
+  }
+
+  static void testWriteFromOffset() {
+    final tmp = tempDirectory.createTempSync('write_from_offset_test_');
+    try {
+      File f = new File('${tmp.path}/file')..createSync();
+      f.writeAsStringSync('pre-existing content\n', flush: true);
+      final raf = f.openSync(mode: FileMode.append);
+      try {
+        String truth = "Hello world";
+        raf.writeFromSync(utf8.encode('Hello world'), 2, 5);
+        raf.flushSync();
+        Expect.equals(f.readAsStringSync(), 'pre-existing content\nllo');
+      } finally {
+        raf.closeSync();
+      }
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  static void testDirectory() {
+    asyncTestStarted();
+    var tempDir = tempDirectory.path;
+    var file = new File("${tempDir}/testDirectory");
+    file.create().then((ignore) {
+      Directory d = file.parent;
+      d.exists().then((xexists) {
+        Expect.isTrue(xexists);
+        Expect.isTrue(d.path.endsWith(tempDir));
+        file.delete().then((ignore) => asyncTestDone("testDirectory"));
+      });
+    });
+  }
+
+  static void testDirectorySync() {
+    var tempDir = tempDirectory.path;
+    var file = new File("${tempDir}/testDirectorySync");
+    // Non-existing file still provides the directory.
+    Expect.equals("${tempDir}", file.parent.path);
+    file.createSync();
+    // Check that the path of the returned directory is the temp directory.
+    Directory d = file.parent;
+    Expect.isTrue(d.existsSync());
+    Expect.isTrue(d.path.endsWith(tempDir));
+    file.deleteSync();
+    // The directory getter does not care about file or type of file
+    // system entity.
+    Expect.equals("${tempDir}", file.parent.path);
+    file = new File("foo");
+    Expect.equals(".", file.parent.path);
+    file = new File(".");
+    Expect.equals(".", file.parent.path);
+  }
+
+  // Test for file length functionality.
+  static void testLength() {
+    asyncTestStarted();
+    String filename = getFilename("fixed_length_file");
+    File file = new File(filename);
+    RandomAccessFile openedFile = file.openSync();
+    openedFile.length().then((length) {
+      Expect.equals(42, length);
+      openedFile.close().then((ignore) => asyncTestDone("testLength"));
+    });
+    file.length().then((length) {
+      Expect.equals(42, length);
+    });
+  }
+
+  static void testLengthSync() {
+    String filename = getFilename("fixed_length_file");
+    File file = new File(filename);
+    RandomAccessFile openedFile = file.openSync();
+    Expect.equals(42, file.lengthSync());
+    Expect.equals(42, openedFile.lengthSync());
+    openedFile.closeSync();
+  }
+
+  static void testLengthSyncDirectory() {
+    Directory tmp = tempDirectory.createTempSync('file_length_test_');
+    String dirPath = '${tmp.path}/dir';
+    new Directory(dirPath).createSync();
+    try {
+      new File(dirPath).lengthSync();
+      Expect.fail('Expected operation to throw');
+    } catch (e) {
+      if (e is! FileSystemException) {
+        print(e);
+      }
+      Expect.isTrue(e is FileSystemException);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  // Test for file position functionality.
+  static void testPosition() {
+    asyncTestStarted();
+    String filename = getFilename("fixed_length_file");
+    RandomAccessFile input = (new File(filename)).openSync();
+    input.position().then((position) {
+      Expect.equals(0, position);
+      List<int> buffer = new List<int>.filled(100, 0);
+      input.readInto(buffer, 0, 12).then((bytes_read) {
+        input.position().then((position) {
+          Expect.equals(12, position);
+          input.readInto(buffer, 12, 18).then((bytes_read) {
+            input.position().then((position) {
+              Expect.equals(18, position);
+              input.setPosition(8).then((ignore) {
+                input.position().then((position) {
+                  Expect.equals(8, position);
+                  input.close().then((ignore) => asyncTestDone("testPosition"));
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testPositionSync() {
+    String filename = getFilename("fixed_length_file");
+    RandomAccessFile input = (new File(filename)).openSync();
+    Expect.equals(0, input.positionSync());
+    List<int> buffer = new List<int>.filled(100, 0);
+    input.readIntoSync(buffer, 0, 12);
+    Expect.equals(12, input.positionSync());
+    input.readIntoSync(buffer, 12, 18);
+    Expect.equals(18, input.positionSync());
+    input.setPositionSync(8);
+    Expect.equals(8, input.positionSync());
+    input.closeSync();
+  }
+
+  static void testTruncate() {
+    asyncTestStarted();
+    File file = new File(tempDirectory.path + "/out_truncate");
+    List<int> buffer = const [65, 65, 65, 65, 65, 65, 65, 65, 65, 65];
+    file.open(mode: FileMode.write).then((RandomAccessFile openedFile) {
+      openedFile.writeFrom(buffer, 0, 10).then((ignore) {
+        openedFile.length().then((length) {
+          Expect.equals(10, length);
+          openedFile.truncate(5).then((ignore) {
+            openedFile.length().then((length) {
+              Expect.equals(5, length);
+              openedFile.close().then((ignore) {
+                file.delete().then((ignore) {
+                  file.exists().then((exists) {
+                    Expect.isFalse(exists);
+                    asyncTestDone("testTruncate");
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testTruncateSync() {
+    File file = new File(tempDirectory.path + "/out_truncate_sync");
+    List<int> buffer = const [65, 65, 65, 65, 65, 65, 65, 65, 65, 65];
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeFromSync(buffer, 0, 10);
+    Expect.equals(10, openedFile.lengthSync());
+    openedFile.truncateSync(5);
+    Expect.equals(5, openedFile.lengthSync());
+    bool exceptionCaught = false;
+    bool wrongExceptionCaught = false;
+    try {
+      openedFile.truncateSync(-5);
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    openedFile.closeSync();
+    file.deleteSync();
+    Expect.isFalse(file.existsSync());
+  }
+
+  static testReadInto() async {
+    asyncTestStarted();
+    File file = new File(tempDirectory.path + "/out_read_into");
+
+    var openedFile = await file.open(mode: FileMode.write);
+    await openedFile.writeFrom(const [1, 2, 3]);
+
+    await openedFile.setPosition(0);
+    var list = [-1, -1, -1];
+    Expect.equals(3, await openedFile.readInto(list));
+    Expect.listEquals([1, 2, 3], list);
+
+    read(start, end, length, expected) async {
+      var list = [-1, -1, -1];
+      await openedFile.setPosition(0);
+      Expect.equals(length, await openedFile.readInto(list, start, end));
+      Expect.listEquals(expected, list);
+      return list;
+    }
+
+    await read(0, 3, 3, [1, 2, 3]);
+    await read(0, 2, 2, [1, 2, -1]);
+    await read(1, 2, 1, [-1, 1, -1]);
+    await read(1, 3, 2, [-1, 1, 2]);
+    await read(2, 3, 1, [-1, -1, 1]);
+    await read(0, 0, 0, [-1, -1, -1]);
+
+    await openedFile.close();
+
+    asyncTestDone("testReadInto");
+  }
+
+  static void testReadIntoSync() {
+    File file = new File(tempDirectory.path + "/out_read_into_sync");
+
+    var openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeFromSync(const [1, 2, 3]);
+
+    openedFile.setPositionSync(0);
+    var list = [-1, -1, -1];
+    Expect.equals(3, openedFile.readIntoSync(list));
+    Expect.listEquals([1, 2, 3], list);
+
+    read(start, end, length, expected) {
+      var list = [-1, -1, -1];
+      openedFile.setPositionSync(0);
+      Expect.equals(length, openedFile.readIntoSync(list, start, end));
+      Expect.listEquals(expected, list);
+      return list;
+    }
+
+    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]);
+
+    openedFile.closeSync();
+  }
+
+  static testWriteFrom() async {
+    asyncTestStarted();
+    File file = new File(tempDirectory.path + "/out_write_from");
+
+    var buffer = const [1, 2, 3];
+    var openedFile = await file.open(mode: FileMode.write);
+
+    await openedFile.writeFrom(buffer);
+    var result = []..addAll(buffer);
+    ;
+
+    write([start, end]) async {
+      var returnValue = await openedFile.writeFrom(buffer, start, end);
+      Expect.identical(openedFile, returnValue);
+      result.addAll(buffer.sublist(start, end));
+    }
+
+    await write(0, 3);
+    await write(0, 2);
+    await write(1, 2);
+    await write(1, 3);
+    await write(2, 3);
+    await write(0, 0);
+
+    var bytesFromFile = await file.readAsBytes();
+    Expect.listEquals(result, bytesFromFile);
+
+    await openedFile.close();
+
+    asyncTestDone("testWriteFrom");
+  }
+
+  static void testWriteFromSync() {
+    File file = new File(tempDirectory.path + "/out_write_from_sync");
+
+    var buffer = const [1, 2, 3];
+    var openedFile = file.openSync(mode: FileMode.write);
+
+    openedFile.writeFromSync(buffer);
+    var result = []..addAll(buffer);
+    ;
+
+    write([start, end]) {
+      openedFile.writeFromSync(buffer, start, end);
+      result.addAll(buffer.sublist(start, end));
+    }
+
+    write(0, 3);
+    write(0, 2);
+    write(1, 2);
+    write(1, 3);
+    write(2, 3);
+
+    var bytesFromFile = file.readAsBytesSync();
+    Expect.listEquals(result, bytesFromFile);
+
+    openedFile.closeSync();
+  }
+
+  // Tests exception handling after file was closed.
+  static void testCloseException() {
+    bool exceptionCaught = false;
+    bool wrongExceptionCaught = false;
+    File input = new File(tempDirectory.path + "/out_close_exception");
+    RandomAccessFile openedFile = input.openSync(mode: FileMode.write);
+    openedFile.closeSync();
+    try {
+      openedFile.readByteSync();
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      openedFile.writeByteSync(1);
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      openedFile.writeStringSync("Test");
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(100, 0);
+      openedFile.readIntoSync(buffer, 0, 10);
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(100, 0);
+      openedFile.writeFromSync(buffer, 0, 10);
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      openedFile.positionSync();
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      openedFile.lengthSync();
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      openedFile.flushSync();
+    } on FileSystemException catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    input.deleteSync();
+  }
+
+  // Tests stream exception handling after file was closed.
+  static void testCloseExceptionStream() {
+    asyncTestStarted();
+    List<int> buffer = new List<int>.filled(42, 0);
+    File file = new File(tempDirectory.path + "/out_close_exception_stream");
+    file.createSync();
+    var output = file.openWrite();
+    output.close();
+    Expect.throws(() {
+      output.add(buffer);
+    });
+    output.done.then((_) {
+      file.deleteSync();
+      asyncTestDone("testCloseExceptionStream");
+    });
+  }
+
+  // Tests buffer out of bounds exception.
+  static void testBufferOutOfBoundsException() {
+    bool exceptionCaught = false;
+    bool wrongExceptionCaught = false;
+    File file = new File(tempDirectory.path + "/out_buffer_out_of_bounds");
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.write);
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.readIntoSync(buffer, 0, 12);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.readIntoSync(buffer, 6, 12);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.readIntoSync(buffer, -1, 1);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.readIntoSync(buffer, 0, -1);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.writeFromSync(buffer, 0, 12);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.writeFromSync(buffer, 6, 12);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.writeFromSync(buffer, -1, 1);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    exceptionCaught = false;
+    try {
+      List<int> buffer = new List<int>.filled(10, 0);
+      openedFile.writeFromSync(buffer, 0, -1);
+    } on RangeError catch (ex) {
+      exceptionCaught = true;
+    } on Exception catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(true, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+    openedFile.closeSync();
+    file.deleteSync();
+  }
+
+  static void testOpenDirectoryAsFile() {
+    var f = new File('.');
+    var future = f.open(mode: FileMode.read);
+    future
+        .then((r) => Expect.fail('Directory opened as file'))
+        .catchError((e) {});
+  }
+
+  static void testOpenDirectoryAsFileSync() {
+    var f = new File('.');
+    try {
+      f.openSync();
+      Expect.fail("Expected exception opening directory as file");
+    } catch (e) {
+      Expect.isTrue(e is FileSystemException);
+    }
+  }
+
+  static void testReadAsBytes() {
+    asyncTestStarted();
+    var name = getFilename("fixed_length_file");
+    var f = new File(name);
+    f.readAsBytes().then((bytes) {
+      Expect.isTrue(new String.fromCharCodes(bytes).endsWith("42 bytes."));
+      Expect.equals(42, bytes.length);
+      asyncTestDone("testReadAsBytes");
+    });
+  }
+
+  static void testReadAsBytesEmptyFile() {
+    asyncTestStarted();
+    var name = getFilename("empty_file");
+    var f = new File(name);
+    f.readAsBytes().then((bytes) {
+      Expect.equals(0, bytes.length);
+      asyncTestDone("testReadAsBytesEmptyFile");
+    });
+  }
+
+  static void testReadAsBytesSync() {
+    var name = getFilename("fixed_length_file");
+    var bytes = new File(name).readAsBytesSync();
+    Expect.isTrue(new String.fromCharCodes(bytes).endsWith("42 bytes."));
+    Expect.equals(bytes.length, 42);
+  }
+
+  static void testReadAsBytesSyncEmptyFile() {
+    var name = getFilename("empty_file");
+    var bytes = new File(name).readAsBytesSync();
+    Expect.equals(bytes.length, 0);
+  }
+
+  static void testReadAsText() {
+    asyncTestStarted();
+    var name = getFilename("fixed_length_file");
+    var f = new File(name);
+    f.readAsString(encoding: utf8).then((text) {
+      Expect.isTrue(text.endsWith("42 bytes."));
+      Expect.equals(42, text.length);
+      var name = getFilename("read_as_text.dat");
+      var f = new File(name);
+      f.readAsString(encoding: utf8).then((text) {
+        Expect.equals(6, text.length);
+        var expected = [955, 120, 46, 32, 120, 10];
+        Expect.listEquals(expected, text.codeUnits);
+        f.readAsString(encoding: latin1).then((text) {
+          Expect.equals(7, text.length);
+          var expected = [206, 187, 120, 46, 32, 120, 10];
+          Expect.listEquals(expected, text.codeUnits);
+          var readAsStringFuture = f.readAsString(encoding: ascii);
+          readAsStringFuture.then((text) {
+            Expect.fail("Non-ascii char should cause error");
+          }).catchError((e) {
+            asyncTestDone("testReadAsText");
+          });
+        });
+      });
+    });
+  }
+
+  static void testReadAsTextEmptyFile() {
+    asyncTestStarted();
+    var name = getFilename("empty_file");
+    var f = new File(name);
+    f.readAsString(encoding: utf8).then((text) {
+      Expect.equals(0, text.length);
+      asyncTestDone("testReadAsTextEmptyFile");
+      return true;
+    });
+  }
+
+  static void testReadAsTextSync() {
+    var name = getFilename("fixed_length_file");
+    var text = new File(name).readAsStringSync();
+    Expect.isTrue(text.endsWith("42 bytes."));
+    Expect.equals(42, text.length);
+    name = getFilename("read_as_text.dat");
+    text = new File(name).readAsStringSync();
+    Expect.equals(6, text.length);
+    var expected = [955, 120, 46, 32, 120, 10];
+    Expect.listEquals(expected, text.codeUnits);
+    // First character is not ASCII. The default ASCII decoder will throw.
+    Expect.throws(() => new File(name).readAsStringSync(encoding: ascii),
+        (e) => e is FileSystemException);
+    // We can use an ASCII decoder that inserts the replacement character.
+    var lenientAscii = const AsciiCodec(allowInvalid: true);
+    text = new File(name).readAsStringSync(encoding: lenientAscii);
+    // Default replacement character is the Unicode replacement character.
+    expected = [
+      unicodeReplacementCharacterRune,
+      unicodeReplacementCharacterRune,
+      120,
+      46,
+      32,
+      120,
+      10
+    ];
+    Expect.listEquals(expected, text.codeUnits);
+    text = new File(name).readAsStringSync(encoding: latin1);
+    expected = [206, 187, 120, 46, 32, 120, 10];
+    Expect.equals(7, text.length);
+    Expect.listEquals(expected, text.codeUnits);
+  }
+
+  static void testReadAsTextSyncEmptyFile() {
+    var name = getFilename("empty_file");
+    var text = new File(name).readAsStringSync();
+    Expect.equals(0, text.length);
+  }
+
+  static void testReadAsLines() {
+    asyncTestStarted();
+    var name = getFilename("fixed_length_file");
+    var f = new File(name);
+    f.readAsLines(encoding: utf8).then((lines) {
+      Expect.equals(1, lines.length);
+      var line = lines[0];
+      Expect.isTrue(line.endsWith("42 bytes."));
+      Expect.equals(42, line.length);
+      asyncTestDone("testReadAsLines");
+    });
+  }
+
+  static void testReadAsLinesSync() {
+    var name = getFilename("fixed_length_file");
+    var lines = new File(name).readAsLinesSync();
+    Expect.equals(1, lines.length);
+    var line = lines[0];
+    Expect.isTrue(line.endsWith("42 bytes."));
+    Expect.equals(42, line.length);
+    name = getFilename("readline_test1.dat");
+    lines = new File(name).readAsLinesSync();
+    Expect.equals(10, lines.length);
+  }
+
+  static void testReadAsErrors() {
+    asyncTestStarted();
+    var f = new File('.');
+    Expect.throws(f.readAsBytesSync, (e) => e is FileSystemException);
+    Expect.throws(f.readAsStringSync, (e) => e is FileSystemException);
+    Expect.throws(f.readAsLinesSync, (e) => e is FileSystemException);
+    var readAsBytesFuture = f.readAsBytes();
+    readAsBytesFuture
+        .then((bytes) => Expect.fail("no bytes expected"))
+        .catchError((e) {
+      var readAsStringFuture = f.readAsString(encoding: utf8);
+      readAsStringFuture
+          .then((text) => Expect.fail("no text expected"))
+          .catchError((e) {
+        var readAsLinesFuture = f.readAsLines(encoding: utf8);
+        readAsLinesFuture
+            .then((lines) => Expect.fail("no lines expected"))
+            .catchError((e) {
+          asyncTestDone("testReadAsLines");
+        });
+      });
+    });
+  }
+
+  static void testLastModified() {
+    asyncTestStarted();
+    new File(Platform.executable).lastModified().then((modified) {
+      Expect.isTrue(modified is DateTime);
+      Expect.isTrue(modified.isBefore(new DateTime.now()));
+      asyncTestDone("testLastModified");
+    });
+  }
+
+  static void testLastAccessed() {
+    asyncTestStarted();
+    new File(Platform.executable).lastAccessed().then((accessed) {
+      Expect.isTrue(accessed is DateTime);
+      Expect.isTrue(accessed.isBefore(new DateTime.now()));
+      asyncTestDone("testLastAccessed");
+    });
+  }
+
+  static void testDoubleAsyncOperation() {
+    asyncTestStarted();
+    var file = new File(Platform.executable).openSync();
+    var completer = new Completer();
+    int done = 0;
+    bool error = false;
+    void getLength() {
+      file.length().catchError((e) {
+        error = true;
+      }).whenComplete(() {
+        if (++done == 2) {
+          asyncTestDone("testDoubleAsyncOperation");
+          Expect.isTrue(error);
+          file.lengthSync();
+          file.closeSync();
+        }
+      });
+    }
+
+    getLength();
+    getLength();
+    Expect.throws(() => file.lengthSync());
+  }
+
+  static void testLastModifiedSync() {
+    var modified = new File(Platform.executable).lastModifiedSync();
+    Expect.isTrue(modified is DateTime);
+    Expect.isTrue(modified.isBefore(new DateTime.now()));
+  }
+
+  static void testLastAccessedSync() {
+    var accessed = new File(Platform.executable).lastAccessedSync();
+    Expect.isTrue(accessed is DateTime);
+    Expect.isTrue(accessed.isBefore(new DateTime.now()));
+  }
+
+  static void testLastModifiedSyncDirectory() {
+    Directory tmp = tempDirectory.createTempSync('file_last_modified_test_');
+    String dirPath = '${tmp.path}/dir';
+    new Directory(dirPath).createSync();
+    try {
+      new File(dirPath).lastModifiedSync();
+      Expect.fail('Expected operation to throw');
+    } catch (e) {
+      if (e is! FileSystemException) {
+        print(e);
+      }
+      Expect.isTrue(e is FileSystemException);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  static void testLastAccessedSyncDirectory() {
+    Directory tmp = tempDirectory.createTempSync('file_last_accessed_test_');
+    String dirPath = '${tmp.path}/dir';
+    new Directory(dirPath).createSync();
+    try {
+      new File(dirPath).lastAccessedSync();
+      Expect.fail('Expected operation to throw');
+    } catch (e) {
+      if (e is! FileSystemException) {
+        print(e);
+      }
+      Expect.isTrue(e is FileSystemException);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  static void testSetLastModifiedSync() {
+    String newFilePath = '${tempDirectory.path}/set_last_modified_sync_test';
+    File file = new File(newFilePath);
+    file.createSync();
+    DateTime modifiedTime = new DateTime(2016, 1, 1);
+    file.setLastModifiedSync(modifiedTime);
+    FileStat stat = file.statSync();
+    Expect.equals(2016, stat.modified.year);
+    Expect.equals(1, stat.modified.month);
+    Expect.equals(1, stat.modified.day);
+  }
+
+  static testSetLastModified() async {
+    asyncTestStarted();
+    String newFilePath = '${tempDirectory.path}/set_last_modified_test';
+    File file = new File(newFilePath);
+    file.createSync();
+    DateTime modifiedTime = new DateTime(2016, 1, 1);
+    await file.setLastModified(modifiedTime);
+    FileStat stat = await file.stat();
+    Expect.equals(2016, stat.modified.year);
+    Expect.equals(1, stat.modified.month);
+    Expect.equals(1, stat.modified.day);
+    asyncTestDone("testSetLastModified");
+  }
+
+  static void testSetLastModifiedSyncDirectory() {
+    Directory tmp = tempDirectory.createTempSync('file_last_modified_test_');
+    String dirPath = '${tmp.path}/dir';
+    new Directory(dirPath).createSync();
+    try {
+      DateTime modifiedTime = new DateTime(2016, 1, 1);
+      new File(dirPath).setLastModifiedSync(modifiedTime);
+      Expect.fail('Expected operation to throw');
+    } catch (e) {
+      if (e is! FileSystemException) {
+        print(e);
+      }
+      Expect.isTrue(e is FileSystemException);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  static void testSetLastAccessedSync() {
+    String newFilePath = '${tempDirectory.path}/set_last_accessed_sync_test';
+    File file = new File(newFilePath);
+    file.createSync();
+    DateTime accessedTime = new DateTime(2016, 1, 1);
+    file.setLastAccessedSync(accessedTime);
+    FileStat stat = file.statSync();
+    Expect.equals(2016, stat.accessed.year);
+    Expect.equals(1, stat.accessed.month);
+    Expect.equals(1, stat.accessed.day);
+  }
+
+  static testSetLastAccessed() async {
+    asyncTestStarted();
+    String newFilePath = '${tempDirectory.path}/set_last_accessed_test';
+    File file = new File(newFilePath);
+    file.createSync();
+    DateTime accessedTime = new DateTime(2016, 1, 1);
+    await file.setLastAccessed(accessedTime);
+    FileStat stat = await file.stat();
+    Expect.equals(2016, stat.accessed.year);
+    Expect.equals(1, stat.accessed.month);
+    Expect.equals(1, stat.accessed.day);
+    asyncTestDone("testSetLastAccessed");
+  }
+
+  static void testSetLastAccessedSyncDirectory() {
+    Directory tmp = tempDirectory.createTempSync('file_last_accessed_test_');
+    String dirPath = '${tmp.path}/dir';
+    new Directory(dirPath).createSync();
+    try {
+      DateTime accessedTime = new DateTime(2016, 1, 1);
+      new File(dirPath).setLastAccessedSync(accessedTime);
+      Expect.fail('Expected operation to throw');
+    } catch (e) {
+      if (e is! FileSystemException) {
+        print(e);
+      }
+      Expect.isTrue(e is FileSystemException);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  }
+
+  // Test that opens the same file for writing then for appending to test
+  // that the file is not truncated when opened for appending.
+  static void testAppend() {
+    asyncTestStarted();
+    var file = new File('${tempDirectory.path}/out_append');
+    file.open(mode: FileMode.write).then((openedFile) {
+      openedFile.writeString("asdf").then((ignore) {
+        openedFile.close().then((ignore) {
+          file.open(mode: FileMode.append).then((openedFile) {
+            openedFile.length().then((length) {
+              Expect.equals(4, length);
+              openedFile.writeString("asdf").then((ignore) {
+                openedFile.length().then((length) {
+                  Expect.equals(8, length);
+                  openedFile.close().then((ignore) {
+                    file.delete().then((ignore) {
+                      file.exists().then((exists) {
+                        Expect.isFalse(exists);
+                        asyncTestDone("testAppend");
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testAppendSync() {
+    var file = new File('${tempDirectory.path}/out_append_sync');
+    var openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeStringSync("asdf");
+    Expect.equals(4, openedFile.lengthSync());
+    openedFile.closeSync();
+    openedFile = file.openSync(mode: FileMode.write);
+    openedFile.setPositionSync(4);
+    openedFile.writeStringSync("asdf");
+    Expect.equals(8, openedFile.lengthSync());
+    openedFile.closeSync();
+    file.deleteSync();
+    Expect.isFalse(file.existsSync());
+  }
+
+  static void testWriteStringUtf8() {
+    asyncTestStarted();
+    var file = new File('${tempDirectory.path}/out_write_string');
+    var string = new String.fromCharCodes([0x192]);
+    file.open(mode: FileMode.write).then((openedFile) {
+      openedFile.writeString(string).then((_) {
+        openedFile.length().then((l) {
+          Expect.equals(2, l);
+          openedFile.close().then((_) {
+            file.open(mode: FileMode.append).then((openedFile) {
+              openedFile.setPosition(2).then((_) {
+                openedFile.writeString(string).then((_) {
+                  openedFile.length().then((l) {
+                    Expect.equals(4, l);
+                    openedFile.close().then((_) {
+                      file.readAsString().then((readBack) {
+                        Expect.stringEquals(readBack, '$string$string');
+                        file.delete().then((_) {
+                          file.exists().then((e) {
+                            Expect.isFalse(e);
+                            asyncTestDone("testWriteStringUtf8");
+                          });
+                        });
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  }
+
+  static void testWriteStringUtf8Sync() {
+    var file = new File('${tempDirectory.path}/out_write_string_sync');
+    var string = new String.fromCharCodes([0x192]);
+    var openedFile = file.openSync(mode: FileMode.write);
+    openedFile.writeStringSync(string);
+    Expect.equals(2, openedFile.lengthSync());
+    openedFile.closeSync();
+    openedFile = file.openSync(mode: FileMode.append);
+    openedFile.setPositionSync(2);
+    openedFile.writeStringSync(string);
+    Expect.equals(4, openedFile.lengthSync());
+    openedFile.closeSync();
+    var readBack = file.readAsStringSync();
+    Expect.stringEquals(readBack, '$string$string');
+    file.deleteSync();
+    Expect.isFalse(file.existsSync());
+  }
+
+  static void testRename({required bool targetExists}) {
+    lift(Function f) => (futureValue) => futureValue.then((value) => f(value));
+    asyncTestStarted();
+
+    String source = join(tempDirectory.path, 'rename_${targetExists}_source');
+    String dest = join(tempDirectory.path, 'rename_${targetExists}_dest');
+    var file = new File(source);
+    var newfile = new File(dest);
+    file
+        .create()
+        .then((_) => targetExists ? newfile.create() : new Future.value(null))
+        .then((_) => file.rename(dest))
+        .then((_) => lift(Expect.isFalse)(file.exists()))
+        .then((_) => lift(Expect.isTrue)(newfile.exists()))
+        .then((_) => newfile.delete())
+        .then((_) => lift(Expect.isFalse)(newfile.exists()))
+        .then((_) {
+      if (Platform.operatingSystem != "windows") {
+        new Link(source).create(dest).then((_) => file.rename("xxx")).then((_) {
+          throw "Rename of broken link succeeded";
+        }).catchError((e) {
+          Expect.isTrue(e is FileSystemException);
+          asyncTestDone("testRename$targetExists");
+        });
+      } else {
+        asyncTestDone("testRename$targetExists");
+      }
+    });
+  }
+
+  static void testRenameSync({required bool targetExists}) {
+    String source = join(tempDirectory.path, 'rename_source');
+    String dest = join(tempDirectory.path, 'rename_dest');
+    var file = new File(source);
+    var newfile = new File(dest);
+    file.createSync();
+    if (targetExists) {
+      newfile.createSync();
+    }
+    var result = file.renameSync(dest);
+    Expect.isFalse(file.existsSync());
+    Expect.isTrue(newfile.existsSync());
+    Expect.equals(result.path, newfile.path);
+    newfile.deleteSync();
+    Expect.isFalse(newfile.existsSync());
+    if (Platform.operatingSystem != "windows") {
+      var brokenLink = new Link(source);
+      brokenLink.createSync(dest);
+      Expect.throws(() => file.renameSync('xxx'));
+      brokenLink.deleteSync();
+    }
+  }
+
+  static String getFilename(String path) {
+    return Platform.script.resolve(path).toFilePath();
+  }
+
+  // Main test entrypoint.
+  static testMain() {
+    asyncStart();
+
+    testRead();
+    testReadSync();
+    testReadStream();
+    testLengthSync();
+    testPositionSync();
+    testOpenDirectoryAsFile();
+    testOpenDirectoryAsFileSync();
+    testReadAsBytesSync();
+    testReadAsBytesSyncEmptyFile();
+    testReadAsTextSync();
+    testReadAsTextSyncEmptyFile();
+    testReadAsLinesSync();
+    testLastModifiedSync();
+    testLastAccessedSync();
+
+    createTempDirectory(() {
+      testLength();
+      testLengthSyncDirectory();
+      testReadWrite();
+      testReadWriteSync();
+      testReadWriteNoArgsSync();
+      testReadWriteStream();
+      testReadEmptyFileSync();
+      testReadEmptyFile();
+      testReadWriteStreamLargeFile();
+      testReadAsBytes();
+      testReadAsBytesEmptyFile();
+      testReadAsText();
+      testReadAsTextEmptyFile();
+      testReadAsLines();
+      testReadAsErrors();
+      testPosition();
+      testTruncate();
+      testTruncateSync();
+      testReadInto();
+      testReadIntoSync();
+      testWriteFrom();
+      testWriteFromSync();
+      testCloseException();
+      testCloseExceptionStream();
+      testBufferOutOfBoundsException();
+      testAppend();
+      testAppendSync();
+      testWriteAppend();
+      testOutputStreamWriteAppend();
+      testOutputStreamWriteString();
+      testWriteVariousLists();
+      testWriteFromOffset();
+      testDirectory();
+      testDirectorySync();
+      testWriteStringUtf8();
+      testWriteStringUtf8Sync();
+      testRename(targetExists: false);
+      testRenameSync(targetExists: false);
+      testRename(targetExists: true);
+      testRenameSync(targetExists: true);
+      testLastModified();
+      testLastAccessed();
+      testLastModifiedSyncDirectory();
+      testLastAccessedSyncDirectory();
+      testSetLastModified();
+      testSetLastModifiedSync();
+      testSetLastModifiedSyncDirectory();
+      testSetLastAccessed();
+      testSetLastAccessedSync();
+      testSetLastAccessedSyncDirectory();
+      testDoubleAsyncOperation();
+      asyncEnd();
+    });
+  }
+}
+
+main() {
+  FileTest.testMain();
+}
diff --git a/tests/standalone/io/file_test.txt b/tests/standalone/io/file_test.txt
new file mode 100644
index 0000000..4c2c0d1
--- /dev/null
+++ b/tests/standalone/io/file_test.txt
@@ -0,0 +1,63 @@
+// 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.
+
+#include "bin/file.h"
+#include "platform/assert.h"
+#include "platform/globals.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+namespace bin {
+
+// Helper method to be able to run the test from the runtime
+// directory, or the top directory.
+static const char* GetFileName(const char* name) {
+  if (File::Exists(name)) {
+    return name;
+  } else {
+    static const int kRuntimeLength = strlen("runtime/");
+    return name + kRuntimeLength;
+  }
+}
+
+
+TEST_CASE(Read) {
+  const char* kFilename = GetFileName("runtime/bin/file_test.cc");
+  File* file = File::Open(kFilename, File::kRead);
+  EXPECT(file != NULL);
+  char buffer[16];
+  buffer[0] = '\0';
+  EXPECT(file->ReadFully(buffer, 13));  // ReadFully returns true.
+  buffer[13] = '\0';
+  EXPECT_STREQ("// Copyright ", buffer);
+  EXPECT(!file->WriteByte(1));  // Cannot write to a read-only file.
+  file->Release();
+}
+
+
+TEST_CASE(FileLength) {
+  const char* kFilename =
+      GetFileName("runtime/tests/vm/data/fixed_length_file");
+  File* file = File::Open(kFilename, File::kRead);
+  EXPECT(file != NULL);
+  EXPECT_EQ(42, file->Length());
+  file->Release();
+}
+
+
+TEST_CASE(FilePosition) {
+  char buf[42];
+  const char* kFilename =
+      GetFileName("runtime/tests/vm/data/fixed_length_file");
+  File* file = File::Open(kFilename, File::kRead);
+  EXPECT(file != NULL);
+  EXPECT(file->ReadFully(buf, 12));
+  EXPECT_EQ(12, file->Position());
+  EXPECT(file->ReadFully(buf, 6));
+  EXPECT_EQ(18, file->Position());
+  file->Release();
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/tests/standalone/io/file_typed_data_test.dart b/tests/standalone/io/file_typed_data_test.dart
new file mode 100644
index 0000000..1e46e49
--- /dev/null
+++ b/tests/standalone/io/file_typed_data_test.dart
@@ -0,0 +1,366 @@
+// 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 program for testing file I/O.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testWriteInt8ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Int8List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  Int8List list = new Int8List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Int8List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(list, 0, LIST_LENGTH);
+    }).then((raf) {
+      return raf.writeFrom(view, 0, VIEW_LENGTH);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      Expect.listEquals(expected, content);
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteUint8ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Uint8List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  Uint8List list = new Uint8List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Uint8List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(list, 0, LIST_LENGTH);
+    }).then((raf) {
+      return raf.writeFrom(view, 0, VIEW_LENGTH);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      Expect.listEquals(expected, content);
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteUint8ClampedListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Uint8ClampedList.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  Uint8ClampedList list = new Uint8ClampedList(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view = new Uint8ClampedList.view(
+      list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(list, 0, LIST_LENGTH);
+    }).then((raf) {
+      return raf.writeFrom(view, 0, VIEW_LENGTH);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      Expect.listEquals(expected, content);
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteInt16ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Int16List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Int16List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Int16List.bytesPerElement;
+  var list = new Int16List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Int16List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Int16List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteUint16ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Uint16List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Uint16List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Uint16List.bytesPerElement;
+  var list = new Uint16List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Uint16List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Uint16List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteInt32ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Int32List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Int32List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Int32List.bytesPerElement;
+  var list = new Int32List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Int32List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Int32List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteUint32ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Int32List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Int32List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Int32List.bytesPerElement;
+  var list = new Uint32List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Uint32List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Uint32List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteInt64ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Int64List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Int64List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Int64List.bytesPerElement;
+  var list = new Int64List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Int64List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Int64List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+void testWriteUint64ListAndView() {
+  asyncStart();
+  const int LIST_LENGTH = 8;
+  const int LIST_LENGTH_IN_BYTES = LIST_LENGTH * Uint64List.bytesPerElement;
+  const int OFFSET_IN_BYTES_FOR_VIEW = 2 * Uint64List.bytesPerElement;
+  const int VIEW_LENGTH = 4;
+  const int VIEW_LENGTH_IN_BYTES = VIEW_LENGTH * Uint64List.bytesPerElement;
+  var list = new Uint64List(LIST_LENGTH);
+  for (int i = 0; i < LIST_LENGTH; i++) list[i] = i;
+  var view =
+      new Uint64List.view(list.buffer, OFFSET_IN_BYTES_FOR_VIEW, VIEW_LENGTH);
+
+  Directory.systemTemp.createTemp('dart_file_typed_data').then((temp) {
+    var file = new File("${temp.path}/test");
+    file.open(mode: FileMode.write).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(list.buffer), 0, LIST_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.writeFrom(
+          new Uint8List.view(
+              view.buffer, view.offsetInBytes, view.lengthInBytes),
+          0,
+          VIEW_LENGTH_IN_BYTES);
+    }).then((raf) {
+      return raf.close();
+    }).then((_) {
+      var expected = [];
+      expected.addAll(list);
+      expected.addAll(view);
+      var content = file.readAsBytesSync();
+      var typed_data_content = new Uint8List(content.length);
+      for (int i = 0; i < content.length; i++) {
+        typed_data_content[i] = content[i];
+      }
+      Expect.listEquals(
+          expected, new Uint64List.view(typed_data_content.buffer));
+      temp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+  });
+}
+
+main() {
+  testWriteInt8ListAndView();
+  testWriteUint8ListAndView();
+  testWriteUint8ClampedListAndView();
+  testWriteInt16ListAndView();
+  testWriteUint16ListAndView();
+  testWriteInt32ListAndView();
+  testWriteUint32ListAndView();
+  testWriteInt64ListAndView();
+  testWriteUint64ListAndView();
+}
diff --git a/tests/standalone/io/file_uri_test.dart b/tests/standalone/io/file_uri_test.dart
new file mode 100644
index 0000000..3001b70
--- /dev/null
+++ b/tests/standalone/io/file_uri_test.dart
@@ -0,0 +1,44 @@
+// 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:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testFromUri() {
+  asyncStart();
+  Directory originalWorkingDirectory = Directory.current;
+  Directory.systemTemp.createTemp('file_uri').then((temp) {
+    String filename = temp.path + '/from_uri';
+    Uri fileUri = new Uri.file(filename);
+    File file = new File.fromUri(fileUri);
+    Expect.isTrue(fileUri.isAbsolute);
+    Expect.isTrue(fileUri.path.startsWith('/'));
+    file.createSync();
+    Expect.isTrue(new File.fromUri(fileUri).existsSync());
+    Expect.isTrue(new File.fromUri(Uri.base.resolveUri(fileUri)).existsSync());
+    Directory.current = temp.path;
+    Expect.isTrue(new File.fromUri(Uri.parse('from_uri')).existsSync());
+    Expect.isTrue(new File.fromUri(Uri.base.resolve('from_uri')).existsSync());
+    Directory.current = originalWorkingDirectory;
+    file.deleteSync();
+    temp.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+void testFromUriUnsupported() {
+  Expect.throwsUnsupportedError(
+      () => new File.fromUri(Uri.parse('http://localhost:8080/index.html')));
+  Expect.throwsUnsupportedError(
+      () => new File.fromUri(Uri.parse('ftp://localhost/tmp/xxx')));
+  Expect.throwsUnsupportedError(
+      () => new File.fromUri(Uri.parse('name#fragment')));
+}
+
+void main() {
+  testFromUri();
+  testFromUriUnsupported();
+}
diff --git a/tests/standalone/io/file_windows_test.dart b/tests/standalone/io/file_windows_test.dart
new file mode 100644
index 0000000..d0e2ddc
--- /dev/null
+++ b/tests/standalone/io/file_windows_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 'dart:io';
+
+import "package:expect/expect.dart";
+
+void testDeleteLongPathPrefix() {
+  var dir = Directory.systemTemp.createTempSync('dart_file_win');
+  var dirPath = "\\\\?\\${dir.path}";
+  var subPath = dirPath;
+  for (int i = 0; i < 16; i++) {
+    subPath += "\\a-long-path-segment";
+    dir = new Directory(subPath)..createSync();
+  }
+  Expect.isTrue(dir.path.length > 256);
+  var prefixDir = new Directory(dirPath);
+  Expect.isTrue(prefixDir.existsSync());
+  prefixDir.deleteSync(recursive: true);
+  Expect.isFalse(dir.existsSync());
+  Expect.isFalse(prefixDir.existsSync());
+}
+
+void main() {
+  if (!Platform.isWindows) return;
+  testDeleteLongPathPrefix();
+}
diff --git a/tests/standalone/io/file_write_as_test.dart b/tests/standalone/io/file_write_as_test.dart
new file mode 100644
index 0000000..ce13ebd
--- /dev/null
+++ b/tests/standalone/io/file_write_as_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.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+testWriteAsBytesSync(dir) {
+  var f = new File('${dir.path}/bytes_sync.txt');
+  var data = [50, 50, 50];
+  f.writeAsBytesSync(data);
+  Expect.listEquals(data, f.readAsBytesSync());
+  f.writeAsBytesSync(data, mode: FileMode.append, flush: true);
+  var expected = [50, 50, 50, 50, 50, 50];
+  Expect.listEquals(expected, f.readAsBytesSync());
+}
+
+testWriteAsStringSync(dir) {
+  var f = new File('${dir.path}/string_sync.txt');
+  var data = 'asdf';
+  f.writeAsStringSync(data);
+  Expect.equals(data, f.readAsStringSync());
+  f.writeAsStringSync(data, mode: FileMode.append, flush: true);
+  Expect.equals('$data$data', f.readAsStringSync());
+}
+
+Future testWriteAsBytes(dir) {
+  var completer = new Completer();
+  var f = new File('${dir.path}/bytes.txt');
+  var data = [50, 50, 50];
+  f.writeAsBytes(data).then((file) {
+    Expect.equals(f, file);
+    f.readAsBytes().then((bytes) {
+      Expect.listEquals(data, bytes);
+      f.writeAsBytes(data, mode: FileMode.append, flush: true).then((file) {
+        Expect.equals(f, file);
+        f.readAsBytes().then((bytes) {
+          var expected = [50, 50, 50, 50, 50, 50];
+          Expect.listEquals(expected, bytes);
+          completer.complete(true);
+        });
+      });
+    });
+  });
+  return completer.future;
+}
+
+Future testWriteAsString(dir) {
+  var completer = new Completer();
+  var f = new File('${dir.path}/strings.txt');
+  var data = 'asdf';
+  f.writeAsString(data).then((file) {
+    Expect.equals(f, file);
+    f.readAsString().then((str) {
+      Expect.equals(data, str);
+      f.writeAsString(data, mode: FileMode.append, flush: true).then((file) {
+        Expect.equals(f, file);
+        f.readAsString().then((str) {
+          Expect.equals('$data$data', str);
+          completer.complete(true);
+        });
+      });
+    });
+  });
+  return completer.future;
+}
+
+main() {
+  asyncStart();
+  var tempDir = Directory.systemTemp.createTempSync('dart_file_write_as');
+  testWriteAsBytesSync(tempDir);
+  testWriteAsStringSync(tempDir);
+  testWriteAsBytes(tempDir).then((_) {
+    return testWriteAsString(tempDir);
+  }).then((_) {
+    tempDir.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/file_write_only_test.dart b/tests/standalone/io/file_write_only_test.dart
new file mode 100644
index 0000000..b2ed67d
--- /dev/null
+++ b/tests/standalone/io/file_write_only_test.dart
@@ -0,0 +1,83 @@
+// 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 program for testing file I/O.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future withTempDir(String prefix, Future<void> test(Directory dir)) async {
+  var tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    await test(tempDir);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+void withTempDirSync(String prefix, void test(Directory dir)) {
+  var tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    test(tempDir);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+Future expectThrowsAsync(Future future, String message) {
+  return future.then((r) => Expect.fail(message)).catchError((e) {});
+}
+
+Future write(Directory dir) async {
+  var f = new File("${dir.path}${Platform.pathSeparator}write");
+  var raf = await f.open(mode: FileMode.writeOnly);
+  await raf.writeString('Hello');
+  await raf.setPosition(0);
+  await raf.writeString('Hello');
+  await raf.setPosition(0);
+  await expectThrowsAsync(
+      raf.readByte(), 'Read from write only file succeeded');
+  await raf.close();
+  raf = await f.open(mode: FileMode.writeOnlyAppend);
+  await raf.writeString('Hello');
+  await expectThrowsAsync(
+      raf.readByte(), 'Read from write only file succeeded');
+  await raf.setPosition(0);
+  await raf.writeString('Hello');
+  await raf.close();
+  Expect.equals(f.lengthSync(), 10);
+}
+
+void writeSync(Directory dir) {
+  var f = new File("${dir.path}${Platform.pathSeparator}write_sync");
+  var raf = f.openSync(mode: FileMode.writeOnly);
+  raf.writeStringSync('Hello');
+  raf.setPositionSync(0);
+  raf.writeStringSync('Hello');
+  raf.setPositionSync(0);
+  Expect.throws(() => raf.readByteSync());
+  raf.closeSync();
+}
+
+Future openWrite(Directory dir) async {
+  var f = new File("${dir.path}${Platform.pathSeparator}open_write");
+  var sink = f.openWrite(mode: FileMode.writeOnly);
+  sink.write('Hello');
+  await sink.close();
+  sink = await f.openWrite(mode: FileMode.writeOnlyAppend);
+  sink.write('Hello');
+  await sink.close();
+  Expect.equals(f.lengthSync(), 10);
+}
+
+main() async {
+  asyncStart();
+  await withTempDir('file_write_only_test_1_', write);
+  withTempDirSync('file_write_only_test_2_', writeSync);
+  await withTempDir('file_write_only_test_3_', openWrite);
+  asyncEnd();
+}
diff --git a/tests/standalone/io/fixed_length_file b/tests/standalone/io/fixed_length_file
new file mode 100644
index 0000000..52ce32d
--- /dev/null
+++ b/tests/standalone/io/fixed_length_file
@@ -0,0 +1 @@
+This file should contain exactly 42 bytes.
\ No newline at end of file
diff --git a/tests/standalone/io/fixed_length_file_out b/tests/standalone/io/fixed_length_file_out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/standalone/io/fixed_length_file_out
diff --git a/tests/standalone/io/fuzz_support.dart b/tests/standalone/io/fuzz_support.dart
new file mode 100644
index 0000000..4b9d59d
--- /dev/null
+++ b/tests/standalone/io/fuzz_support.dart
@@ -0,0 +1,58 @@
+// 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 fuzz_support;
+
+import 'package:expect/expect.dart';
+import 'dart:async';
+import 'dart:io';
+
+const typeMapping = const {
+  'null': null,
+  'int': 0,
+  'int64': -9000000000000000000,
+  'String': 'a',
+  'FileMode': FileMode.read,
+  'num': 0.50,
+  'List<int>': const [1, 2, 3],
+  'Map<String, int>': const {"a": 23}
+};
+
+typePermutations(int argCount) {
+  var result = [];
+  if (argCount == 2) {
+    typeMapping.forEach((k, v) {
+      typeMapping.forEach((k2, v2) {
+        result.add([v, v2]);
+      });
+    });
+  } else {
+    Expect.isTrue(argCount == 3);
+    typeMapping.forEach((k, v) {
+      typeMapping.forEach((k2, v2) {
+        typeMapping.forEach((k3, v3) {
+          result.add([v, v2, v3]);
+        });
+      });
+    });
+  }
+  return result;
+}
+
+// Perform sync operation and ignore all exceptions.
+doItSync(Function f) {
+  try {
+    f();
+  } catch (e) {}
+}
+
+// Perform async operation and transform the future for the operation
+// into a future that never fails by treating errors as normal
+// completion.
+Future doItAsync(FutureOr f()) {
+  // Ignore value and errors.
+  return new Future.delayed(Duration.zero, f)
+      .catchError((_) {})
+      .then((_) => true);
+}
diff --git a/tests/standalone/io/http_100_continue.dart b/tests/standalone/io/http_100_continue.dart
new file mode 100644
index 0000000..f0e18a5
--- /dev/null
+++ b/tests/standalone/io/http_100_continue.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import 'dart:convert';
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+void test(responseBytes, bodyLength) async {
+  fullRequest(bytes) {
+    var len = bytes.length;
+    return len > 4 &&
+        bytes[len - 4] == 13 &&
+        bytes[len - 3] == 10 &&
+        bytes[len - 2] == 13 &&
+        bytes[len - 1] == 10;
+  }
+
+  handleSocket(socket) async {
+    var bytes = [];
+    await for (var data in socket) {
+      bytes.addAll(data);
+      if (fullRequest(bytes)) {
+        socket.add(responseBytes);
+        socket.close();
+      }
+    }
+  }
+
+  var server = await ServerSocket.bind('127.0.0.1', 0);
+  server.listen(handleSocket);
+
+  var client = new HttpClient();
+  var request =
+      await client.getUrl(Uri.parse('http://127.0.0.1:${server.port}/'));
+  var response = await request.close();
+  Expect.equals(response.statusCode, 200);
+  Expect.equals(bodyLength,
+      (await response.fold<List<int>>(<int>[], (p, e) => p..addAll(e))).length);
+  server.close();
+}
+
+main() {
+  var r1 = '''
+HTTP/1.1 100 Continue\r
+\r
+HTTP/1.1 200 OK\r
+\r
+''';
+
+  var r2 = '''
+HTTP/1.1 100 Continue\r
+My-Header-1: hello\r
+My-Header-2: world\r
+\r
+HTTP/1.1 200 OK\r
+\r
+''';
+
+  var r3 = '''
+HTTP/1.1 100 Continue\r
+\r
+HTTP/1.1 200 OK\r
+Content-Length: 2\r
+\r
+AB''';
+
+  test(ascii.encode(r1), 0);
+  test(ascii.encode(r2), 0);
+  test(ascii.encode(r3), 2);
+}
diff --git a/tests/standalone/io/http_10_test.dart b/tests/standalone/io/http_10_test.dart
new file mode 100644
index 0000000..92ecc6f
--- /dev/null
+++ b/tests/standalone/io/http_10_test.dart
@@ -0,0 +1,215 @@
+// (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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:isolate";
+import "dart:io";
+import "package:expect/expect.dart";
+
+// Client makes a HTTP 1.0 request without connection keep alive. The
+// server sets a content length but still needs to close the
+// connection as there is no keep alive.
+void testHttp10NoKeepAlive() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNull(request.headers.value('content-length'));
+      Expect.equals(-1, request.contentLength);
+      var response = request.response;
+      response.contentLength = 1;
+      Expect.equals("1.0", request.protocolVersion);
+      response.done
+          .then((_) => Expect.fail("Unexpected response completion"))
+          .catchError((error) => Expect.isTrue(error is HttpException));
+      response.write("Z");
+      response.write("Z");
+      response.close();
+      Expect.throws(() {
+        response.write("x");
+      }, (e) => e is StateError);
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.write("GET / HTTP/1.0\r\n\r\n");
+
+        List<int> response = [];
+        socket.listen(response.addAll, onDone: () {
+          count++;
+          socket.destroy();
+          String s = new String.fromCharCodes(response).toLowerCase();
+          Expect.equals(-1, s.indexOf("keep-alive"));
+          if (count < 10) {
+            makeRequest();
+          } else {
+            server.close();
+          }
+        });
+      });
+    }
+
+    makeRequest();
+  });
+}
+
+// Client makes a HTTP 1.0 request and the server does not set a
+// content length so it has to close the connection to mark the end of
+// the response.
+void testHttp10ServerClose() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNull(request.headers.value('content-length'));
+      Expect.equals(-1, request.contentLength);
+      request.listen((_) {}, onDone: () {
+        var response = request.response;
+        Expect.equals("1.0", request.protocolVersion);
+        response.write("Z");
+        response.close();
+      });
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.write("GET / HTTP/1.0\r\n");
+        socket.write("Connection: Keep-Alive\r\n\r\n");
+
+        List<int> response = [];
+        socket.listen(response.addAll,
+            onDone: () {
+              socket.destroy();
+              count++;
+              String s = new String.fromCharCodes(response).toLowerCase();
+              Expect.equals("z", s[s.length - 1]);
+              Expect.equals(-1, s.indexOf("content-length:"));
+              Expect.equals(-1, s.indexOf("keep-alive"));
+              if (count < 10) {
+                makeRequest();
+              } else {
+                server.close();
+              }
+            },
+            onError: (e) => print(e));
+      });
+    }
+
+    makeRequest();
+  });
+}
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server sets a content length so the persistent connection can be
+// used.
+void testHttp10KeepAlive() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNull(request.headers.value('content-length'));
+      Expect.equals(-1, request.contentLength);
+      var response = request.response;
+      response.contentLength = 1;
+      response.persistentConnection = true;
+      Expect.equals("1.0", request.protocolVersion);
+      response.write("Z");
+      response.close();
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      void sendRequest() {
+        socket.write("GET / HTTP/1.0\r\n");
+        socket.write("Connection: Keep-Alive\r\n\r\n");
+      }
+
+      List<int> response = [];
+      int count = 0;
+      socket.listen((d) {
+        response.addAll(d);
+        if (response[response.length - 1] == "Z".codeUnitAt(0)) {
+          String s = new String.fromCharCodes(response).toLowerCase();
+          Expect.isTrue(s.indexOf("\r\nconnection: keep-alive\r\n") > 0);
+          Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
+          count++;
+          if (count < 10) {
+            response = [];
+            sendRequest();
+          } else {
+            socket.close();
+          }
+        }
+      }, onDone: () {
+        socket.destroy();
+        server.close();
+      });
+      sendRequest();
+    });
+  });
+}
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server does not set a content length so it cannot honor connection
+// keep alive.
+void testHttp10KeepAliveServerCloses() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNull(request.headers.value('content-length'));
+      Expect.equals(-1, request.contentLength);
+      var response = request.response;
+      Expect.equals("1.0", request.protocolVersion);
+      response.write("Z");
+      response.close();
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.write("GET / HTTP/1.0\r\n");
+        socket.write("Connection: Keep-Alive\r\n\r\n");
+
+        List<int> response = [];
+        socket.listen(response.addAll, onDone: () {
+          socket.destroy();
+          count++;
+          String s = new String.fromCharCodes(response).toLowerCase();
+          Expect.equals("z", s[s.length - 1]);
+          Expect.equals(-1, s.indexOf("content-length"));
+          Expect.equals(-1, s.indexOf("connection"));
+          if (count < 10) {
+            makeRequest();
+          } else {
+            server.close();
+          }
+        });
+      });
+    }
+
+    makeRequest();
+  });
+}
+
+void main() {
+  testHttp10NoKeepAlive();
+  testHttp10ServerClose();
+  testHttp10KeepAlive();
+  testHttp10KeepAliveServerCloses();
+}
diff --git a/tests/standalone/io/http_advanced_test.dart b/tests/standalone/io/http_advanced_test.dart
new file mode 100644
index 0000000..87553d9
--- /dev/null
+++ b/tests/standalone/io/http_advanced_test.dart
@@ -0,0 +1,423 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+class IsolatedHttpServer {
+  IsolatedHttpServer() : _statusPort = new ReceivePort();
+
+  void setServerStartedHandler(void startedCallback(int port)) {
+    _startedCallback = startedCallback;
+  }
+
+  void start() {
+    ReceivePort receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startIsolatedHttpServer, receivePort.sendPort);
+    receivePort.first.then((port) {
+      _serverPort = port;
+
+      // Send server start message to the server.
+      var command = new IsolatedHttpServerCommand.start();
+      port.send([command, _statusPort.sendPort]);
+    });
+
+    // Handle status messages from the server.
+    _statusPort.listen((var status) {
+      if (status.isStarted) {
+        _startedCallback(status.port);
+      }
+    });
+  }
+
+  void shutdown() {
+    // Send server stop message to the server.
+    _serverPort
+        .send([new IsolatedHttpServerCommand.stop(), _statusPort.sendPort]);
+    _statusPort.close();
+  }
+
+  void chunkedEncoding() {
+    // Send chunked encoding message to the server.
+    _serverPort.send([
+      new IsolatedHttpServerCommand.chunkedEncoding(),
+      _statusPort.sendPort
+    ]);
+  }
+
+  ReceivePort _statusPort; // Port for receiving messages from the server.
+  late SendPort _serverPort; // Port for sending messages to the server.
+  var _startedCallback;
+}
+
+class IsolatedHttpServerCommand {
+  static const START = 0;
+  static const STOP = 1;
+  static const CHUNKED_ENCODING = 2;
+
+  IsolatedHttpServerCommand.start() : _command = START;
+  IsolatedHttpServerCommand.stop() : _command = STOP;
+  IsolatedHttpServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING;
+
+  bool get isStart => _command == START;
+  bool get isStop => _command == STOP;
+  bool get isChunkedEncoding => _command == CHUNKED_ENCODING;
+
+  int _command;
+}
+
+class IsolatedHttpServerStatus {
+  static const STARTED = 0;
+  static const STOPPED = 1;
+  static const ERROR = 2;
+
+  IsolatedHttpServerStatus.started(this._port) : _state = STARTED;
+  IsolatedHttpServerStatus.stopped() : _state = STOPPED;
+  IsolatedHttpServerStatus.error() : _state = ERROR;
+
+  bool get isStarted => _state == STARTED;
+  bool get isStopped => _state == STOPPED;
+  bool get isError => _state == ERROR;
+
+  int get port => _port;
+
+  int _state;
+  int _port = 0;
+}
+
+void startIsolatedHttpServer(Object replyToObj) {
+  final replyTo = replyToObj as SendPort;
+  var server = new TestServer();
+  server.init();
+  replyTo.send(server.dispatchSendPort);
+}
+
+class TestServer {
+  // Return a 404.
+  void _notFoundHandler(HttpRequest request) {
+    var response = request.response;
+    response.statusCode = HttpStatus.notFound;
+    response.headers.set("Content-Type", "text/html; charset=UTF-8");
+    response.write("Page not found");
+    response.close();
+  }
+
+  // Check the "Host" header.
+  void _hostHandler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals(1, request.headers["Host"]!.length);
+    Expect.equals("www.dartlang.org:1234", request.headers["Host"]![0]);
+    Expect.equals("www.dartlang.org", request.headers.host);
+    Expect.equals(1234, request.headers.port);
+    response.statusCode = HttpStatus.ok;
+    response.close();
+  }
+
+  // Set the "Expires" header using the expires property.
+  void _expires1Handler(HttpRequest request) {
+    var response = request.response;
+    DateTime date = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+    response.headers.expires = date;
+    Expect.equals(date, response.headers.expires);
+    response.close();
+  }
+
+  // Set the "Expires" header.
+  void _expires2Handler(HttpRequest request) {
+    var response = request.response;
+    response.headers.set("Expires", "Fri, 11 Jun 1999 18:46:53 GMT");
+    DateTime date = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+    Expect.equals(date, response.headers.expires);
+    response.close();
+  }
+
+  void _contentType1Handler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals("text/html", request.headers.contentType!.value);
+    Expect.equals("text", request.headers.contentType!.primaryType);
+    Expect.equals("html", request.headers.contentType!.subType);
+    Expect.equals("utf-8", request.headers.contentType!.parameters["charset"]);
+
+    ContentType contentType = new ContentType("text", "html", charset: "utf-8");
+    response.headers.contentType = contentType;
+    response.close();
+  }
+
+  void _contentType2Handler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals("text/html", request.headers.contentType!.value);
+    Expect.equals("text", request.headers.contentType!.primaryType);
+    Expect.equals("html", request.headers.contentType!.subType);
+    Expect.equals("utf-8", request.headers.contentType!.parameters["charset"]);
+
+    response.headers
+        .set(HttpHeaders.contentTypeHeader, "text/html;  charset = utf-8");
+    response.close();
+  }
+
+  void _cookie1Handler(HttpRequest request) {
+    var response = request.response;
+
+    // No cookies passed with this request.
+    Expect.equals(0, request.cookies.length);
+
+    Cookie cookie1 = new Cookie("name1", "value1");
+    DateTime date = new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
+    cookie1.expires = date;
+    cookie1.domain = "www.example.com";
+    cookie1.httpOnly = true;
+    response.cookies.add(cookie1);
+    Cookie cookie2 = new Cookie("name2", "value2");
+    cookie2.maxAge = 100;
+    cookie2.domain = ".example.com";
+    cookie2.path = "/shop";
+    response.cookies.add(cookie2);
+    response.close();
+  }
+
+  void _cookie2Handler(HttpRequest request) {
+    var response = request.response;
+
+    // Two cookies passed with this request.
+    Expect.equals(2, request.cookies.length);
+    response.close();
+  }
+
+  void init() {
+    // Setup request handlers.
+    _requestHandlers["/host"] = _hostHandler;
+    _requestHandlers["/expires1"] = _expires1Handler;
+    _requestHandlers["/expires2"] = _expires2Handler;
+    _requestHandlers["/contenttype1"] = _contentType1Handler;
+    _requestHandlers["/contenttype2"] = _contentType2Handler;
+    _requestHandlers["/cookie1"] = _cookie1Handler;
+    _requestHandlers["/cookie2"] = _cookie2Handler;
+    _dispatchPort.listen(dispatch);
+  }
+
+  SendPort get dispatchSendPort => _dispatchPort.sendPort;
+
+  void dispatch(message) {
+    IsolatedHttpServerCommand command = message[0];
+    SendPort replyTo = message[1];
+    if (command.isStart) {
+      try {
+        HttpServer.bind("127.0.0.1", 0).then((server) {
+          _server = server;
+          _server.listen(_requestReceivedHandler);
+          replyTo.send(new IsolatedHttpServerStatus.started(_server.port));
+        });
+      } catch (e) {
+        replyTo.send(new IsolatedHttpServerStatus.error());
+      }
+    } else if (command.isStop) {
+      _server.close();
+      _dispatchPort.close();
+      replyTo.send(new IsolatedHttpServerStatus.stopped());
+    } else if (command.isChunkedEncoding) {
+      _chunkedEncoding = true;
+    }
+  }
+
+  void _requestReceivedHandler(HttpRequest request) {
+    var requestHandler = _requestHandlers[request.uri.path];
+    if (requestHandler != null) {
+      requestHandler(request);
+    } else {
+      _notFoundHandler(request);
+    }
+  }
+
+  late HttpServer _server; // HTTP server instance.
+  final _dispatchPort = new ReceivePort();
+  final _requestHandlers = {};
+  bool _chunkedEncoding = false;
+}
+
+Future testHost() {
+  Completer completer = new Completer();
+  IsolatedHttpServer server = new IsolatedHttpServer();
+  server.setServerStartedHandler((int port) {
+    HttpClient httpClient = new HttpClient();
+    httpClient.get("127.0.0.1", port, "/host").then((request) {
+      Expect.equals("127.0.0.1:$port", request.headers["host"]![0]);
+      request.headers.host = "www.dartlang.com";
+      Expect.equals("www.dartlang.com:$port", request.headers["host"]![0]);
+      Expect.equals("www.dartlang.com", request.headers.host);
+      Expect.equals(port, request.headers.port);
+      request.headers.port = 1234;
+      Expect.equals("www.dartlang.com:1234", request.headers["host"]![0]);
+      Expect.equals(1234, request.headers.port);
+      request.headers.port = HttpClient.defaultHttpPort;
+      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
+      Expect.equals("www.dartlang.com", request.headers["host"]![0]);
+      request.headers.set("Host", "www.dartlang.org");
+      Expect.equals("www.dartlang.org", request.headers.host);
+      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
+      request.headers.set("Host", "www.dartlang.org:");
+      Expect.equals("www.dartlang.org", request.headers.host);
+      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
+      request.headers.set("Host", "www.dartlang.org:1234");
+      Expect.equals("www.dartlang.org", request.headers.host);
+      Expect.equals(1234, request.headers.port);
+      return request.close();
+    }).then((response) {
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      response.listen((_) {}, onDone: () {
+        httpClient.close();
+        server.shutdown();
+        completer.complete(true);
+      });
+    });
+  });
+  server.start();
+  return completer.future;
+}
+
+Future testExpires() {
+  Completer completer = new Completer();
+  IsolatedHttpServer server = new IsolatedHttpServer();
+  server.setServerStartedHandler((int port) {
+    int responses = 0;
+    HttpClient httpClient = new HttpClient();
+
+    void processResponse(HttpClientResponse response) {
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      Expect.equals(
+          "Fri, 11 Jun 1999 18:46:53 GMT", response.headers["expires"]![0]);
+      Expect.equals(new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0),
+          response.headers.expires);
+      response.listen((_) {}, onDone: () {
+        responses++;
+        if (responses == 2) {
+          httpClient.close();
+          server.shutdown();
+          completer.complete(true);
+        }
+      });
+    }
+
+    httpClient
+        .get("127.0.0.1", port, "/expires1")
+        .then((request) => request.close())
+        .then(processResponse);
+    httpClient
+        .get("127.0.0.1", port, "/expires2")
+        .then((request) => request.close())
+        .then(processResponse);
+  });
+  server.start();
+  return completer.future;
+}
+
+Future testContentType() {
+  Completer completer = new Completer();
+  IsolatedHttpServer server = new IsolatedHttpServer();
+  server.setServerStartedHandler((int port) {
+    int responses = 0;
+    HttpClient httpClient = new HttpClient();
+
+    void processResponse(HttpClientResponse response) {
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      Expect.equals(
+          "text/html; charset=utf-8", response.headers.contentType.toString());
+      Expect.equals("text/html", response.headers.contentType!.value);
+      Expect.equals("text", response.headers.contentType!.primaryType);
+      Expect.equals("html", response.headers.contentType!.subType);
+      Expect.equals(
+          "utf-8", response.headers.contentType!.parameters["charset"]);
+      response.listen((_) {}, onDone: () {
+        responses++;
+        if (responses == 2) {
+          httpClient.close();
+          server.shutdown();
+          completer.complete(true);
+        }
+      });
+    }
+
+    httpClient.get("127.0.0.1", port, "/contenttype1").then((request) {
+      request.headers.contentType =
+          new ContentType("text", "html", charset: "utf-8");
+      return request.close();
+    }).then(processResponse);
+
+    httpClient.get("127.0.0.1", port, "/contenttype2").then((request) {
+      request.headers
+          .set(HttpHeaders.contentTypeHeader, "text/html;  charset = utf-8");
+      return request.close();
+    }).then(processResponse);
+  });
+  server.start();
+  return completer.future;
+}
+
+Future testCookies() {
+  Completer completer = new Completer();
+  IsolatedHttpServer server = new IsolatedHttpServer();
+  server.setServerStartedHandler((int port) {
+    int responses = 0;
+    HttpClient httpClient = new HttpClient();
+
+    httpClient
+        .get("127.0.0.1", port, "/cookie1")
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals(2, response.cookies.length);
+      response.cookies.forEach((cookie) {
+        if (cookie.name == "name1") {
+          Expect.equals("value1", cookie.value);
+          DateTime date =
+              new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
+          Expect.equals(date, cookie.expires);
+          Expect.equals("www.example.com", cookie.domain);
+          Expect.isTrue(cookie.httpOnly);
+        } else if (cookie.name == "name2") {
+          Expect.equals("value2", cookie.value);
+          Expect.equals(100, cookie.maxAge);
+          Expect.equals(".example.com", cookie.domain);
+          Expect.equals("/shop", cookie.path);
+        } else {
+          Expect.fail("Unexpected cookie");
+        }
+      });
+
+      response.listen((_) {}, onDone: () {
+        httpClient.get("127.0.0.1", port, "/cookie2").then((request) {
+          request.cookies.add(response.cookies[0]);
+          request.cookies.add(response.cookies[1]);
+          return request.close();
+        }).then((response) {
+          response.listen((_) {}, onDone: () {
+            httpClient.close();
+            server.shutdown();
+            completer.complete(true);
+          });
+        });
+      });
+    });
+  });
+  server.start();
+  return completer.future;
+}
+
+void main() {
+  testHost().then((_) {
+    return testExpires().then((_) {
+      return testContentType().then((_) {
+        return testCookies();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/http_auth_digest_test.dart b/tests/standalone/io/http_auth_digest_test.dart
new file mode 100644
index 0000000..e8d66fb
--- /dev/null
+++ b/tests/standalone/io/http_auth_digest_test.dart
@@ -0,0 +1,381 @@
+// 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:convert/convert.dart";
+import "package:crypto/crypto.dart";
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+class Server {
+  late HttpServer server;
+  int unauthCount = 0; // Counter of the 401 responses.
+  int successCount = 0; // Counter of the successful responses.
+  int nonceCount = 0; // Counter of use of current nonce.
+  var ha1;
+
+  static Future<Server> start(String? algorithm, String? qop,
+      {int? nonceStaleAfter, bool useNextNonce: false}) {
+    return new Server()._start(algorithm, qop, nonceStaleAfter, useNextNonce);
+  }
+
+  Future<Server> _start(String? serverAlgorithm, String? serverQop,
+      int? nonceStaleAfter, bool useNextNonce) {
+    Set ncs = new Set();
+    // Calculate ha1.
+    String realm = "test";
+    String username = "dart";
+    String password = "password";
+    var hasher = md5.convert("${username}:${realm}:${password}".codeUnits);
+    ha1 = hex.encode(hasher.bytes);
+
+    var nonce = "12345678"; // No need for random nonce in test.
+
+    var completer = new Completer<Server>();
+    HttpServer.bind("127.0.0.1", 0).then((s) {
+      server = s;
+      server.listen((HttpRequest request) {
+        sendUnauthorizedResponse(HttpResponse response, {stale: false}) {
+          response.statusCode = HttpStatus.unauthorized;
+          StringBuffer authHeader = new StringBuffer();
+          authHeader.write('Digest');
+          authHeader.write(', realm="$realm"');
+          authHeader.write(', nonce="$nonce"');
+          if (stale) authHeader.write(', stale="true"');
+          if (serverAlgorithm != null) {
+            authHeader.write(', algorithm=$serverAlgorithm');
+          }
+          authHeader.write(', domain="/digest/"');
+          if (serverQop != null) authHeader.write(', qop="$serverQop"');
+          response.headers.set(HttpHeaders.wwwAuthenticateHeader, authHeader);
+          unauthCount++;
+        }
+
+        var response = request.response;
+        if (request.headers[HttpHeaders.authorizationHeader] != null) {
+          Expect.equals(
+              1, request.headers[HttpHeaders.authorizationHeader]!.length);
+          String authorization =
+              request.headers[HttpHeaders.authorizationHeader]![0];
+          HeaderValue header =
+              HeaderValue.parse(authorization, parameterSeparator: ",");
+          if (header.value.toLowerCase() == "basic") {
+            sendUnauthorizedResponse(response);
+          } else if (!useNextNonce && nonceCount == nonceStaleAfter) {
+            nonce = "87654321";
+            nonceCount = 0;
+            sendUnauthorizedResponse(response, stale: true);
+          } else {
+            var uri = header.parameters["uri"];
+            var qop = header.parameters["qop"];
+            var cnonce = header.parameters["cnonce"];
+            var nc = header.parameters["nc"];
+            Expect.equals("digest", header.value.toLowerCase());
+            Expect.equals("dart", header.parameters["username"]);
+            Expect.equals(realm, header.parameters["realm"]);
+            Expect.equals("MD5", header.parameters["algorithm"]);
+            Expect.equals(nonce, header.parameters["nonce"]);
+            Expect.equals(request.uri.toString(), uri);
+            if (qop != null) {
+              // A server qop of auth-int is downgraded to none by the client.
+              Expect.equals("auth", serverQop);
+              Expect.equals("auth", header.parameters["qop"]);
+              Expect.isNotNull(cnonce);
+              Expect.isNotNull(nc);
+              Expect.isFalse(ncs.contains(nc));
+              ncs.add(nc);
+            } else {
+              Expect.isNull(cnonce);
+              Expect.isNull(nc);
+            }
+            Expect.isNotNull(header.parameters["response"]);
+
+            var hasher = md5.convert("${request.method}:${uri}".codeUnits);
+            var ha2 = hex.encode(hasher.bytes);
+
+            var x;
+            Digest digest;
+            if (qop == null || qop == "" || qop == "none") {
+              digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
+            } else {
+              digest = md5.convert(
+                  "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
+            }
+            Expect.equals(
+                hex.encode(digest.bytes), header.parameters["response"]);
+
+            successCount++;
+            nonceCount++;
+
+            // Add a bogus Authentication-Info for testing.
+            var info = 'rspauth="77180d1ab3d6c9de084766977790f482", '
+                'cnonce="8f971178", '
+                'nc=000002c74, '
+                'qop=auth';
+            if (useNextNonce && nonceCount == nonceStaleAfter) {
+              nonce = "abcdef01";
+              info += ', nextnonce="$nonce"';
+            }
+            response.headers.set("Authentication-Info", info);
+          }
+        } else {
+          sendUnauthorizedResponse(response);
+        }
+        response.close();
+      });
+      completer.complete(this);
+    });
+    return completer.future;
+  }
+
+  void shutdown() {
+    server.close();
+  }
+
+  int get port => server.port;
+}
+
+void testNoCredentials(String? algorithm, String? qop) {
+  Server.start(algorithm, qop).then((server) {
+    HttpClient client = new HttpClient();
+
+    // Add digest credentials which does not match the path requested.
+    client.addCredentials(Uri.parse("http://127.0.0.1:${server.port}/xxx"),
+        "test", new HttpClientDigestCredentials("dart", "password"));
+
+    // Add basic credentials for the path requested.
+    client.addCredentials(Uri.parse("http://127.0.0.1:${server.port}/digest"),
+        "test", new HttpClientBasicCredentials("dart", "password"));
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.unauthorized, response.statusCode);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/digest")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testCredentials(String? algorithm, String? qop) {
+  Server.start(algorithm, qop).then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        Expect.equals(1, response.headers["Authentication-Info"]?.length);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    client.addCredentials(Uri.parse("http://127.0.0.1:${server.port}/digest"),
+        "test", new HttpClientDigestCredentials("dart", "password"));
+
+    var futures = <Future>[];
+    for (int i = 0; i < 2; i++) {
+      String uriBase = "http://127.0.0.1:${server.port}/digest";
+      futures.add(makeRequest(Uri.parse(uriBase)));
+      futures.add(makeRequest(Uri.parse("$uriBase?querystring")));
+      futures.add(makeRequest(Uri.parse("$uriBase?querystring#fragment")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testAuthenticateCallback(String? algorithm, String? qop) {
+  Server.start(algorithm, qop).then((server) {
+    HttpClient client = new HttpClient();
+
+    client.authenticate = (Uri url, String scheme, String realm) {
+      Expect.equals("Digest", scheme);
+      Expect.equals("test", realm);
+      final completer = new Completer<bool>();
+      new Timer(const Duration(milliseconds: 10), () {
+        client.addCredentials(
+            Uri.parse("http://127.0.0.1:${server.port}/digest"),
+            "test",
+            new HttpClientDigestCredentials("dart", "password"));
+        completer.complete(true);
+      });
+      return completer.future;
+    };
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        Expect.equals(1, response.headers["Authentication-Info"]?.length);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/digest")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testStaleNonce() {
+  Server.start("MD5", "auth", nonceStaleAfter: 2).then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        Expect.equals(1, response.headers["Authentication-Info"]?.length);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    Uri uri = Uri.parse("http://127.0.0.1:${server.port}/digest");
+    var credentials = new HttpClientDigestCredentials("dart", "password");
+    client.addCredentials(uri, "test", credentials);
+
+    makeRequest(uri)
+        .then((_) => makeRequest(uri))
+        .then((_) => makeRequest(uri))
+        .then((_) => makeRequest(uri))
+        .then((_) {
+      Expect.equals(2, server.unauthCount);
+      Expect.equals(4, server.successCount);
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testNextNonce() {
+  Server.start("MD5", "auth", nonceStaleAfter: 2, useNextNonce: true)
+      .then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        Expect.equals(1, response.headers["Authentication-Info"]?.length);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    Uri uri = Uri.parse("http://127.0.0.1:${server.port}/digest");
+    var credentials = new HttpClientDigestCredentials("dart", "password");
+    client.addCredentials(uri, "test", credentials);
+
+    makeRequest(uri)
+        .then((_) => makeRequest(uri))
+        .then((_) => makeRequest(uri))
+        .then((_) => makeRequest(uri))
+        .then((_) {
+      Expect.equals(1, server.unauthCount);
+      Expect.equals(4, server.successCount);
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+// An Apache virtual directory configuration like this can be used for
+// running the local server tests.
+//
+//  <Directory "/usr/local/prj/website/digest/">
+//    AllowOverride None
+//    Order deny,allow
+//    Deny from all
+//    Allow from 127.0.0.0/255.0.0.0 ::1/128
+//    AuthType Digest
+//    AuthName "test"
+//    AuthDigestDomain /digest/
+//    AuthDigestAlgorithm MD5
+//    AuthDigestQop auth
+//    AuthDigestNonceLifetime 10
+//    AuthDigestProvider file
+//    AuthUserFile /usr/local/prj/apache/passwd/digest-passwd
+//    Require valid-user
+//  </Directory>
+//
+
+void testLocalServerDigest() {
+  int count = 0;
+  HttpClient client = new HttpClient();
+
+  Future makeRequest() {
+    return client
+        .getUrl(Uri.parse("http://127.0.0.1/digest/test"))
+        .then((HttpClientRequest request) => request.close())
+        .then((HttpClientResponse response) {
+      count++;
+      if (count % 100 == 0) print(count);
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      return response.fold(null, (x, y) {});
+    });
+  }
+
+  client.addCredentials(Uri.parse("http://127.0.0.1/digest"), "test",
+      new HttpClientDigestCredentials("dart", "password"));
+
+  client.authenticate = (Uri url, String scheme, String realm) {
+    client.addCredentials(Uri.parse("http://127.0.0.1/digest"), "test",
+        new HttpClientDigestCredentials("dart", "password"));
+    return new Future.value(true);
+  };
+
+  next() {
+    makeRequest().then((_) => next());
+  }
+
+  next();
+}
+
+main() {
+  testNoCredentials(null, null);
+  testNoCredentials("MD5", null);
+  testNoCredentials("MD5", "auth");
+  testCredentials(null, null);
+  testCredentials("MD5", null);
+  testCredentials("MD5", "auth");
+  testCredentials("MD5", "auth-int");
+  testAuthenticateCallback(null, null);
+  testAuthenticateCallback("MD5", null);
+  testAuthenticateCallback("MD5", "auth");
+  testAuthenticateCallback("MD5", "auth-int");
+  testStaleNonce();
+  testNextNonce();
+  // These teste are not normally run. They can be used for locally
+  // testing with another web server (e.g. Apache).
+  //testLocalServerDigest();
+}
diff --git a/tests/standalone/io/http_auth_test.dart b/tests/standalone/io/http_auth_test.dart
new file mode 100644
index 0000000..b1e5b31
--- /dev/null
+++ b/tests/standalone/io/http_auth_test.dart
@@ -0,0 +1,258 @@
+// 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:crypto/crypto.dart";
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:convert';
+
+class Server {
+  late HttpServer server;
+  bool passwordChanged = false;
+
+  Future<Server> start() {
+    var completer = new Completer<Server>();
+    HttpServer.bind("127.0.0.1", 0).then((s) {
+      server = s;
+      server.listen((HttpRequest request) {
+        var response = request.response;
+        if (request.uri.path == "/passwdchg") {
+          passwordChanged = true;
+          response.close();
+          return;
+        }
+        ;
+
+        String username;
+        String password;
+        if (request.uri.path == "/") {
+          username = "username";
+          password = "password";
+        } else {
+          username = request.uri.path.substring(1, 6);
+          password = request.uri.path.substring(1, 6);
+        }
+        if (passwordChanged) password = "${password}1";
+        if (request.headers[HttpHeaders.authorizationHeader] != null) {
+          Expect.equals(
+              1, request.headers[HttpHeaders.authorizationHeader]!.length);
+          String authorization =
+              request.headers[HttpHeaders.authorizationHeader]![0];
+          List<String> tokens = authorization.split(" ");
+          Expect.equals("Basic", tokens[0]);
+          String auth = base64.encode(utf8.encode("$username:$password"));
+          if (passwordChanged && auth != tokens[1]) {
+            response.statusCode = HttpStatus.unauthorized;
+            response.headers
+                .set(HttpHeaders.wwwAuthenticateHeader, "Basic, realm=realm");
+          } else {
+            Expect.equals(auth, tokens[1]);
+          }
+        } else {
+          response.statusCode = HttpStatus.unauthorized;
+          response.headers
+              .set(HttpHeaders.wwwAuthenticateHeader, "Basic, realm=realm");
+        }
+        response.close();
+      });
+      completer.complete(this);
+    });
+    return completer.future;
+  }
+
+  void shutdown() {
+    server.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<Server> setupServer() {
+  return new Server().start();
+}
+
+void testUrlUserInfo() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .getUrl(Uri.parse("http://username:password@127.0.0.1:${server.port}/"))
+        .then((request) => request.close())
+        .then((HttpClientResponse response) {
+      response.listen((_) {}, onDone: () {
+        server.shutdown();
+        client.close();
+      });
+    });
+  });
+}
+
+void testBasicNoCredentials() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.unauthorized, response.statusCode);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testBasicCredentials() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    for (int i = 0; i < 5; i++) {
+      client.addCredentials(Uri.parse("http://127.0.0.1:${server.port}/test$i"),
+          "realm", new HttpClientBasicCredentials("test$i", "test$i"));
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+    });
+  });
+}
+
+void testBasicAuthenticateCallback() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+    bool passwordChanged = false;
+
+    client.authenticate = (Uri url, String scheme, String realm) {
+      Expect.equals("Basic", scheme);
+      Expect.equals("realm", realm);
+      String username = url.path.substring(1, 6);
+      String password = url.path.substring(1, 6);
+      if (passwordChanged) password = "${password}1";
+      final completer = new Completer<bool>();
+      new Timer(const Duration(milliseconds: 10), () {
+        client.addCredentials(
+            url, realm, new HttpClientBasicCredentials(username, password));
+        completer.complete(true);
+      });
+      return completer.future;
+    };
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    List<Future> makeRequests() {
+      var futures = <Future>[];
+      for (int i = 0; i < 5; i++) {
+        futures.add(
+            makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+        futures.add(makeRequest(
+            Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+      }
+      return futures;
+    }
+
+    Future.wait(makeRequests()).then((_) {
+      makeRequest(Uri.parse("http://127.0.0.1:${server.port}/passwdchg"))
+          .then((_) {
+        passwordChanged = true;
+        Future.wait(makeRequests()).then((_) {
+          server.shutdown();
+          client.close();
+        });
+      });
+    });
+  });
+}
+
+void testLocalServerBasic() {
+  HttpClient client = new HttpClient();
+
+  client.authenticate = (Uri url, String scheme, String realm) {
+    client.addCredentials(Uri.parse("http://127.0.0.1/basic"), "test",
+        new HttpClientBasicCredentials("test", "test"));
+    return new Future.value(true);
+  };
+
+  client
+      .getUrl(Uri.parse("http://127.0.0.1/basic/test"))
+      .then((HttpClientRequest request) => request.close())
+      .then((HttpClientResponse response) {
+    Expect.equals(HttpStatus.ok, response.statusCode);
+    response.drain().then((_) {
+      client.close();
+    });
+  });
+}
+
+void testLocalServerDigest() {
+  HttpClient client = new HttpClient();
+
+  client.authenticate = (Uri url, String scheme, String realm) {
+    print("url: $url, scheme: $scheme, realm: $realm");
+    client.addCredentials(Uri.parse("http://127.0.0.1/digest"), "test",
+        new HttpClientDigestCredentials("test", "test"));
+    return new Future.value(true);
+  };
+
+  client
+      .getUrl(Uri.parse("http://127.0.0.1/digest/test"))
+      .then((HttpClientRequest request) => request.close())
+      .then((HttpClientResponse response) {
+    Expect.equals(HttpStatus.ok, response.statusCode);
+    response.drain().then((_) {
+      client.close();
+    });
+  });
+}
+
+main() {
+  testUrlUserInfo();
+  testBasicNoCredentials();
+  testBasicCredentials();
+  testBasicAuthenticateCallback();
+  // These teste are not normally run. They can be used for locally
+  // testing with another web server (e.g. Apache).
+  //testLocalServerBasic();
+  //testLocalServerDigest();
+}
diff --git a/tests/standalone/io/http_basic_test.dart b/tests/standalone/io/http_basic_test.dart
new file mode 100644
index 0000000..acc6eb5
--- /dev/null
+++ b/tests/standalone/io/http_basic_test.dart
@@ -0,0 +1,317 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// VMOptions=--trace_shutdown
+// VMOptions=--trace_shutdown --short_socket_read
+// VMOptions=--trace_shutdown --short_socket_write
+// VMOptions=--trace_shutdown --short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:isolate";
+import "dart:io";
+
+class TestServerMain {
+  TestServerMain();
+
+  void setServerStartedHandler(void startedCallback(int port)) {
+    _startedCallback = startedCallback;
+  }
+
+  void start([bool chunkedEncoding = false]) {
+    ReceivePort receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startTestServer, receivePort.sendPort);
+    receivePort.first.then((port) {
+      _serverPort = port;
+
+      if (chunkedEncoding) {
+        // Send chunked encoding message to the server.
+        port.send(
+            [new TestServerCommand.chunkedEncoding(), _statusPort.sendPort]);
+      }
+
+      // Send server start message to the server.
+      var command = new TestServerCommand.start();
+      port.send([command, _statusPort.sendPort]);
+    });
+
+    // Handle status messages from the server.
+    _statusPort.listen((var status) {
+      if (status.isStarted) {
+        _startedCallback(status.port);
+      }
+    });
+  }
+
+  void close() {
+    // Send server stop message to the server.
+    _serverPort.send([new TestServerCommand.stop(), _statusPort.sendPort]);
+    _statusPort.close();
+  }
+
+  final _statusPort =
+      new ReceivePort(); // Port for receiving messages from the server.
+  late SendPort _serverPort; // Port for sending messages to the server.
+  var _startedCallback;
+}
+
+class TestServerCommand {
+  static const START = 0;
+  static const STOP = 1;
+  static const CHUNKED_ENCODING = 2;
+
+  TestServerCommand.start() : _command = START;
+  TestServerCommand.stop() : _command = STOP;
+  TestServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING;
+
+  bool get isStart => _command == START;
+  bool get isStop => _command == STOP;
+  bool get isChunkedEncoding => _command == CHUNKED_ENCODING;
+
+  int _command;
+}
+
+class TestServerStatus {
+  static const STARTED = 0;
+  static const STOPPED = 1;
+  static const ERROR = 2;
+
+  TestServerStatus.started(this._port) : _state = STARTED;
+  TestServerStatus.stopped() : _state = STOPPED;
+  TestServerStatus.error() : _state = ERROR;
+
+  bool get isStarted => _state == STARTED;
+  bool get isStopped => _state == STOPPED;
+  bool get isError => _state == ERROR;
+
+  int get port => _port;
+
+  int _state;
+  int _port = 0;
+}
+
+void startTestServer(Object replyToObj) {
+  final replyTo = replyToObj as SendPort;
+  var server = new TestServer();
+  server.init();
+  replyTo.send(server.dispatchSendPort);
+}
+
+class TestServer {
+  // Echo the request content back to the response.
+  void _echoHandler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals("POST", request.method);
+    response.contentLength = request.contentLength;
+    request.cast<List<int>>().pipe(response);
+  }
+
+  // Echo the request content back to the response.
+  void _zeroToTenHandler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals("GET", request.method);
+    request.listen((_) {}, onDone: () {
+      response.write("01234567890");
+      response.close();
+    });
+  }
+
+  // Return a 404.
+  void _notFoundHandler(HttpRequest request) {
+    var response = request.response;
+    response.statusCode = HttpStatus.notFound;
+    response.headers.set("Content-Type", "text/html; charset=UTF-8");
+    response.write("Page not found");
+    response.close();
+  }
+
+  // Return a 301 with a custom reason phrase.
+  void _reasonForMovingHandler(HttpRequest request) {
+    var response = request.response;
+    response.statusCode = HttpStatus.movedPermanently;
+    response.reasonPhrase = "Don't come looking here any more";
+    response.close();
+  }
+
+  // Check the "Host" header.
+  void _hostHandler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals(1, request.headers["Host"]?.length);
+    Expect.equals("www.dartlang.org:1234", request.headers["Host"]![0]);
+    Expect.equals("www.dartlang.org", request.headers.host);
+    Expect.equals(1234, request.headers.port);
+    response.statusCode = HttpStatus.ok;
+    response.close();
+  }
+
+  void init() {
+    // Setup request handlers.
+    _requestHandlers["/echo"] = _echoHandler;
+    _requestHandlers["/0123456789"] = _zeroToTenHandler;
+    _requestHandlers["/reasonformoving"] = _reasonForMovingHandler;
+    _requestHandlers["/host"] = _hostHandler;
+    _dispatchPort.listen(dispatch);
+  }
+
+  SendPort get dispatchSendPort => _dispatchPort.sendPort;
+
+  void dispatch(var message) {
+    TestServerCommand command = message[0];
+    SendPort replyTo = message[1];
+    if (command.isStart) {
+      try {
+        HttpServer.bind("127.0.0.1", 0).then((server) {
+          _server = server;
+          _server.listen(_requestReceivedHandler);
+          replyTo.send(new TestServerStatus.started(_server.port));
+        });
+      } catch (e) {
+        replyTo.send(new TestServerStatus.error());
+      }
+    } else if (command.isStop) {
+      _server.close();
+      _dispatchPort.close();
+      replyTo.send(new TestServerStatus.stopped());
+    } else if (command.isChunkedEncoding) {
+      _chunkedEncoding = true;
+    }
+  }
+
+  void _requestReceivedHandler(HttpRequest request) {
+    var requestHandler = _requestHandlers[request.uri.path];
+    if (requestHandler != null) {
+      requestHandler(request);
+    } else {
+      _notFoundHandler(request);
+    }
+  }
+
+  late HttpServer _server; // HTTP server instance.
+  final ReceivePort _dispatchPort = new ReceivePort();
+  final _requestHandlers = {};
+  bool _chunkedEncoding = false;
+}
+
+void testStartStop() {
+  TestServerMain testServerMain = new TestServerMain();
+  testServerMain.setServerStartedHandler((int port) {
+    testServerMain.close();
+  });
+  testServerMain.start();
+}
+
+void testGET() {
+  TestServerMain testServerMain = new TestServerMain();
+  testServerMain.setServerStartedHandler((int port) {
+    HttpClient httpClient = new HttpClient();
+    httpClient
+        .get("127.0.0.1", port, "/0123456789")
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      StringBuffer body = new StringBuffer();
+      response.listen((data) => body.write(new String.fromCharCodes(data)),
+          onDone: () {
+        Expect.equals("01234567890", body.toString());
+        httpClient.close();
+        testServerMain.close();
+      });
+    });
+  });
+  testServerMain.start();
+}
+
+void testPOST(bool chunkedEncoding) {
+  String data = "ABCDEFGHIJKLMONPQRSTUVWXYZ";
+  final int kMessageCount = 10;
+
+  TestServerMain testServerMain = new TestServerMain();
+
+  void runTest(int port) {
+    int count = 0;
+    HttpClient httpClient = new HttpClient();
+    void sendRequest() {
+      httpClient.post("127.0.0.1", port, "/echo").then((request) {
+        if (chunkedEncoding) {
+          request.write(data.substring(0, 10));
+          request.write(data.substring(10, data.length));
+        } else {
+          request.contentLength = data.length;
+          request.write(data);
+        }
+        return request.close();
+      }).then((response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        StringBuffer body = new StringBuffer();
+        response.listen((data) => body.write(new String.fromCharCodes(data)),
+            onDone: () {
+          Expect.equals(data, body.toString());
+          count++;
+          if (count < kMessageCount) {
+            sendRequest();
+          } else {
+            httpClient.close();
+            testServerMain.close();
+          }
+        });
+      });
+    }
+
+    sendRequest();
+  }
+
+  testServerMain.setServerStartedHandler(runTest);
+  testServerMain.start(chunkedEncoding);
+}
+
+void test404() {
+  TestServerMain testServerMain = new TestServerMain();
+  testServerMain.setServerStartedHandler((int port) {
+    HttpClient httpClient = new HttpClient();
+    httpClient
+        .get("127.0.0.1", port, "/thisisnotfound")
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals(HttpStatus.notFound, response.statusCode);
+      var body = new StringBuffer();
+      response.listen((data) => body.write(new String.fromCharCodes(data)),
+          onDone: () {
+        Expect.equals("Page not found", body.toString());
+        httpClient.close();
+        testServerMain.close();
+      });
+    });
+  });
+  testServerMain.start();
+}
+
+void testReasonPhrase() {
+  TestServerMain testServerMain = new TestServerMain();
+  testServerMain.setServerStartedHandler((int port) {
+    HttpClient httpClient = new HttpClient();
+    httpClient.get("127.0.0.1", port, "/reasonformoving").then((request) {
+      request.followRedirects = false;
+      return request.close();
+    }).then((response) {
+      Expect.equals(HttpStatus.movedPermanently, response.statusCode);
+      Expect.equals("Don't come looking here any more", response.reasonPhrase);
+      response.listen((data) => Expect.fail("No data expected"), onDone: () {
+        httpClient.close();
+        testServerMain.close();
+      });
+    });
+  });
+  testServerMain.start();
+}
+
+void main() {
+  testStartStop();
+  testGET();
+  testPOST(true);
+  testPOST(false);
+  test404();
+  testReasonPhrase();
+}
diff --git a/tests/standalone/io/http_bind_test.dart b/tests/standalone/io/http_bind_test.dart
new file mode 100644
index 0000000..502a012
--- /dev/null
+++ b/tests/standalone/io/http_bind_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:convert';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+testBindShared(String host, bool v6Only) async {
+  asyncStart();
+
+  // Sent a single request using a new HttpClient to ensure a new TCP
+  // connection is used.
+  Future singleRequest(host, port, statusCode) async {
+    var client = new HttpClient();
+    var request = await client.open('GET', host, port, '/');
+    var response = await request.close();
+    await response.drain();
+    Expect.equals(statusCode, response.statusCode);
+    client.close(force: true);
+  }
+
+  Completer server1Request = new Completer();
+  Completer server2Request = new Completer();
+
+  var server1 = await HttpServer.bind(host, 0, v6Only: v6Only, shared: true);
+  var port = server1.port;
+  Expect.isTrue(port > 0);
+
+  var server2 = await HttpServer.bind(host, port, v6Only: v6Only, shared: true);
+  Expect.equals(server1.address.address, server2.address.address);
+  Expect.equals(port, server2.port);
+
+  server1.listen((request) {
+    server1Request.complete();
+    request.response.statusCode = 501;
+    request.response.close();
+  });
+
+  await singleRequest(host, port, 501);
+  await server1.close();
+
+  server2.listen((request) {
+    server2Request.complete();
+    request.response.statusCode = 502;
+    request.response.close();
+  });
+
+  await singleRequest(host, port, 502);
+  await server2.close();
+
+  await server1Request.future;
+  await server2Request.future;
+
+  asyncEnd();
+}
+
+void main() {
+  // Please don't change this to use await/async.
+  asyncStart();
+  supportsIPV6().then((ok) {
+    var addresses = ['127.0.0.1'];
+    if (ok) {
+      addresses.add('::1');
+    }
+    var futures = <Future>[];
+    for (var host in addresses) {
+      futures.add(testBindShared(host, false));
+      futures.add(testBindShared(host, true));
+    }
+    Future.wait(futures).then((_) => asyncEnd());
+  });
+}
+
+Future<bool> supportsIPV6() async {
+  try {
+    var socket = await ServerSocket.bind('::1', 0);
+    await socket.close();
+    return true;
+  } catch (e) {
+    print(e);
+    return false;
+  }
+}
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
new file mode 100644
index 0000000..284c441d
--- /dev/null
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -0,0 +1,301 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testGetEmptyRequest() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.cast<List<int>>().pipe(request.response);
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((data) {}, onDone: server.close);
+    });
+  });
+}
+
+void testGetDataRequest() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    var data = "lalala".codeUnits;
+    server.listen((request) {
+      request.response.add(data);
+      request.cast<List<int>>().pipe(request.response);
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      int count = 0;
+      response.listen((data) => count += data.length, onDone: () {
+        server.close();
+        Expect.equals(data.length, count);
+      });
+    });
+  });
+}
+
+void testGetInvalidHost() {
+  asyncStart();
+  var client = new HttpClient();
+  client.get("__SOMETHING_INVALID__", 8888, "/").catchError((error) {
+    client.close();
+    asyncEnd();
+  });
+}
+
+void testGetServerClose() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      server.close();
+      new Timer(const Duration(milliseconds: 100), () {
+        request.response.close();
+      });
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) => response.drain())
+        .then((_) => asyncEnd());
+  });
+}
+
+void testGetServerCloseNoKeepAlive() {
+  asyncStart();
+  var client = new HttpClient();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int port = server.port;
+    server.first.then((request) => request.response.close());
+
+    client
+        .get("127.0.0.1", port, "/")
+        .then((request) => request.close())
+        .then((response) => response.drain())
+        .then((_) => client.get("127.0.0.1", port, "/"))
+        .then((request) => request.close())
+        .then((_) => Expect.fail('should not succeed'), onError: (_) {})
+        .then((_) => asyncEnd());
+  });
+}
+
+void testGetServerForceClose() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      server.close(force: true);
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      Expect.fail("Request not expected");
+    }).catchError((error) => asyncEnd(),
+            test: (error) => error is HttpException);
+  });
+}
+
+void testGetDataServerForceClose() {
+  asyncStart();
+  var completer = new Completer();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response.bufferOutput = false;
+      request.response.contentLength = 100;
+      request.response.write("data");
+      request.response.write("more data");
+      completer.future.then((_) => server.close(force: true));
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      // Close the (incomplete) response, now that we have seen
+      // the response object.
+      completer.complete(null);
+      int errors = 0;
+      response.listen((data) {},
+          onError: (error) => errors++,
+          onDone: () {
+            Expect.equals(1, errors);
+            asyncEnd();
+          });
+    });
+  });
+}
+
+typedef Future<HttpClientRequest> Callback1(String a1, int a2, String a3);
+void testOpenEmptyRequest() {
+  var client = new HttpClient();
+  var methods = [
+    [client.get, 'GET'],
+    [client.post, 'POST'],
+    [client.put, 'PUT'],
+    [client.delete, 'DELETE'],
+    [client.patch, 'PATCH'],
+    [client.head, 'HEAD']
+  ];
+
+  for (var method in methods) {
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      server.listen((request) {
+        Expect.equals(method[1], request.method);
+        request.cast<List<int>>().pipe(request.response);
+      });
+
+      Callback1 cb = method[0] as Callback1;
+      cb("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+        response.listen((data) {}, onDone: server.close);
+      });
+    });
+  }
+}
+
+typedef Future<HttpClientRequest> Callback2(Uri a1);
+void testOpenUrlEmptyRequest() {
+  var client = new HttpClient();
+  var methods = [
+    [client.getUrl, 'GET'],
+    [client.postUrl, 'POST'],
+    [client.putUrl, 'PUT'],
+    [client.deleteUrl, 'DELETE'],
+    [client.patchUrl, 'PATCH'],
+    [client.headUrl, 'HEAD']
+  ];
+
+  for (var method in methods) {
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      server.listen((request) {
+        Expect.equals(method[1], request.method);
+        request.cast<List<int>>().pipe(request.response);
+      });
+
+      Callback2 cb = method[0] as Callback2;
+      cb(Uri.parse("http://127.0.0.1:${server.port}/"))
+          .then((request) => request.close())
+          .then((response) {
+        response.listen((data) {}, onDone: server.close);
+      });
+    });
+  }
+}
+
+void testNoBuffer() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    var response;
+    server.listen((request) {
+      response = request.response;
+      response.bufferOutput = false;
+      response.writeln('init');
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((clientResponse) {
+      var iterator = new StreamIterator(clientResponse
+          .cast<List<int>>()
+          .transform(utf8.decoder)
+          .transform(new LineSplitter()));
+      iterator.moveNext().then((hasValue) {
+        Expect.isTrue(hasValue);
+        Expect.equals('init', iterator.current);
+        int count = 0;
+        void run() {
+          if (count == 10) {
+            response.close();
+            iterator.moveNext().then((hasValue) {
+              Expect.isFalse(hasValue);
+              server.close();
+              asyncEnd();
+            });
+          } else {
+            response.writeln('output$count');
+            iterator.moveNext().then((hasValue) {
+              Expect.isTrue(hasValue);
+              Expect.equals('output$count', iterator.current);
+              count++;
+              run();
+            });
+          }
+        }
+
+        run();
+      });
+    });
+  });
+}
+
+void testMaxConnectionsPerHost(int connectionCap, int connections) {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int handled = 0;
+    server.listen((request) {
+      Expect.isTrue(server.connectionsInfo().total <= connectionCap);
+      request.response.close();
+      handled++;
+      if (handled == connections) {
+        asyncEnd();
+        server.close();
+      }
+    });
+
+    var client = new HttpClient();
+    client.maxConnectionsPerHost = connectionCap;
+    for (int i = 0; i < connections; i++) {
+      asyncStart();
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+        response.listen(null, onDone: () {
+          asyncEnd();
+        });
+      });
+    }
+  });
+}
+
+void main() {
+  testGetEmptyRequest();
+  testGetDataRequest();
+  testGetInvalidHost();
+  testGetServerClose();
+  testGetServerCloseNoKeepAlive();
+  testGetServerForceClose();
+  testGetDataServerForceClose();
+  testOpenEmptyRequest();
+  testOpenUrlEmptyRequest();
+  testNoBuffer();
+  testMaxConnectionsPerHost(1, 1);
+  testMaxConnectionsPerHost(1, 10);
+  testMaxConnectionsPerHost(5, 10);
+  testMaxConnectionsPerHost(10, 50);
+}
diff --git a/tests/standalone/io/http_client_exception_test.dart b/tests/standalone/io/http_client_exception_test.dart
new file mode 100644
index 0000000..7b5ad9d
--- /dev/null
+++ b/tests/standalone/io/http_client_exception_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 "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testInvalidUrl() {
+  HttpClient client = new HttpClient();
+  Expect.throws(() => client.getUrl(Uri.parse('ftp://www.google.com')),
+      (e) => e.toString().contains("Unsupported scheme"));
+  Expect.throws(() => client.getUrl(Uri.parse('httpx://www.google.com')),
+      (e) => e.toString().contains("Unsupported scheme"));
+  Expect.throwsFormatException(() => client.getUrl(Uri.parse('http://::1')));
+  Expect.throws(() => client.getUrl(Uri.parse('http://user@:1')),
+      (e) => e.toString().contains("No host specified"));
+  Expect.throws(() => client.getUrl(Uri.parse('http:///')),
+      (e) => e.toString().contains("No host specified"));
+  Expect.throws(() => client.getUrl(Uri.parse('http:///index.html')),
+      (e) => e.toString().contains("No host specified"));
+  Expect.throws(() => client.getUrl(Uri.parse('///')),
+      (e) => e.toString().contains("No host specified"));
+  Expect.throws(() => client.getUrl(Uri.parse('///index.html')),
+      (e) => e.toString().contains("No host specified"));
+}
+
+void testBadHostName() {
+  asyncStart();
+  HttpClient client = new HttpClient();
+  client.get("some.bad.host.name.7654321", 0, "/").then((request) {
+    Expect.fail("Should not open a request on bad hostname");
+  }).catchError((error) {
+    asyncEnd(); // We expect onError to be called, due to bad host name.
+  }, test: (error) => error is! String);
+}
+
+void main() {
+  testInvalidUrl();
+  testBadHostName();
+}
diff --git a/tests/standalone/io/http_client_request_test.dart b/tests/standalone/io/http_client_request_test.dart
new file mode 100644
index 0000000..dae2b2a
--- /dev/null
+++ b/tests/standalone/io/http_client_request_test.dart
@@ -0,0 +1,109 @@
+// 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:io";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testClientRequest(Future handler(request)) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.drain().then((_) => request.response.close()).catchError((_) {});
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) {
+          return handler(request);
+        })
+        .then((response) => response.drain())
+        .catchError((_) {})
+        .whenComplete(() {
+          client.close();
+          server.close();
+        });
+  });
+}
+
+void testResponseDone() {
+  testClientRequest((request) {
+    request.close().then((res1) {
+      request.done.then((res2) {
+        Expect.equals(res1, res2);
+      });
+    });
+    return request.done;
+  });
+}
+
+void testBadResponseAdd() {
+  asyncStart();
+  testClientRequest((request) {
+    request.contentLength = 0;
+    request.add([0]);
+    request.close();
+    request.done.catchError((error) {
+      asyncEnd();
+    }, test: (e) => e is HttpException);
+    return request.done;
+  });
+
+  asyncStart();
+  testClientRequest((request) {
+    request.contentLength = 5;
+    request.add([0, 0, 0]);
+    request.add([0, 0, 0]);
+    request.close();
+    request.done.catchError((error) {
+      asyncEnd();
+    }, test: (e) => e is HttpException);
+    return request.done;
+  });
+
+  asyncStart();
+  testClientRequest((request) {
+    request.contentLength = 0;
+    request.add(new Uint8List(64 * 1024));
+    request.add(new Uint8List(64 * 1024));
+    request.add(new Uint8List(64 * 1024));
+    request.close();
+    request.done.catchError((error) {
+      asyncEnd();
+    }, test: (e) => e is HttpException);
+    return request.done;
+  });
+}
+
+void testBadResponseClose() {
+  asyncStart();
+  testClientRequest((request) {
+    request.contentLength = 5;
+    request.close();
+    request.done.catchError((error) {
+      asyncEnd();
+    }, test: (e) => e is HttpException);
+    return request.done;
+  });
+
+  asyncStart();
+  testClientRequest((request) {
+    request.contentLength = 5;
+    request.add([0]);
+    request.close();
+    request.done.catchError((error) {
+      asyncEnd();
+    }, test: (e) => e is HttpException);
+    return request.done;
+  });
+}
+
+void main() {
+  testResponseDone();
+  testBadResponseAdd();
+  testBadResponseClose();
+}
diff --git a/tests/standalone/io/http_client_stays_alive_test.dart b/tests/standalone/io/http_client_stays_alive_test.dart
new file mode 100644
index 0000000..37af33a
--- /dev/null
+++ b/tests/standalone/io/http_client_stays_alive_test.dart
@@ -0,0 +1,85 @@
+// 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.
+
+// OtherResources=http_client_stays_alive_test.dart
+
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+
+// NOTE: This test tries to ensure that an HttpClient will close it's
+// underlying idle connections after [HttpClient.idleTimeout].
+//
+// The main script spawns a server and a subprocess which does a connection back
+// to it.
+// The subprocess is expected to shut down its idle sockets after
+// [HttpClient.idleTimeout] and the main script will assert that this happens
+// within +/- 2 <= seconds.
+
+const SECONDS = 4;
+const SLACK = 60;
+
+void runServerProcess() {
+  asyncStart();
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+    var url = 'http://127.0.0.1:${server.port}/';
+
+    server.idleTimeout = const Duration(hours: 1);
+
+    var subscription = server.listen((HttpRequest request) {
+      request.response
+        ..write('hello world')
+        ..close();
+    });
+
+    var sw = new Stopwatch()..start();
+    var script = Platform.script
+        .resolve('http_client_stays_alive_test.dart')
+        .toFilePath();
+    var arguments = <String>[]
+      ..addAll(Platform.executableArguments)
+      ..add(script)
+      ..add(url);
+    Process.run(Platform.executable, arguments).then((res) {
+      subscription.cancel();
+      if (res.exitCode != 0) {
+        throw "Child exited with ${res.exitCode} instead of 0. "
+            "(stdout: ${res.stdout}, stderr: ${res.stderr})";
+      }
+      var seconds = sw.elapsed.inSeconds;
+      // NOTE: There is a slight chance this will cause flakiness, but there is
+      // no other good way of testing correctness of timing-dependent code
+      // form the outside.
+      if (seconds < SECONDS || (SECONDS + SLACK) < seconds) {
+        throw "Child did exit within $seconds seconds, but expected it to take "
+            "roughly between $SECONDS and ${SECONDS + SLACK} seconds.";
+      }
+
+      asyncEnd();
+    });
+  });
+}
+
+void runClientProcess(String url) {
+  var uri = Uri.parse(url);
+
+  // NOTE: We make an HTTP client request and then *forget to close* the HTTP
+  // client instance. The idle timer should fire after SECONDS.
+  var client = new HttpClient();
+  client.idleTimeout = const Duration(seconds: SECONDS);
+
+  client
+      .getUrl(uri)
+      .then((req) => req.close())
+      .then((response) => response.drain())
+      .then((_) => print('drained client request'));
+}
+
+void main(List<String> args) {
+  if (args.length == 1) {
+    runClientProcess(args.first);
+  } else {
+    runServerProcess();
+  }
+}
diff --git a/tests/standalone/io/http_close_test.dart b/tests/standalone/io/http_close_test.dart
new file mode 100644
index 0000000..d07175f
--- /dev/null
+++ b/tests/standalone/io/http_close_test.dart
@@ -0,0 +1,151 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+import "dart:math";
+
+testClientAndServerCloseNoListen(int connections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int closed = 0;
+    server.listen((request) {
+      request.response.close();
+      request.response.done.then((_) {
+        closed++;
+        if (closed == connections) {
+          Expect.equals(0, server.connectionsInfo().active);
+          Expect.equals(
+              server.connectionsInfo().total, server.connectionsInfo().idle);
+          server.close();
+        }
+      });
+    });
+    var client = HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {});
+    }
+  });
+}
+
+testClientCloseServerListen(int connections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int closed = 0;
+    check() {
+      closed++;
+      if (closed == connections * 2) {
+        Expect.equals(0, server.connectionsInfo().active);
+        Expect.equals(
+            server.connectionsInfo().total, server.connectionsInfo().idle);
+        server.close();
+      }
+    }
+
+    server.listen((request) {
+      request.listen((_) {}, onDone: () {
+        request.response.close();
+        request.response.done.then((_) => check());
+      });
+    });
+    var client = HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) => check());
+    }
+  });
+}
+
+testClientCloseSendingResponse(int connections) {
+  var buffer = Uint8List(64 * 1024);
+  var rand = Random();
+  for (int i = 0; i < buffer.length; i++) {
+    buffer[i] = rand.nextInt(256);
+  }
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int closed = 0;
+    check() {
+      closed++;
+      // Wait for both server and client to see the connections as closed.
+      if (closed == connections * 2) {
+        Expect.equals(0, server.connectionsInfo().active);
+        Expect.equals(
+            server.connectionsInfo().total, server.connectionsInfo().idle);
+        server.close();
+      }
+    }
+
+    server.listen((request) {
+      var timer = Timer.periodic(const Duration(milliseconds: 50), (_) {
+        request.response.add(buffer);
+      });
+      request.response.done.catchError((_) {}).whenComplete(() {
+        check();
+        timer.cancel();
+      });
+    });
+    var client = HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+        // Ensure we don't accept the response until we have send the entire
+        // request.
+        var subscription = response.listen((_) {});
+        Timer(const Duration(milliseconds: 20), () {
+          subscription.cancel();
+          check();
+        });
+      });
+    }
+  });
+}
+
+// Closing the request early, before sending the full request payload should
+// result in an error on both server and client.
+testClientCloseWhileSendingRequest(int connections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int serverErrors = 0;
+    int clientErrors = 0;
+    server.listen((request) {
+      request.listen((_) {}, onError: (_) {
+        serverErrors++;
+        if (serverErrors == connections) {
+          server.close();
+        }
+      });
+    }, onDone: () {
+      Expect.equals(connections, clientErrors);
+      Expect.equals(connections, serverErrors);
+    });
+    var client = HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client.post("127.0.0.1", server.port, "/").then((request) {
+        request.contentLength = 110;
+        request.write("0123456789");
+        return request.close();
+      }).catchError((_) {
+        clientErrors++;
+      });
+    }
+  });
+}
+
+main() {
+  testClientAndServerCloseNoListen(10);
+  testClientCloseServerListen(10);
+  testClientCloseSendingResponse(10);
+  testClientCloseWhileSendingRequest(10);
+}
diff --git a/tests/standalone/io/http_compression_test.dart b/tests/standalone/io/http_compression_test.dart
new file mode 100644
index 0000000..ae5507c
--- /dev/null
+++ b/tests/standalone/io/http_compression_test.dart
@@ -0,0 +1,105 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'package:expect/expect.dart';
+import 'dart:io';
+import 'dart:typed_data';
+
+void testServerCompress({bool clientAutoUncompress: true}) async {
+  void test(List<int> data) async {
+    final server = await HttpServer.bind("127.0.0.1", 0);
+    server.autoCompress = true;
+    server.listen((request) {
+      request.response.add(data);
+      request.response.close();
+    });
+    var client = new HttpClient();
+    client.autoUncompress = clientAutoUncompress;
+    final request = await client.get("127.0.0.1", server.port, "/");
+    request.headers.set(HttpHeaders.acceptEncodingHeader, "gzip,deflate");
+    final response = await request.close();
+    Expect.equals(
+        "gzip", response.headers.value(HttpHeaders.contentEncodingHeader));
+    final list =
+        await response.fold<List<int>>(<int>[], (list, b) => list..addAll(b));
+    if (clientAutoUncompress) {
+      Expect.listEquals(data, list);
+    } else {
+      Expect.listEquals(data, gzip.decode(list));
+    }
+    server.close();
+    client.close();
+  }
+
+  await test("My raw server provided data".codeUnits);
+  var longBuffer = new Uint8List(1024 * 1024);
+  for (int i = 0; i < longBuffer.length; i++) {
+    longBuffer[i] = i & 0xFF;
+  }
+  await test(longBuffer);
+}
+
+void testAcceptEncodingHeader() async {
+  void test(String encoding, bool valid) async {
+    final server = await HttpServer.bind("127.0.0.1", 0);
+    server.autoCompress = true;
+    server.listen((request) {
+      request.response.write("data");
+      request.response.close();
+    });
+    var client = new HttpClient();
+    final request = await client.get("127.0.0.1", server.port, "/");
+    request.headers.set(HttpHeaders.acceptEncodingHeader, encoding);
+    final response = await request.close();
+    Expect.equals(valid,
+        ("gzip" == response.headers.value(HttpHeaders.contentEncodingHeader)));
+    await response.listen((_) {}).asFuture();
+    server.close();
+    client.close();
+  }
+
+  await test('gzip', true);
+  await test('deflate', false);
+  await test('gzip, deflate', true);
+  await test('gzip ,deflate', true);
+  await test('gzip  ,  deflate', true);
+  await test('deflate,gzip', true);
+  await test('deflate, gzip', true);
+  await test('deflate ,gzip', true);
+  await test('deflate  ,  gzip', true);
+  await test('abc,deflate  ,  gzip,def,,,ghi  ,jkl', true);
+  await test('xgzip', false);
+  await test('gzipx;', false);
+}
+
+void testDisableCompressTest() async {
+  final server = await HttpServer.bind("127.0.0.1", 0);
+  Expect.equals(false, server.autoCompress);
+  server.listen((request) {
+    Expect.equals(
+        'gzip', request.headers.value(HttpHeaders.acceptEncodingHeader));
+    request.response.write("data");
+    request.response.close();
+  });
+  final client = new HttpClient();
+  final request = await client.get("127.0.0.1", server.port, "/");
+  final response = await request.close();
+  Expect.equals(
+      null, response.headers.value(HttpHeaders.contentEncodingHeader));
+  await response.listen((_) {}).asFuture();
+  server.close();
+  client.close();
+}
+
+void main() async {
+  await testServerCompress();
+  await testServerCompress(clientAutoUncompress: false);
+  await testAcceptEncodingHeader();
+  await testDisableCompressTest();
+}
diff --git a/tests/standalone/io/http_connection_close_test.dart b/tests/standalone/io/http_connection_close_test.dart
new file mode 100644
index 0000000..2ec57fb
--- /dev/null
+++ b/tests/standalone/io/http_connection_close_test.dart
@@ -0,0 +1,81 @@
+// 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 "dart:async";
+import "dart:io";
+
+void testHttp10Close(bool closeRequest) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.write("GET / HTTP/1.0\r\n\r\n");
+      socket.listen((data) {}, onDone: () {
+        if (!closeRequest) socket.destroy();
+        server.close();
+      });
+      if (closeRequest) socket.close();
+    });
+  });
+}
+
+void testHttp11Close(bool closeRequest) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      List<int> buffer = new List<int>.filled(1024, 0);
+      socket.write("GET / HTTP/1.1\r\nConnection: close\r\n\r\n");
+      socket.listen((data) {}, onDone: () {
+        if (!closeRequest) socket.destroy();
+        server.close();
+      });
+      if (closeRequest) socket.close();
+    });
+  });
+}
+
+void testStreamResponse() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {
+        request.response
+            .write('data:${new DateTime.now().millisecondsSinceEpoch}\n\n');
+      });
+      request.response.done.whenComplete(() {
+        timer.cancel();
+      }).catchError((_) {});
+    });
+
+    var client = new HttpClient();
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}"))
+        .then((request) => request.close())
+        .then((response) {
+      int bytes = 0;
+      response.listen((data) {
+        bytes += data.length;
+        if (bytes > 100) {
+          client.close(force: true);
+        }
+      }, onError: (error) {
+        server.close();
+      });
+    });
+  });
+}
+
+main() {
+  testHttp10Close(false);
+  testHttp10Close(true);
+  testHttp11Close(false);
+  testHttp11Close(true);
+  testStreamResponse();
+}
diff --git a/tests/standalone/io/http_connection_header_test.dart b/tests/standalone/io/http_connection_header_test.dart
new file mode 100644
index 0000000..55c8cd8
--- /dev/null
+++ b/tests/standalone/io/http_connection_header_test.dart
@@ -0,0 +1,81 @@
+// 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 "dart:isolate";
+import "dart:io";
+
+void setConnectionHeaders(HttpHeaders headers) {
+  headers.add(HttpHeaders.connectionHeader, "my-connection-header1");
+  headers.add("My-Connection-Header1", "some-value1");
+  headers.add(HttpHeaders.connectionHeader, "my-connection-header2");
+  headers.add("My-Connection-Header2", "some-value2");
+}
+
+void checkExpectedConnectionHeaders(
+    HttpHeaders headers, bool persistentConnection) {
+  Expect.equals("some-value1", headers.value("My-Connection-Header1"));
+  Expect.equals("some-value2", headers.value("My-Connection-Header2"));
+  Expect.isTrue(headers[HttpHeaders.connectionHeader]!
+      .any((value) => value.toLowerCase() == "my-connection-header1"));
+  Expect.isTrue(headers[HttpHeaders.connectionHeader]!
+      .any((value) => value.toLowerCase() == "my-connection-header2"));
+  if (persistentConnection) {
+    Expect.equals(2, headers[HttpHeaders.connectionHeader]!.length);
+  } else {
+    Expect.equals(3, headers[HttpHeaders.connectionHeader]!.length);
+    Expect.isTrue(headers[HttpHeaders.connectionHeader]!
+        .any((value) => value.toLowerCase() == "close"));
+  }
+}
+
+void test(int totalConnections, bool clientPersistentConnection) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      // Check expected request.
+      Expect.equals(clientPersistentConnection, request.persistentConnection);
+      Expect.equals(
+          clientPersistentConnection, request.response.persistentConnection);
+      checkExpectedConnectionHeaders(
+          request.headers, request.persistentConnection);
+
+      // Generate response. If the client signaled non-persistent
+      // connection the server should not need to set it.
+      if (request.persistentConnection) {
+        request.response.persistentConnection = false;
+      }
+      setConnectionHeaders(request.response.headers);
+      request.response.close();
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) {
+        setConnectionHeaders(request.headers);
+        request.persistentConnection = clientPersistentConnection;
+        return request.close();
+      }).then((HttpClientResponse response) {
+        Expect.isFalse(response.persistentConnection);
+        checkExpectedConnectionHeaders(
+            response.headers, response.persistentConnection);
+        response.listen((_) {}, onDone: () {
+          count++;
+          if (count == totalConnections) {
+            client.close();
+            server.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+void main() {
+  test(2, false);
+  test(2, true);
+}
diff --git a/tests/standalone/io/http_connection_info_test.dart b/tests/standalone/io/http_connection_info_test.dart
new file mode 100644
index 0000000..967c2ed
--- /dev/null
+++ b/tests/standalone/io/http_connection_info_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.
+
+import "package:expect/expect.dart";
+import "dart:io";
+
+void testHttpConnectionInfo() {
+  HttpServer.bind("0.0.0.0", 0).then((server) {
+    int? clientPort;
+
+    server.listen((request) {
+      var response = request.response;
+      Expect.isTrue(request.connectionInfo!.remoteAddress is InternetAddress);
+      Expect.isTrue(response.connectionInfo!.remoteAddress is InternetAddress);
+      Expect.equals(request.connectionInfo!.localPort, server.port);
+      Expect.equals(response.connectionInfo!.localPort, server.port);
+      Expect.isNotNull(clientPort);
+      Expect.equals(request.connectionInfo!.remotePort, clientPort);
+      Expect.equals(response.connectionInfo!.remotePort, clientPort);
+      request.listen((_) {}, onDone: () {
+        request.response.close();
+      });
+    });
+
+    HttpClient client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/").then((request) {
+      Expect.isTrue(request.connectionInfo!.remoteAddress is InternetAddress);
+      Expect.equals(request.connectionInfo!.remotePort, server.port);
+      clientPort = request.connectionInfo!.localPort;
+      return request.close();
+    }).then((response) {
+      Expect.equals(server.port, response.connectionInfo!.remotePort);
+      Expect.equals(clientPort, response.connectionInfo!.localPort);
+      response.listen((_) {}, onDone: () {
+        client.close();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testHttpConnectionInfo();
+}
diff --git a/tests/standalone/io/http_content_length_test.dart b/tests/standalone/io/http_content_length_test.dart
new file mode 100644
index 0000000..15d6520
--- /dev/null
+++ b/tests/standalone/io/http_content_length_test.dart
@@ -0,0 +1,237 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:isolate";
+import "dart:io";
+import "package:expect/expect.dart";
+
+void testNoBody(int totalConnections, bool explicitContentLength) {
+  int count = 0;
+  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.equals("0", request.headers.value('content-length'));
+      Expect.equals(0, request.contentLength);
+      var response = request.response;
+      response.contentLength = 0;
+      response.done.then((_) {
+        Expect.fail("Unexpected successful response completion");
+      }).catchError((error) {
+        Expect.isTrue(error is HttpException);
+        if (++count == totalConnections) {
+          server.close();
+        }
+      });
+      // write with content length 0 closes the connection and
+      // reports an error.
+      response.write("x");
+      // Subsequent write are ignored as there is already an
+      // error.
+      response.write("x");
+      // After an explicit close, write becomes a state error
+      // because we have said we will not add more.
+      response.close();
+      Expect.throws(() {
+        response.write("x");
+      }, (e) => e is StateError);
+    }, onError: (e, trace) {
+      String msg = "Unexpected server error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client.get("127.0.0.1", server.port, "/").then((request) {
+        if (explicitContentLength) {
+          request.contentLength = 0;
+        }
+        return request.close();
+      }).then((response) {
+        Expect.equals("0", response.headers.value('content-length'));
+        Expect.equals(0, response.contentLength);
+        response.drain();
+      }).catchError((e, trace) {
+        // It's also okay to fail, as headers may not be written.
+      });
+    }
+  });
+}
+
+void testBody(int totalConnections, bool useHeader) {
+  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
+    int serverCount = 0;
+    server.listen((HttpRequest request) {
+      Expect.equals("2", request.headers.value('content-length'));
+      Expect.equals(2, request.contentLength);
+      var response = request.response;
+      if (useHeader) {
+        response.contentLength = 2;
+      } else {
+        response.headers.set("content-length", 2);
+      }
+      request.listen((d) {}, onDone: () {
+        response.write("x");
+        Expect.throws(
+            () => response.contentLength = 3, (e) => e is HttpException);
+        response.write("x");
+        response.write("x");
+        response.done.then((_) {
+          Expect.fail("Unexpected successful response completion");
+        }).catchError((error) {
+          Expect.isTrue(error is HttpException, "[$error]");
+          if (++serverCount == totalConnections) {
+            server.close();
+          }
+        });
+        response.close();
+        Expect.throws(() {
+          response.write("x");
+        }, (e) => e is StateError);
+      });
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    int clientCount = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client.get("127.0.0.1", server.port, "/").then((request) {
+        if (useHeader) {
+          request.contentLength = 2;
+        } else {
+          request.headers.add(HttpHeaders.contentLengthHeader, "7");
+          request.headers.add(HttpHeaders.contentLengthHeader, "2");
+        }
+        request.write("x");
+        Expect.throws(
+            () => request.contentLength = 3, (e) => e is HttpException);
+        request.write("x");
+        return request.close();
+      }).then((response) {
+        Expect.equals("2", response.headers.value('content-length'));
+        Expect.equals(2, response.contentLength);
+        response.listen((d) {}, onDone: () {
+          if (++clientCount == totalConnections) {
+            client.close();
+          }
+        }, onError: (error, trace) {
+          // Undefined what server response sends.
+        });
+      }).catchError((error) {
+        // It's also okay to fail, as headers may not be written.
+      });
+    }
+  });
+}
+
+void testBodyChunked(int totalConnections, bool useHeader) {
+  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNull(request.headers.value('content-length'));
+      Expect.equals(-1, request.contentLength);
+      var response = request.response;
+      if (useHeader) {
+        response.contentLength = 2;
+        response.headers.chunkedTransferEncoding = true;
+      } else {
+        response.headers.set("content-length", 2);
+        response.headers.set("transfer-encoding", "chunked");
+      }
+      request.listen((d) {}, onDone: () {
+        response.write("x");
+        Expect.throws(() => response.headers.chunkedTransferEncoding = false,
+            (e) => e is HttpException);
+        response.write("x");
+        response.write("x");
+        response.close();
+        Expect.throws(() {
+          response.write("x");
+        }, (e) => e is StateError);
+      });
+    }, onError: (e, trace) {
+      String msg = "Unexpected error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client.get("127.0.0.1", server.port, "/").then((request) {
+        if (useHeader) {
+          request.contentLength = 2;
+          request.headers.chunkedTransferEncoding = true;
+        } else {
+          request.headers.add(HttpHeaders.contentLengthHeader, "2");
+          request.headers.set(HttpHeaders.transferEncodingHeader, "chunked");
+        }
+        request.write("x");
+        Expect.throws(() => request.headers.chunkedTransferEncoding = false,
+            (e) => e is HttpException);
+        request.write("x");
+        request.write("x");
+        return request.close();
+      }).then((response) {
+        Expect.isNull(response.headers.value('content-length'));
+        Expect.equals(-1, response.contentLength);
+        response.listen((d) {}, onDone: () {
+          if (++count == totalConnections) {
+            client.close();
+            server.close();
+          }
+        });
+      }).catchError((e, trace) {
+        String msg = "Unexpected error $e";
+        if (trace != null) msg += "\nStackTrace: $trace";
+        Expect.fail(msg);
+      });
+    }
+  });
+}
+
+void testSetContentLength() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      var response = request.response;
+      Expect.isNull(response.headers.value('content-length'));
+      Expect.equals(-1, response.contentLength);
+      response.headers.set("content-length", 3);
+      Expect.equals("3", response.headers.value('content-length'));
+      Expect.equals(3, response.contentLength);
+      response.write("xxx");
+      response.close();
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}, onDone: () {
+        client.close();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testNoBody(5, false);
+  testNoBody(25, false);
+  testNoBody(5, true);
+  testNoBody(25, true);
+  testBody(5, false);
+  testBody(5, true);
+  testBodyChunked(5, false);
+  testBodyChunked(5, true);
+  testSetContentLength();
+}
diff --git a/tests/standalone/io/http_cookie_date_test.dart b/tests/standalone/io/http_cookie_date_test.dart
new file mode 100644
index 0000000..6b94254
--- /dev/null
+++ b/tests/standalone/io/http_cookie_date_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.
+
+// @dart = 2.6
+
+library dart._http;
+
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:developer";
+import "dart:io";
+import "dart:math";
+import "dart:typed_data";
+import "package:expect/expect.dart";
+
+part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/http_impl.dart";
+part "../../../sdk/lib/_http/http_date.dart";
+part "../../../sdk/lib/_http/http_parser.dart";
+part "../../../sdk/lib/_http/http_headers.dart";
+part "../../../sdk/lib/_http/http_session.dart";
+
+void testParseHttpCookieDate() {
+  Expect.throws(() => HttpDate._parseCookieDate(""));
+
+  test(int year, int month, int day, int hours, int minutes, int seconds,
+      String formatted) {
+    DateTime date =
+        new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
+    Expect.equals(date, HttpDate._parseCookieDate(formatted));
+  }
+
+  test(2012, DateTime.june, 19, 14, 15, 01, "tue, 19-jun-12 14:15:01 gmt");
+  test(2021, DateTime.june, 09, 10, 18, 14, "Wed, 09-Jun-2021 10:18:14 GMT");
+  test(2021, DateTime.january, 13, 22, 23, 01, "Wed, 13-Jan-2021 22:23:01 GMT");
+  test(2013, DateTime.january, 15, 21, 47, 38, "Tue, 15-Jan-2013 21:47:38 GMT");
+  test(1970, DateTime.january, 01, 00, 00, 01, "Thu, 01-Jan-1970 00:00:01 GMT");
+}
+
+void main() {
+  testParseHttpCookieDate();
+}
diff --git a/tests/standalone/io/http_cookie_test.dart b/tests/standalone/io/http_cookie_test.dart
new file mode 100644
index 0000000..bfe9302
--- /dev/null
+++ b/tests/standalone/io/http_cookie_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.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+void testCookies() {
+  var cookies = [
+    {'abc': 'def'},
+    {'ABC': 'DEF'},
+    {'Abc': 'Def'},
+    {'Abc': 'Def', 'SID': 'sffFSDF4FsdfF56765'}
+  ];
+
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      // Collect the cookies in a map.
+      var cookiesMap = {};
+      request.cookies.forEach((c) => cookiesMap[c.name] = c.value);
+      int index = int.parse(request.uri.path.substring(1));
+      Expect.mapEquals(cookies[index], cookiesMap);
+      // Return the same cookies to the client.
+      cookiesMap.forEach((k, v) {
+        request.response.cookies.add(new Cookie(k, v));
+      });
+      request.response.close();
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < cookies.length; i++) {
+      client.get("127.0.0.1", server.port, "/$i").then((request) {
+        // Send the cookies to the server.
+        cookies[i].forEach((k, v) {
+          request.cookies.add(new Cookie(k, v));
+        });
+        return request.close();
+      }).then((response) {
+        // Expect the same cookies back.
+        var cookiesMap = {};
+        response.cookies.forEach((c) => cookiesMap[c.name] = c.value);
+        Expect.mapEquals(cookies[i], cookiesMap);
+        response.cookies.forEach((c) => Expect.isTrue(c.httpOnly));
+        response.listen((d) {}, onDone: () {
+          if (++count == cookies.length) {
+            client.close();
+            server.close();
+          }
+        });
+      }).catchError((e, trace) {
+        String msg = "Unexpected error $e";
+        if (trace != null) msg += "\nStackTrace: $trace";
+        Expect.fail(msg);
+      });
+    }
+  });
+}
+
+void testValidateCookieWithDoubleQuotes() {
+  Expect.equals(Cookie('key', 'value').toString(), 'key=value; HttpOnly');
+  Expect.equals(Cookie('key', '').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie('key', '""').toString(), 'key=""; HttpOnly');
+  Expect.equals(Cookie('key', '"value"').toString(), 'key="value"; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=value; HttpOnly').toString(),
+      'key=value; HttpOnly');
+  Expect.equals(
+      Cookie.fromSetCookieValue('key=; HttpOnly').toString(), 'key=; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key=""; HttpOnly').toString(),
+      'key=""; HttpOnly');
+  Expect.equals(Cookie.fromSetCookieValue('key="value"; HttpOnly').toString(),
+      'key="value"; HttpOnly');
+  Expect.throwsFormatException(() => Cookie('key', '"'));
+  Expect.throwsFormatException(() => Cookie('key', '"""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x""'));
+  Expect.throwsFormatException(() => Cookie('key', '"x"y"'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="""; HttpOnly'));
+  Expect.throwsFormatException(
+      () => Cookie.fromSetCookieValue('key="x""; HttpOnly'));
+}
+
+void main() {
+  testCookies();
+  testValidateCookieWithDoubleQuotes();
+}
diff --git a/tests/standalone/io/http_cross_process_test.dart b/tests/standalone/io/http_cross_process_test.dart
new file mode 100644
index 0000000..598ac68
--- /dev/null
+++ b/tests/standalone/io/http_cross_process_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+
+import 'dart:async';
+import 'dart:io';
+import "package:expect/expect.dart";
+
+const int NUM_SERVERS = 10;
+
+void main(List<String> args) {
+  if (args.isEmpty) {
+    for (int i = 0; i < NUM_SERVERS; ++i) {
+      makeServer().then((server) {
+        runClientProcess(server.port).then((_) => server.close());
+      });
+    }
+  } else if (args[0] == '--client') {
+    int port = int.parse(args[1]);
+    runClient(port);
+  } else {
+    Expect.fail('Unknown arguments to http_cross_process_test.dart');
+  }
+}
+
+Future makeServer() {
+  return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((request) {
+      request.cast<List<int>>().pipe(request.response);
+    });
+    return server;
+  });
+}
+
+Future runClientProcess(int port) {
+  return Process.run(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(Platform.script.toFilePath())
+            ..add('--client')
+            ..add(port.toString()))
+      .then((ProcessResult result) {
+    if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
+      print("Client failed, exit code ${result.exitCode}");
+      print("  stdout:");
+      print(result.stdout);
+      print("  stderr:");
+      print(result.stderr);
+      Expect.fail('Client subprocess exit code: ${result.exitCode}');
+    }
+  });
+}
+
+runClient(int port) {
+  var client = new HttpClient();
+  client
+      .get('127.0.0.1', port, "/")
+      .then((request) => request.close())
+      .then((response) => response.drain())
+      .then((_) => client.close())
+      .then((_) => print('SUCCESS'));
+}
diff --git a/tests/standalone/io/http_date_test.dart b/tests/standalone/io/http_date_test.dart
new file mode 100644
index 0000000..baa879f
--- /dev/null
+++ b/tests/standalone/io/http_date_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.
+
+import "dart:async";
+import "dart:math";
+import "dart:io";
+import "package:expect/expect.dart";
+
+void testParseHttpDate() {
+  DateTime date;
+  date = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+  Expect.equals(date, HttpDate.parse("Fri, 11 Jun 1999 18:46:53 GMT"));
+  Expect.equals(date, HttpDate.parse("Friday, 11-Jun-1999 18:46:53 GMT"));
+  Expect.equals(date, HttpDate.parse("Fri Jun 11 18:46:53 1999"));
+
+  date = new DateTime.utc(1970, DateTime.january, 1, 0, 0, 0, 0);
+  Expect.equals(date, HttpDate.parse("Thu, 1 Jan 1970 00:00:00 GMT"));
+  Expect.equals(date, HttpDate.parse("Thursday, 1-Jan-1970 00:00:00 GMT"));
+  Expect.equals(date, HttpDate.parse("Thu Jan  1 00:00:00 1970"));
+
+  date = new DateTime.utc(2012, DateTime.march, 5, 23, 59, 59, 0);
+  Expect.equals(date, HttpDate.parse("Mon, 5 Mar 2012 23:59:59 GMT"));
+  Expect.equals(date, HttpDate.parse("Monday, 5-Mar-2012 23:59:59 GMT"));
+  Expect.equals(date, HttpDate.parse("Mon Mar  5 23:59:59 2012"));
+}
+
+void testFormatParseHttpDate() {
+  test(int year, int month, int day, int hours, int minutes, int seconds,
+      String expectedFormatted) {
+    DateTime date;
+    String formatted;
+    date = new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
+    formatted = HttpDate.format(date);
+    Expect.equals(expectedFormatted, formatted);
+    Expect.equals(date, HttpDate.parse(formatted));
+  }
+
+  test(1999, DateTime.june, 11, 18, 46, 53, "Fri, 11 Jun 1999 18:46:53 GMT");
+  test(1970, DateTime.january, 1, 0, 0, 0, "Thu, 01 Jan 1970 00:00:00 GMT");
+  test(1970, DateTime.january, 1, 9, 9, 9, "Thu, 01 Jan 1970 09:09:09 GMT");
+  test(2012, DateTime.march, 5, 23, 59, 59, "Mon, 05 Mar 2012 23:59:59 GMT");
+}
+
+void testParseHttpDateFailures() {
+  Expect.throws(() {
+    HttpDate.parse("");
+  });
+  String valid = "Mon, 5 Mar 2012 23:59:59 GMT";
+  for (int i = 1; i < valid.length - 1; i++) {
+    String tmp = valid.substring(0, i);
+    Expect.throws(() {
+      HttpDate.parse(tmp);
+    });
+    Expect.throws(() {
+      HttpDate.parse(" $tmp");
+    });
+    Expect.throws(() {
+      HttpDate.parse(" $tmp ");
+    });
+    Expect.throws(() {
+      HttpDate.parse("$tmp ");
+    });
+  }
+  Expect.throws(() {
+    HttpDate.parse(" $valid");
+  });
+  Expect.throws(() {
+    HttpDate.parse(" $valid ");
+  });
+  Expect.throws(() {
+    HttpDate.parse("$valid ");
+  });
+}
+
+void main() {
+  testParseHttpDate();
+  testFormatParseHttpDate();
+  testParseHttpDateFailures();
+}
diff --git a/tests/standalone/io/http_detach_socket_test.dart b/tests/standalone/io/http_detach_socket_test.dart
new file mode 100644
index 0000000..fdbc257
--- /dev/null
+++ b/tests/standalone/io/http_detach_socket_test.dart
@@ -0,0 +1,198 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "dart:io";
+import "dart:isolate";
+
+void testServerDetachSocket() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.defaultResponseHeaders.clear();
+    server.serverHeader = null;
+    server.listen((request) {
+      var response = request.response;
+      response.contentLength = 0;
+      response.detachSocket().then((socket) {
+        Expect.isNotNull(socket);
+        var body = new StringBuffer();
+        socket.listen((data) => body.write(new String.fromCharCodes(data)),
+            onDone: () => Expect.equals("Some data", body.toString()));
+        socket.write("Test!");
+        socket.close();
+      });
+      server.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.write("GET / HTTP/1.1\r\n"
+          "content-length: 0\r\n\r\n"
+          "Some data");
+      var body = new StringBuffer();
+      socket.listen((data) => body.write(new String.fromCharCodes(data)),
+          onDone: () {
+        Expect.equals(
+            "HTTP/1.1 200 OK\r\n"
+            "content-length: 0\r\n"
+            "\r\n"
+            "Test!",
+            body.toString());
+        socket.close();
+      });
+    });
+  });
+}
+
+void testServerDetachSocketNoWriteHeaders() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      var response = request.response;
+      response.contentLength = 0;
+      response.detachSocket(writeHeaders: false).then((socket) {
+        Expect.isNotNull(socket);
+        var body = new StringBuffer();
+        socket.listen((data) => body.write(new String.fromCharCodes(data)),
+            onDone: () => Expect.equals("Some data", body.toString()));
+        socket.write("Test!");
+        socket.close();
+      });
+      server.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.write("GET / HTTP/1.1\r\n"
+          "content-length: 0\r\n\r\n"
+          "Some data");
+      var body = new StringBuffer();
+      socket.listen((data) => body.write(new String.fromCharCodes(data)),
+          onDone: () {
+        Expect.equals("Test!", body.toString());
+        socket.close();
+      });
+    });
+  });
+}
+
+void testBadServerDetachSocket() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      var response = request.response;
+      response.contentLength = 0;
+      response.close();
+      Expect.throws(response.detachSocket);
+      server.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.write("GET / HTTP/1.1\r\n"
+          "content-length: 0\r\n\r\n");
+      socket.listen((_) {}, onDone: () {
+        socket.close();
+      });
+    });
+  });
+}
+
+void testClientDetachSocket() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    server.listen((socket) {
+      int port = server.port;
+      socket.write("HTTP/1.1 200 OK\r\n"
+          "\r\n"
+          "Test!");
+      var body = new StringBuffer();
+      socket.listen((data) => body.write(new String.fromCharCodes(data)),
+          onDone: () {
+        List<String> lines = body.toString().split("\r\n");
+        Expect.equals(6, lines.length);
+        Expect.equals("GET / HTTP/1.1", lines[0]);
+        Expect.equals("", lines[4]);
+        Expect.equals("Some data", lines[5]);
+        lines.sort(); // Lines 1-3 becomes 3-5 in a fixed order.
+        Expect.equals("accept-encoding: gzip", lines[3]);
+        Expect.equals("content-length: 0", lines[4]);
+        Expect.equals("host: 127.0.0.1:${port}", lines[5]);
+        socket.close();
+      });
+      server.close();
+    });
+
+    var client = new HttpClient();
+    client.userAgent = null;
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.detachSocket().then((socket) {
+        var body = new StringBuffer();
+        socket.listen((data) => body.write(new String.fromCharCodes(data)),
+            onDone: () {
+          Expect.equals("Test!", body.toString());
+          client.close();
+        });
+        socket.write("Some data");
+        socket.close();
+      });
+    });
+  });
+}
+
+void testUpgradedConnection() {
+  asyncStart();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response.headers.set('connection', 'upgrade');
+      if (request.headers.value('upgrade') == 'mine') {
+        asyncStart();
+        request.response.detachSocket().then((socket) {
+          socket.cast<List<int>>().pipe(socket).then((_) {
+            asyncEnd();
+          });
+        });
+      } else {
+        request.response.close();
+      }
+    });
+
+    var client = new HttpClient();
+    client.userAgent = null;
+    client.get("127.0.0.1", server.port, "/").then((request) {
+      request.headers.set('upgrade', 'mine');
+      return request.close();
+    }).then((response) {
+      client.get("127.0.0.1", server.port, "/").then((request) {
+        response.detachSocket().then((socket) {
+          // We are testing that we can detach the socket, even though
+          // we made a new connection (testing it was not reused).
+          request.close().then((response) {
+            asyncStart();
+            response.listen(null, onDone: () {
+              server.close();
+              asyncEnd();
+            });
+            socket.add([0]);
+            socket.close();
+            socket.fold<List<int>>([], (l, d) => l..addAll(d)).then((data) {
+              asyncEnd();
+              Expect.listEquals([0], data);
+            });
+          });
+        });
+      });
+    });
+  });
+}
+
+void main() {
+  testServerDetachSocket();
+  testServerDetachSocketNoWriteHeaders();
+  testBadServerDetachSocket();
+  testClientDetachSocket();
+  testUpgradedConnection();
+}
diff --git a/tests/standalone/io/http_head_test.dart b/tests/standalone/io/http_head_test.dart
new file mode 100644
index 0000000..de19182
--- /dev/null
+++ b/tests/standalone/io/http_head_test.dart
@@ -0,0 +1,70 @@
+// 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:io";
+import "package:expect/expect.dart";
+
+void testHEAD(int totalConnections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      var response = request.response;
+      if (request.uri.path == "/test100") {
+        response.contentLength = 100;
+        response.close();
+      } else if (request.uri.path == "/test200") {
+        response.contentLength = 200;
+        List<int> data = new List<int>.filled(200, 0);
+        response.add(data);
+        response.close();
+      } else if (request.uri.path == "/testChunked100") {
+        List<int> data = new List<int>.filled(100, 0);
+        response.add(data);
+        response.close();
+      } else if (request.uri.path == "/testChunked200") {
+        List<int> data = new List<int>.filled(200, 0);
+        response.add(data);
+        response.close();
+      } else {
+        assert(false);
+      }
+    });
+
+    HttpClient client = new HttpClient();
+
+    int count = 0;
+
+    requestDone() {
+      count++;
+      if (count == totalConnections * 2) {
+        client.close();
+        server.close();
+      }
+    }
+
+    for (int i = 0; i < totalConnections; i++) {
+      int len = (i % 2 == 0) ? 100 : 200;
+      client
+          .open("HEAD", "127.0.0.1", server.port, "/test$len")
+          .then((request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(len, response.contentLength);
+        response.listen((_) => Expect.fail("Data from HEAD request"),
+            onDone: requestDone);
+      });
+
+      client
+          .open("HEAD", "127.0.0.1", server.port, "/testChunked$len")
+          .then((request) => request.close())
+          .then((HttpClientResponse response) {
+        Expect.equals(-1, response.contentLength);
+        response.listen((_) => Expect.fail("Data from HEAD request"),
+            onDone: requestDone);
+      });
+    }
+  });
+}
+
+void main() {
+  testHEAD(4);
+}
diff --git a/tests/standalone/io/http_headers_state_test.dart b/tests/standalone/io/http_headers_state_test.dart
new file mode 100644
index 0000000..764b3cd
--- /dev/null
+++ b/tests/standalone/io/http_headers_state_test.dart
@@ -0,0 +1,84 @@
+// 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:isolate";
+import "dart:io";
+import "package:expect/expect.dart";
+
+void test(int totalConnections, [String? body]) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      HttpResponse response = request.response;
+      // Cannot mutate request headers.
+      Expect.throws(() => request.headers.add("X-Request-Header", "value"),
+          (e) => e is HttpException);
+      Expect.equals("value", request.headers.value("X-Request-Header"));
+      request.listen((_) {}, onDone: () {
+        // Can still mutate response headers as long as no data has been sent.
+        response.headers.add("X-Response-Header", "value");
+        if (body != null) {
+          response.write(body);
+          // Cannot change state or reason when data has been sent.
+          Expect.throwsStateError(() => response.statusCode = 200);
+          Expect.throwsStateError(() => response.reasonPhrase = "OK");
+          // Cannot mutate response headers when data has been sent.
+          Expect.throws(
+              () => response.headers.add("X-Request-Header", "value2"),
+              (e) => e is HttpException);
+        }
+        response..close();
+        // Cannot change state or reason after connection is closed.
+        Expect.throwsStateError(() => response.statusCode = 200);
+        Expect.throwsStateError(() => response.reasonPhrase = "OK");
+        // Cannot mutate response headers after connection is closed.
+        Expect.throws(() => response.headers.add("X-Request-Header", "value3"),
+            (e) => e is HttpException);
+      });
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) {
+        if (body != null) {
+          request.contentLength = -1;
+        }
+        // Can still mutate request headers as long as no data has been sent.
+        request.headers.add("X-Request-Header", "value");
+        if (body != null) {
+          request.write(body);
+          // Cannot mutate request headers when data has been sent.
+          Expect.throws(() => request.headers.add("X-Request-Header", "value2"),
+              (e) => e is HttpException);
+        }
+        request.close();
+        // Cannot mutate request headers when data has been sent.
+        Expect.throws(() => request.headers.add("X-Request-Header", "value3"),
+            (e) => e is HttpException);
+        return request.done;
+      }).then((HttpClientResponse response) {
+        // Cannot mutate response headers.
+        Expect.throws(() => response.headers.add("X-Response-Header", "value"),
+            (e) => e is HttpException);
+        Expect.equals("value", response.headers.value("X-Response-Header"));
+        response.listen((_) {}, onDone: () {
+          // Do not close the connections before we have read the
+          // full response bodies for all connections.
+          if (++count == totalConnections) {
+            client.close();
+            server.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+void main() {
+  test(5);
+  test(5, "Hello and goodbye");
+}
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
new file mode 100644
index 0000000..ea53d8a
--- /dev/null
+++ b/tests/standalone/io/http_headers_test.dart
@@ -0,0 +1,602 @@
+// 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 = 2.6
+
+library dart._http;
+
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:developer";
+import "dart:io";
+import "dart:isolate";
+import "dart:math";
+import "dart:typed_data";
+import "package:expect/expect.dart";
+
+part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/http_impl.dart";
+part "../../../sdk/lib/_http/http_date.dart";
+part "../../../sdk/lib/_http/http_parser.dart";
+part "../../../sdk/lib/_http/http_headers.dart";
+part "../../../sdk/lib/_http/http_session.dart";
+
+void testMultiValue() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers[HttpHeaders.pragmaHeader]);
+  headers.add(HttpHeaders.pragmaHeader, "pragma1");
+  Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
+  Expect.equals(1, headers["pragma"].length);
+  Expect.equals(1, headers["Pragma"].length);
+  Expect.equals(1, headers["pragma"].length);
+  Expect.equals("pragma1", headers.value(HttpHeaders.pragmaHeader));
+
+  headers.add(HttpHeaders.pragmaHeader, "pragma2");
+  Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
+  Expect.throws(
+      () => headers.value(HttpHeaders.pragmaHeader), (e) => e is HttpException);
+
+  headers.add(HttpHeaders.pragmaHeader, ["pragma3", "pragma4"]);
+  Expect.listEquals(["pragma1", "pragma2", "pragma3", "pragma4"],
+      headers[HttpHeaders.pragmaHeader]);
+
+  headers.remove(HttpHeaders.pragmaHeader, "pragma3");
+  Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
+  Expect.listEquals(
+      ["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.pragmaHeader]);
+
+  headers.remove(HttpHeaders.pragmaHeader, "pragma3");
+  Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
+
+  headers.set(HttpHeaders.pragmaHeader, "pragma5");
+  Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
+
+  headers.set(HttpHeaders.pragmaHeader, ["pragma6", "pragma7"]);
+  Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
+
+  headers.removeAll(HttpHeaders.pragmaHeader);
+  Expect.isNull(headers[HttpHeaders.pragmaHeader]);
+}
+
+void testDate() {
+  DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+  String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
+  DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
+  String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
+
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers.date);
+  headers.date = date1;
+  Expect.equals(date1, headers.date);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
+  Expect.equals(1, headers[HttpHeaders.dateHeader].length);
+  headers.add(HttpHeaders.dateHeader, httpDate2);
+  Expect.equals(1, headers[HttpHeaders.dateHeader].length);
+  Expect.equals(date2, headers.date);
+  Expect.equals(httpDate2, headers.value(HttpHeaders.dateHeader));
+  headers.set(HttpHeaders.dateHeader, httpDate1);
+  Expect.equals(1, headers[HttpHeaders.dateHeader].length);
+  Expect.equals(date1, headers.date);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
+
+  headers.set(HttpHeaders.dateHeader, "xxx");
+  Expect.equals("xxx", headers.value(HttpHeaders.dateHeader));
+  Expect.equals(null, headers.date);
+}
+
+void testExpires() {
+  DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+  String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
+  DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
+  String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
+
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers.expires);
+  headers.expires = date1;
+  Expect.equals(date1, headers.expires);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
+  Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
+  headers.add(HttpHeaders.expiresHeader, httpDate2);
+  Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
+  Expect.equals(date2, headers.expires);
+  Expect.equals(httpDate2, headers.value(HttpHeaders.expiresHeader));
+  headers.set(HttpHeaders.expiresHeader, httpDate1);
+  Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
+  Expect.equals(date1, headers.expires);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
+
+  headers.set(HttpHeaders.expiresHeader, "xxx");
+  Expect.equals("xxx", headers.value(HttpHeaders.expiresHeader));
+  Expect.equals(null, headers.expires);
+}
+
+void testIfModifiedSince() {
+  DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
+  String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
+  DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
+  String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
+
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers.ifModifiedSince);
+  headers.ifModifiedSince = date1;
+  Expect.equals(date1, headers.ifModifiedSince);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
+  Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
+  headers.add(HttpHeaders.ifModifiedSinceHeader, httpDate2);
+  Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
+  Expect.equals(date2, headers.ifModifiedSince);
+  Expect.equals(httpDate2, headers.value(HttpHeaders.ifModifiedSinceHeader));
+  headers.set(HttpHeaders.ifModifiedSinceHeader, httpDate1);
+  Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
+  Expect.equals(date1, headers.ifModifiedSince);
+  Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
+
+  headers.set(HttpHeaders.ifModifiedSinceHeader, "xxx");
+  Expect.equals("xxx", headers.value(HttpHeaders.ifModifiedSinceHeader));
+  Expect.equals(null, headers.ifModifiedSince);
+}
+
+void testHost() {
+  String host = "www.google.com";
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers.host);
+  Expect.isNull(headers.port);
+  headers.host = host;
+  Expect.equals(host, headers.value(HttpHeaders.hostHeader));
+  headers.port = 1234;
+  Expect.equals("$host:1234", headers.value(HttpHeaders.hostHeader));
+  headers.port = HttpClient.defaultHttpPort;
+  Expect.equals(host, headers.value(HttpHeaders.hostHeader));
+
+  headers = new _HttpHeaders("1.1");
+  headers.add(HttpHeaders.hostHeader, host);
+  Expect.equals(host, headers.host);
+  Expect.equals(HttpClient.defaultHttpPort, headers.port);
+  headers.add(HttpHeaders.hostHeader, "$host:4567");
+  Expect.equals(1, headers[HttpHeaders.hostHeader].length);
+  Expect.equals(host, headers.host);
+  Expect.equals(4567, headers.port);
+
+  headers = new _HttpHeaders("1.1");
+  headers.add(HttpHeaders.hostHeader, "$host:xxx");
+  Expect.equals("$host:xxx", headers.value(HttpHeaders.hostHeader));
+  Expect.equals(host, headers.host);
+  Expect.isNull(headers.port);
+
+  headers = new _HttpHeaders("1.1");
+  headers.add(HttpHeaders.hostHeader, ":1234");
+  Expect.equals(":1234", headers.value(HttpHeaders.hostHeader));
+  Expect.isNull(headers.host);
+  Expect.equals(1234, headers.port);
+}
+
+void testTransferEncoding() {
+  expectChunked(headers) {
+    Expect.listEquals(headers['transfer-encoding'], ['chunked']);
+    Expect.isTrue(headers.chunkedTransferEncoding);
+  }
+
+  expectNonChunked(headers) {
+    Expect.isNull(headers['transfer-encoding']);
+    Expect.isFalse(headers.chunkedTransferEncoding);
+  }
+
+  _HttpHeaders headers;
+
+  headers = new _HttpHeaders("1.1");
+  headers.chunkedTransferEncoding = true;
+  expectChunked(headers);
+  headers.set('transfer-encoding', ['chunked']);
+  expectChunked(headers);
+
+  headers = new _HttpHeaders("1.1");
+  headers.set('transfer-encoding', ['chunked']);
+  expectChunked(headers);
+  headers.chunkedTransferEncoding = true;
+  expectChunked(headers);
+
+  headers = new _HttpHeaders("1.1");
+  headers.chunkedTransferEncoding = true;
+  headers.chunkedTransferEncoding = false;
+  expectNonChunked(headers);
+
+  headers = new _HttpHeaders("1.1");
+  headers.chunkedTransferEncoding = true;
+  headers.remove('transfer-encoding', 'chunked');
+  expectNonChunked(headers);
+
+  headers = new _HttpHeaders("1.1");
+  headers.set('transfer-encoding', ['chunked']);
+  headers.chunkedTransferEncoding = false;
+  expectNonChunked(headers);
+
+  headers = new _HttpHeaders("1.1");
+  headers.set('transfer-encoding', ['chunked']);
+  headers.remove('transfer-encoding', 'chunked');
+  expectNonChunked(headers);
+}
+
+void testEnumeration() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  Expect.isNull(headers[HttpHeaders.pragmaHeader]);
+  headers.add("My-Header-1", "value 1");
+  headers.add("My-Header-2", "value 2");
+  headers.add("My-Header-1", "value 3");
+  bool myHeader1 = false;
+  bool myHeader2 = false;
+  int totalValues = 0;
+  headers.forEach((String name, List<String> values) {
+    totalValues += values.length;
+    if (name == "my-header-1") {
+      myHeader1 = true;
+      Expect.isTrue(values.indexOf("value 1") != -1);
+      Expect.isTrue(values.indexOf("value 3") != -1);
+    }
+    if (name == "my-header-2") {
+      myHeader2 = true;
+      Expect.isTrue(values.indexOf("value 2") != -1);
+    }
+  });
+  Expect.isTrue(myHeader1);
+  Expect.isTrue(myHeader2);
+  Expect.equals(3, totalValues);
+}
+
+void testHeaderValue() {
+  void check(HeaderValue headerValue, String value,
+      [Map<String, String> parameters]) {
+    Expect.equals(value, headerValue.value);
+    if (parameters != null) {
+      Expect.equals(parameters.length, headerValue.parameters.length);
+      parameters.forEach((String name, String value) {
+        Expect.equals(value, headerValue.parameters[name]);
+      });
+    } else {
+      Expect.equals(0, headerValue.parameters.length);
+    }
+  }
+
+  HeaderValue headerValue;
+  headerValue =
+      HeaderValue.parse("xxx; aaa=bbb; ccc=\"\\\";\\a\"; ddd=\"    \"");
+  check(headerValue, "xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": "    "});
+  headerValue =
+      new HeaderValue("xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": "    "});
+  check(headerValue, "xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": "    "});
+
+  headerValue = HeaderValue.parse("attachment; filename=genome.jpeg;"
+      "modification-date=\"Wed, 12 February 1997 16:29:51 -0500\"");
+  var parameters = {
+    "filename": "genome.jpeg",
+    "modification-date": "Wed, 12 February 1997 16:29:51 -0500"
+  };
+  check(headerValue, "attachment", parameters);
+  headerValue = new HeaderValue("attachment", parameters);
+  check(headerValue, "attachment", parameters);
+  headerValue = HeaderValue.parse("  attachment  ;filename=genome.jpeg  ;"
+      "modification-date = \"Wed, 12 February 1997 16:29:51 -0500\"");
+  check(headerValue, "attachment", parameters);
+  headerValue = HeaderValue.parse("xxx; aaa; bbb; ccc");
+  check(headerValue, "xxx", {"aaa": null, "bbb": null, "ccc": null});
+}
+
+void testContentType() {
+  void check(ContentType contentType, String primaryType, String subType,
+      [Map<String, String> parameters]) {
+    Expect.equals(primaryType, contentType.primaryType);
+    Expect.equals(subType, contentType.subType);
+    Expect.equals("$primaryType/$subType", contentType.value);
+    if (parameters != null) {
+      Expect.equals(parameters.length, contentType.parameters.length);
+      parameters.forEach((String name, String value) {
+        Expect.equals(value, contentType.parameters[name]);
+      });
+    } else {
+      Expect.equals(0, contentType.parameters.length);
+    }
+  }
+
+  ContentType contentType;
+  contentType = new ContentType("", "");
+  Expect.equals("", contentType.primaryType);
+  Expect.equals("", contentType.subType);
+  Expect.equals("/", contentType.value);
+  Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
+
+  contentType = ContentType.parse("text/html");
+  check(contentType, "text", "html");
+  Expect.equals("text/html", contentType.toString());
+  contentType = new ContentType("text", "html", charset: "utf-8");
+  check(contentType, "text", "html", {"charset": "utf-8"});
+  Expect.equals("text/html; charset=utf-8", contentType.toString());
+  Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
+
+  contentType = new ContentType("text", "html",
+      parameters: {"CHARSET": "UTF-8", "xxx": "YYY"});
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "YYY"});
+  String s = contentType.toString();
+  bool expectedToString = (s == "text/html; charset=utf-8; xxx=YYY" ||
+      s == "text/html; xxx=YYY; charset=utf-8");
+  Expect.isTrue(expectedToString);
+  contentType = ContentType.parse("text/html; CHARSET=UTF-8; xxx=YYY");
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "YYY"});
+  Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
+
+  contentType = new ContentType("text", "html",
+      charset: "ISO-8859-1", parameters: {"CHARSET": "UTF-8", "xxx": "yyy"});
+  check(contentType, "text", "html", {"charset": "iso-8859-1", "xxx": "yyy"});
+  s = contentType.toString();
+  expectedToString = (s == "text/html; charset=iso-8859-1; xxx=yyy" ||
+      s == "text/html; xxx=yyy; charset=iso-8859-1");
+  Expect.isTrue(expectedToString);
+
+  contentType = ContentType.parse("text/html");
+  check(contentType, "text", "html");
+  contentType = ContentType.parse(" text/html  ");
+  check(contentType, "text", "html");
+  contentType = ContentType.parse("text/html; charset=utf-8");
+  check(contentType, "text", "html", {"charset": "utf-8"});
+  contentType = ContentType.parse("  text/html  ;  charset  =  utf-8  ");
+  check(contentType, "text", "html", {"charset": "utf-8"});
+  contentType = ContentType.parse("text/html; charset=utf-8; xxx=yyy");
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
+  contentType =
+      ContentType.parse("  text/html  ;  charset  =  utf-8  ;  xxx=yyy  ");
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
+  contentType = ContentType.parse('text/html; charset=utf-8; xxx="yyy"');
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
+  contentType =
+      ContentType.parse("  text/html  ;  charset  =  utf-8  ;  xxx=yyy  ");
+  check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
+
+  contentType = ContentType.parse("text/html; charset=;");
+  check(contentType, "text", "html", {"charset": null});
+  contentType = ContentType.parse("text/html; charset;");
+  check(contentType, "text", "html", {"charset": null});
+
+  // Test builtin content types.
+  check(ContentType.text, "text", "plain", {"charset": "utf-8"});
+  check(ContentType.html, "text", "html", {"charset": "utf-8"});
+  check(ContentType.json, "application", "json", {"charset": "utf-8"});
+  check(ContentType.binary, "application", "octet-stream");
+}
+
+void testKnownContentTypes() {
+  // Well known content types used by the VM service.
+  ContentType.parse('text/html; charset=UTF-8');
+  ContentType.parse('application/dart; charset=UTF-8');
+  ContentType.parse('application/javascript; charset=UTF-8');
+  ContentType.parse('text/css; charset=UTF-8');
+  ContentType.parse('image/gif');
+  ContentType.parse('image/png');
+  ContentType.parse('image/jpeg');
+  ContentType.parse('image/jpeg');
+  ContentType.parse('image/svg+xml');
+  ContentType.parse('text/plain');
+}
+
+void testContentTypeCache() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  headers.set(HttpHeaders.contentTypeHeader, "text/html");
+  Expect.equals("text", headers.contentType.primaryType);
+  Expect.equals("html", headers.contentType.subType);
+  Expect.equals("text/html", headers.contentType.value);
+  headers.set(HttpHeaders.contentTypeHeader, "text/plain; charset=utf-8");
+  Expect.equals("text", headers.contentType.primaryType);
+  Expect.equals("plain", headers.contentType.subType);
+  Expect.equals("text/plain", headers.contentType.value);
+  headers.removeAll(HttpHeaders.contentTypeHeader);
+  Expect.isNull(headers.contentType);
+}
+
+void testCookie() {
+  test(String name, String value) {
+    void checkCookiesEquals(a, b) {
+      Expect.equals(a.name, b.name);
+      Expect.equals(a.value, b.value);
+      Expect.equals(a.expires, b.expires);
+      Expect.equals(a.toString(), b.toString());
+    }
+
+    void checkCookie(cookie, s) {
+      Expect.equals(s, cookie.toString());
+      var c = new _Cookie.fromSetCookieValue(s);
+      checkCookiesEquals(cookie, c);
+    }
+
+    Cookie cookie;
+    cookie = new Cookie(name, value);
+    Expect.equals("$name=$value; HttpOnly", cookie.toString());
+    DateTime date = new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
+    cookie.expires = date;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; HttpOnly");
+    cookie.maxAge = 567;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; Max-Age=567"
+        "; HttpOnly");
+    cookie.domain = "example.com";
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; Max-Age=567"
+        "; Domain=example.com"
+        "; HttpOnly");
+    cookie.path = "/xxx";
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; Max-Age=567"
+        "; Domain=example.com"
+        "; Path=/xxx"
+        "; HttpOnly");
+    cookie.secure = true;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; Max-Age=567"
+        "; Domain=example.com"
+        "; Path=/xxx"
+        "; Secure"
+        "; HttpOnly");
+    cookie.httpOnly = false;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
+        "; Max-Age=567"
+        "; Domain=example.com"
+        "; Path=/xxx"
+        "; Secure");
+    cookie.expires = null;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Max-Age=567"
+        "; Domain=example.com"
+        "; Path=/xxx"
+        "; Secure");
+    cookie.maxAge = null;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Domain=example.com"
+        "; Path=/xxx"
+        "; Secure");
+    cookie.domain = null;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Path=/xxx"
+        "; Secure");
+    cookie.path = null;
+    checkCookie(
+        cookie,
+        "$name=$value"
+        "; Secure");
+    cookie.secure = false;
+    checkCookie(cookie, "$name=$value");
+  }
+
+  test("name", "value");
+  test("abc", "def");
+  test("ABC", "DEF");
+  test("Abc", "Def");
+  test("SID", "sJdkjKSJD12343kjKj78");
+}
+
+void testInvalidCookie() {
+  Expect.throws(() => new _Cookie.fromSetCookieValue(""));
+  Expect.throws(() => new _Cookie.fromSetCookieValue("="));
+  Expect.throws(() => new _Cookie.fromSetCookieValue("=xxx"));
+  Expect.throws(() => new _Cookie.fromSetCookieValue("xxx"));
+  Expect.throws(
+      () => new _Cookie.fromSetCookieValue("xxx=yyy; expires=12 jan 2013"));
+  Expect.throws(() => new _Cookie.fromSetCookieValue("x x = y y"));
+  Expect.throws(() => new _Cookie("[4", "y"));
+  Expect.throws(() => new _Cookie("4", "y\""));
+
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  headers.set(
+      'Cookie', 'DARTSESSID=d3d6fdd78d51aaaf2924c32e991f4349; undefined');
+  Expect.equals('DARTSESSID', headers._parseCookies().single.name);
+  Expect.equals(
+      'd3d6fdd78d51aaaf2924c32e991f4349', headers._parseCookies().single.value);
+}
+
+void testHeaderLists() {
+  HttpHeaders.generalHeaders.forEach((x) => null);
+  HttpHeaders.entityHeaders.forEach((x) => null);
+  HttpHeaders.responseHeaders.forEach((x) => null);
+  HttpHeaders.requestHeaders.forEach((x) => null);
+}
+
+void testInvalidFieldName() {
+  void test(String field) {
+    _HttpHeaders headers = new _HttpHeaders("1.1");
+    Expect.throwsFormatException(() => headers.add(field, "value"));
+    Expect.throwsFormatException(() => headers.set(field, "value"));
+    Expect.throwsFormatException(() => headers.remove(field, "value"));
+    Expect.throwsFormatException(() => headers.removeAll(field));
+  }
+
+  test('\r');
+  test('\n');
+  test(',');
+  test('test\x00');
+}
+
+void testInvalidFieldValue() {
+  void test(value, {bool remove: true}) {
+    _HttpHeaders headers = new _HttpHeaders("1.1");
+    Expect.throwsFormatException(() => headers.add("field", value));
+    Expect.throwsFormatException(() => headers.set("field", value));
+    if (remove) {
+      Expect.throwsFormatException(() => headers.remove("field", value));
+    }
+  }
+
+  test('\r');
+  test('\n');
+  test('test\x00');
+  // Test we handle other types correctly.
+  test(new StringBuffer('\x00'), remove: false);
+}
+
+void testClear() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  headers.add("a", "b");
+  headers.contentLength = 7;
+  headers.chunkedTransferEncoding = true;
+  headers.clear();
+  Expect.isNull(headers["a"]);
+  Expect.equals(headers.contentLength, -1);
+  Expect.isFalse(headers.chunkedTransferEncoding);
+}
+
+void testFolding() {
+  _HttpHeaders headers = new _HttpHeaders("1.1");
+  headers.add("a", "b");
+  headers.add("a", "c");
+  headers.add("a", "d");
+  // no folding by default
+  Expect.isTrue(headers.toString().contains('b, c, d'));
+  // Header name should be case insensitive
+  headers.noFolding('A');
+  var str = headers.toString();
+  Expect.isTrue(str.contains(': b'));
+  Expect.isTrue(str.contains(': c'));
+  Expect.isTrue(str.contains(': d'));
+}
+
+main() {
+  testMultiValue();
+  testDate();
+  testExpires();
+  testIfModifiedSince();
+  testHost();
+  testTransferEncoding();
+  testEnumeration();
+  testHeaderValue();
+  testContentType();
+  testKnownContentTypes();
+  testContentTypeCache();
+  testCookie();
+  testInvalidCookie();
+  testHeaderLists();
+  testInvalidFieldName();
+  testInvalidFieldValue();
+  testClear();
+  testFolding();
+}
diff --git a/tests/standalone/io/http_ipv6_test.dart b/tests/standalone/io/http_ipv6_test.dart
new file mode 100644
index 0000000..ee1d0c5
--- /dev/null
+++ b/tests/standalone/io/http_ipv6_test.dart
@@ -0,0 +1,46 @@
+// (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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+// Client makes a HTTP 1.0 request without connection keep alive. The
+// server sets a content length but still needs to close the
+// connection as there is no keep alive.
+void testHttpIPv6() {
+  asyncStart();
+  HttpServer.bind("::", 0).then((server) {
+    server.listen((HttpRequest request) {
+      Expect.equals(request.headers["host"]![0], "[::1]:${server.port}");
+      Expect.equals(request.requestedUri.host, "::1");
+      request.response.close();
+    });
+
+    var client = new HttpClient();
+    var url = Uri.parse('http://[::1]:${server.port}/xxx');
+    Expect.equals(url.host, '::1');
+    client
+        .openUrl('GET', url)
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals(response.statusCode, HttpStatus.ok);
+    }).whenComplete(() {
+      server.close();
+      client.close();
+      asyncEnd();
+    });
+  });
+}
+
+void main() {
+  testHttpIPv6();
+}
diff --git a/tests/standalone/io/http_keep_alive_test.dart b/tests/standalone/io/http_keep_alive_test.dart
new file mode 100644
index 0000000..a9d794b
--- /dev/null
+++ b/tests/standalone/io/http_keep_alive_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "package:expect/expect.dart";
+
+Future getData(HttpClient client, int port, bool chunked, int length) {
+  return client
+      .get("127.0.0.1", port, "/?chunked=$chunked&length=$length")
+      .then((request) => request.close())
+      .then((response) {
+    return response
+        .fold<int>(0, (bytes, data) => bytes + data.length)
+        .then((bytes) {
+      Expect.equals(length, bytes);
+    });
+  });
+}
+
+Future<HttpServer> startServer() {
+  return HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      bool chunked = request.uri.queryParameters["chunked"] == "true";
+      int length = int.parse(request.uri.queryParameters["length"]!);
+      var buffer = new List<int>.filled(length, 0);
+      if (!chunked) request.response.contentLength = length;
+      request.response.add(buffer);
+      request.response.close();
+    });
+    return server;
+  });
+}
+
+testKeepAliveNonChunked() {
+  startServer().then((server) {
+    var client = new HttpClient();
+
+    getData(client, server.port, false, 100)
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) {
+      server.close();
+      client.close();
+    });
+  });
+}
+
+testKeepAliveChunked() {
+  startServer().then((server) {
+    var client = new HttpClient();
+
+    getData(client, server.port, true, 100)
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) {
+      server.close();
+      client.close();
+    });
+  });
+}
+
+testKeepAliveMixed() {
+  startServer().then((server) {
+    var client = new HttpClient();
+
+    getData(client, server.port, true, 100)
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) => getData(client, server.port, true, 100))
+        .then((_) => getData(client, server.port, false, 100))
+        .then((_) {
+      server.close();
+      client.close();
+    });
+  });
+}
+
+void main() {
+  testKeepAliveNonChunked();
+  testKeepAliveChunked();
+  testKeepAliveMixed();
+}
diff --git a/tests/standalone/io/http_linklocal_ipv6_test.dart b/tests/standalone/io/http_linklocal_ipv6_test.dart
new file mode 100644
index 0000000..ea4e54d
--- /dev/null
+++ b/tests/standalone/io/http_linklocal_ipv6_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.
+import 'dart:async';
+import 'dart:io';
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+void main() {
+  // A virtual tun/tap interface should be created with following instrutctions:
+  // Create an interface with name [tap0],
+  //    sudo ip tuntap add name [tap0] mode tap
+  // Assign an ipv6 address [fe80:1::1],
+  //    sudo ip -6 addr add dev [tap0] [fe80:1::1] scope link nodad
+  // Check for virtual interface with ipv6 set,
+  //    ip address show
+  asyncStart();
+  try {
+    // Make sure the address here is the same as what it shows in "ip address show"
+    var ipv6 = 'fe80:1::10%tap0';
+    HttpServer.bind(ipv6, 0).then((server) {
+      server.listen((request) {
+        var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {
+          request.response
+              .write('data:${new DateTime.now().millisecondsSinceEpoch}\n\n');
+        });
+        request.response.done.whenComplete(() {
+          timer.cancel();
+        }).catchError((_) {});
+      });
+
+      var client = new HttpClient();
+      client
+          .getUrl(Uri.parse("http://[${ipv6}]:${server.port}"))
+          .then((request) => request.close())
+          .then((response) {
+        print(
+            'reponse: status code: ${response.statusCode}, reason: ${response.reasonPhrase}');
+        int bytes = 0;
+        response.listen((data) {
+          bytes += data.length;
+          if (bytes > 100) {
+            client.close(force: true);
+          }
+        }, onError: (error) {
+          server.close();
+        });
+      });
+      asyncEnd();
+    });
+  } catch (e) {
+    Expect.fail('SocketException: $e');
+    asyncEnd();
+  }
+}
diff --git a/tests/standalone/io/http_loopback_test.dart b/tests/standalone/io/http_loopback_test.dart
new file mode 100644
index 0000000..3e476ea
--- /dev/null
+++ b/tests/standalone/io/http_loopback_test.dart
@@ -0,0 +1,77 @@
+// 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:io";
+import "package:expect/expect.dart";
+
+/// Creates a callback that listens for incomming connections.
+/// If [remotePorts] is not null then callback would add remote port of each
+/// new connection to the given list.
+makeListener([List<int>? remotePorts]) {
+  return (RawSocket serverSide) {
+    serveData(RawSocketEvent event) {
+      serverSide.shutdown(SocketDirection.send);
+    }
+
+    remotePorts?.add(serverSide.remotePort);
+    serverSide.listen(serveData);
+  };
+}
+
+/// Verify that you can't connect to loopback via mismatching protocol, e.g.
+/// if the server is listening to IPv4 then you can't connect via IPv6.
+Future<void> failureTest(
+    InternetAddress serverAddr, InternetAddress clientAddr) async {
+  final remotePorts = <int>[];
+  final server = await RawServerSocket.bind(serverAddr, 0);
+  server.listen(makeListener(remotePorts));
+
+  bool success = false;
+  try {
+    final client = await RawSocket.connect(clientAddr, server.port);
+    final clientPort = client.port;
+
+    // We might actually succeed in connecting somewhere (e.g. to another test
+    // which by chance started listening to the same port).
+    // To make this test more robust we add a check that verifies that we did
+    // not connect to our server by checking if clientPort is within
+    // the list of remotePorts observed by the server. It should not be there.
+    await Future.delayed(Duration(seconds: 2));
+    success = !remotePorts.contains(clientPort);
+    await client.close();
+  } on SocketException catch (e) {
+    // We expect that we fail to connect to IPv4 server via IPv6 client and
+    // vice versa.
+    success = true;
+  } catch (e) {
+    Expect.fail('Unexpected exception: $e');
+  } finally {
+    Expect.isTrue(success,
+        'Unexpected connection to $serverAddr via $clientAddr address!');
+    await server.close();
+  }
+}
+
+Future<void> successTest(InternetAddress address) async {
+  final server = await RawServerSocket.bind(address, 0);
+  server.listen(makeListener());
+  bool testFailure = false;
+  try {
+    final client = await RawSocket.connect(address, server.port);
+    await client.close();
+  } catch (e) {
+    testFailure = true;
+  } finally {
+    Expect.equals(testFailure, false);
+    await server.close();
+  }
+}
+
+main() async {
+  await failureTest(InternetAddress.loopbackIPv4, InternetAddress.loopbackIPv6);
+  await failureTest(InternetAddress.loopbackIPv6, InternetAddress.loopbackIPv4);
+  await successTest(InternetAddress.loopbackIPv4);
+  await successTest(InternetAddress.loopbackIPv6);
+}
diff --git a/tests/standalone/io/http_no_reason_phrase_test.dart b/tests/standalone/io/http_no_reason_phrase_test.dart
new file mode 100644
index 0000000..2a1558e
--- /dev/null
+++ b/tests/standalone/io/http_no_reason_phrase_test.dart
@@ -0,0 +1,44 @@
+// (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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:isolate";
+import "dart:io";
+import "package:expect/expect.dart";
+
+// Test that a response line without any reason phrase is handled.
+void missingReasonPhrase(int statusCode, bool includeSpace) {
+  var client = new HttpClient();
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    server.listen((client) {
+      client.listen(null);
+      if (includeSpace) {
+        client.write("HTTP/1.1 $statusCode \r\n\r\n");
+      } else {
+        client.write("HTTP/1.1 $statusCode\r\n\r\n");
+      }
+      client.close();
+    });
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/"))
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals(statusCode, response.statusCode);
+      Expect.equals("", response.reasonPhrase);
+      return response.drain();
+    }).whenComplete(() => server.close());
+  });
+}
+
+void main() {
+  missingReasonPhrase(HttpStatus.ok, true);
+  missingReasonPhrase(HttpStatus.internalServerError, true);
+  missingReasonPhrase(HttpStatus.ok, false);
+  missingReasonPhrase(HttpStatus.internalServerError, false);
+}
diff --git a/tests/standalone/io/http_outgoing_size_test.dart b/tests/standalone/io/http_outgoing_size_test.dart
new file mode 100644
index 0000000..06a33a8
--- /dev/null
+++ b/tests/standalone/io/http_outgoing_size_test.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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+void testChunkedBufferSizeMsg() {
+  // Buffer of same size as our internal buffer, minus 4. Makes us hit the
+  // boundary.
+  var sendData = new Uint8List(8 * 1024 - 4);
+  for (int i = 0; i < sendData.length; i++) sendData[i] = i % 256;
+
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+    server.listen((request) {
+      // Chunked is on by default. Be sure no data is lost when sending several
+      // chunks of data.
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.add(sendData);
+      request.response.close();
+    });
+    var client = new HttpClient();
+    client.get('127.0.0.1', server.port, '/').then((request) {
+      request.headers.set(HttpHeaders.acceptEncodingHeader, "");
+      return request.close();
+    }).then((response) {
+      var buffer = [];
+      response.listen((data) => buffer.addAll(data), onDone: () {
+        Expect.equals(sendData.length * 8, buffer.length);
+        for (int i = 0; i < buffer.length; i++) {
+          Expect.equals(sendData[i % sendData.length], buffer[i]);
+        }
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testChunkedBufferSizeMsg();
+}
diff --git a/tests/standalone/io/http_override_test.dart b/tests/standalone/io/http_override_test.dart
new file mode 100644
index 0000000..4be81c7
--- /dev/null
+++ b/tests/standalone/io/http_override_test.dart
@@ -0,0 +1,221 @@
+// 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:io';
+
+import "package:expect/expect.dart";
+
+class MyHttpClient1 implements HttpClient {
+  String? userAgent = "MyHttpClient1";
+
+  MyHttpClient1(SecurityContext? context);
+
+  Duration idleTimeout = Duration.zero;
+  Duration? connectionTimeout;
+  int? maxConnectionsPerHost;
+  bool autoUncompress = true;
+  bool enableTimelineLogging = false;
+
+  Future<HttpClientRequest> open(
+          String method, String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> openUrl(String method, Uri url) => throw "";
+  Future<HttpClientRequest> get(String host, int port, String path) => throw "";
+  Future<HttpClientRequest> getUrl(Uri url) => throw "";
+  Future<HttpClientRequest> post(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> postUrl(Uri url) => throw "";
+  Future<HttpClientRequest> put(String host, int port, String path) => throw "";
+  Future<HttpClientRequest> putUrl(Uri url) => throw "";
+  Future<HttpClientRequest> delete(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> deleteUrl(Uri url) => throw "";
+  Future<HttpClientRequest> patch(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> patchUrl(Uri url) => throw "";
+  Future<HttpClientRequest> head(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> headUrl(Uri url) => throw "";
+  set authenticate(Future<bool> f(Uri url, String scheme, String realm)?) {}
+  void addCredentials(
+      Uri url, String realm, HttpClientCredentials credentials) {}
+  set findProxy(String f(Uri url)?) {}
+  set authenticateProxy(
+      Future<bool> f(String host, int port, String scheme, String realm)?) {}
+  void addProxyCredentials(
+      String host, int port, String realm, HttpClientCredentials credentials) {}
+  set badCertificateCallback(
+      bool callback(X509Certificate cert, String host, int port)?) {}
+  void close({bool force: false}) {}
+}
+
+class MyHttpClient2 implements HttpClient {
+  String? userAgent = "MyHttpClient2";
+
+  MyHttpClient2(SecurityContext? context);
+
+  Duration idleTimeout = Duration.zero;
+  Duration? connectionTimeout;
+  int? maxConnectionsPerHost;
+  bool autoUncompress = true;
+  bool enableTimelineLogging = false;
+
+  Future<HttpClientRequest> open(
+          String method, String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> openUrl(String method, Uri url) => throw "";
+  Future<HttpClientRequest> get(String host, int port, String path) => throw "";
+  Future<HttpClientRequest> getUrl(Uri url) => throw "";
+  Future<HttpClientRequest> post(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> postUrl(Uri url) => throw "";
+  Future<HttpClientRequest> put(String host, int port, String path) => throw "";
+  Future<HttpClientRequest> putUrl(Uri url) => throw "";
+  Future<HttpClientRequest> delete(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> deleteUrl(Uri url) => throw "";
+  Future<HttpClientRequest> patch(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> patchUrl(Uri url) => throw "";
+  Future<HttpClientRequest> head(String host, int port, String path) =>
+      throw "";
+  Future<HttpClientRequest> headUrl(Uri url) => throw "";
+  set authenticate(Future<bool> f(Uri url, String scheme, String realm)?) {}
+  void addCredentials(
+      Uri url, String realm, HttpClientCredentials credentials) {}
+  set findProxy(String f(Uri url)?) {}
+  set authenticateProxy(
+      Future<bool> f(String host, int port, String scheme, String realm)?) {}
+  void addProxyCredentials(
+      String host, int port, String realm, HttpClientCredentials credentials) {}
+  set badCertificateCallback(
+      bool callback(X509Certificate cert, String host, int port)?) {}
+  void close({bool force: false}) {}
+}
+
+class MyHttpOverrides extends HttpOverrides {
+  @override
+  HttpClient createHttpClient(SecurityContext? context) {
+    return new MyHttpClient1(context);
+  }
+}
+
+HttpClient myCreateHttp1Client(SecurityContext? context) {
+  return new MyHttpClient1(context);
+}
+
+HttpClient myCreateHttp2Client(SecurityContext? context) {
+  return new MyHttpClient2(context);
+}
+
+String myFindProxyFromEnvironment(Uri url, Map<String, String>? environment) {
+  return "proxy";
+}
+
+withHttpOverridesTest() {
+  HttpOverrides.runZoned(() {
+    var httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+  }, createHttpClient: myCreateHttp1Client);
+  var httpClient = new HttpClient();
+  Expect.isTrue(httpClient is HttpClient);
+  Expect.isTrue(httpClient is! MyHttpClient1);
+}
+
+nestedWithHttpOverridesTest() {
+  HttpOverrides.runZoned(() {
+    var httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+    HttpOverrides.runZoned(() {
+      var httpClient = new HttpClient();
+      Expect.isNotNull(httpClient);
+      Expect.isTrue(httpClient is MyHttpClient2);
+      Expect.equals((new MyHttpClient2(null)).userAgent, httpClient.userAgent);
+    }, createHttpClient: myCreateHttp2Client);
+    httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+  }, createHttpClient: myCreateHttp1Client);
+  var httpClient = new HttpClient();
+  Expect.isTrue(httpClient is HttpClient);
+  Expect.isTrue(httpClient is! MyHttpClient1);
+  Expect.isTrue(httpClient is! MyHttpClient2);
+}
+
+nestedDifferentOverridesTest() {
+  HttpOverrides.runZoned(() {
+    var httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+    HttpOverrides.runZoned(() {
+      var httpClient = new HttpClient();
+      Expect.isNotNull(httpClient);
+      Expect.isTrue(httpClient is MyHttpClient1);
+      Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+      Expect.equals(myFindProxyFromEnvironment(new Uri(), null),
+          HttpClient.findProxyFromEnvironment(new Uri()));
+    }, findProxyFromEnvironment: myFindProxyFromEnvironment);
+    httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+  }, createHttpClient: myCreateHttp1Client);
+  var httpClient = new HttpClient();
+  Expect.isTrue(httpClient is HttpClient);
+  Expect.isTrue(httpClient is! MyHttpClient1);
+  Expect.isTrue(httpClient is! MyHttpClient2);
+}
+
+zonedWithHttpOverridesTest() {
+  HttpOverrides.runWithHttpOverrides(() {
+    var httpClient = new HttpClient();
+    Expect.isNotNull(httpClient);
+    Expect.isTrue(httpClient is MyHttpClient1);
+    Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+  }, new MyHttpOverrides());
+}
+
+globalHttpOverridesTest() {
+  HttpOverrides.global = new MyHttpOverrides();
+  var httpClient = new HttpClient();
+  Expect.isNotNull(httpClient);
+  Expect.isTrue(httpClient is MyHttpClient1);
+  Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+  HttpOverrides.global = null;
+  httpClient = new HttpClient();
+  Expect.isTrue(httpClient is HttpClient);
+  Expect.isTrue(httpClient is! MyHttpClient1);
+}
+
+globalHttpOverridesZoneTest() {
+  HttpOverrides.global = new MyHttpOverrides();
+  runZoned(() {
+    runZoned(() {
+      var httpClient = new HttpClient();
+      Expect.isNotNull(httpClient);
+      Expect.isTrue(httpClient is MyHttpClient1);
+      Expect.equals((new MyHttpClient1(null)).userAgent, httpClient.userAgent);
+    });
+  });
+  HttpOverrides.global = null;
+  var httpClient = new HttpClient();
+  Expect.isTrue(httpClient is HttpClient);
+  Expect.isTrue(httpClient is! MyHttpClient1);
+}
+
+main() {
+  withHttpOverridesTest();
+  nestedWithHttpOverridesTest();
+  nestedDifferentOverridesTest();
+  zonedWithHttpOverridesTest();
+  globalHttpOverridesTest();
+  globalHttpOverridesZoneTest();
+}
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
new file mode 100644
index 0000000..6951916
--- /dev/null
+++ b/tests/standalone/io/http_parser_test.dart
@@ -0,0 +1,824 @@
+// 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 = 2.6
+
+library dart._http;
+
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:developer";
+import "dart:io";
+import "dart:isolate";
+import "dart:math";
+import "dart:typed_data";
+import "package:expect/expect.dart";
+
+part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/http_impl.dart";
+part "../../../sdk/lib/_http/http_date.dart";
+part "../../../sdk/lib/_http/http_parser.dart";
+part "../../../sdk/lib/_http/http_headers.dart";
+part "../../../sdk/lib/_http/http_session.dart";
+
+class HttpParserTest {
+  static void runAllTests() {
+    testParseRequest();
+    testParseResponse();
+    testParseInvalidRequest();
+    testParseInvalidResponse();
+  }
+
+  static void _testParseRequest(
+      String request, String expectedMethod, String expectedUri,
+      {int expectedTransferLength: 0,
+      int expectedBytesReceived: 0,
+      Map<String, String> expectedHeaders: null,
+      bool chunked: false,
+      bool upgrade: false,
+      int unparsedLength: 0,
+      bool connectionClose: false,
+      String expectedVersion: "1.1"}) {
+    StreamController<Uint8List> controller;
+    void reset() {
+      _HttpParser httpParser = new _HttpParser.requestParser();
+      controller = new StreamController(sync: true);
+      var port1 = new ReceivePort();
+      var port2 = new ReceivePort();
+
+      String method;
+      Uri uri;
+      _HttpHeaders headers;
+      int contentLength;
+      int bytesReceived;
+      int unparsedBytesReceived;
+      bool upgraded;
+
+      httpParser.listenToStream(controller.stream);
+      var subscription = httpParser.listen((incoming) {
+        method = incoming.method;
+        uri = incoming.uri;
+        headers = incoming.headers;
+        upgraded = incoming.upgraded;
+        Expect.equals(upgrade, upgraded);
+
+        if (!chunked) {
+          Expect.equals(expectedTransferLength, incoming.transferLength);
+        } else {
+          Expect.equals(-1, incoming.transferLength);
+        }
+        if (expectedHeaders != null) {
+          expectedHeaders.forEach((String name, String value) =>
+              Expect.equals(value, headers[name][0]));
+        }
+        incoming.listen((List<int> data) {
+          Expect.isFalse(upgraded);
+          bytesReceived += data.length;
+        }, onDone: () {
+          port2.close();
+          Expect.equals(expectedMethod, method);
+          Expect.stringEquals(expectedUri, uri.toString());
+          Expect.equals(expectedVersion, headers.protocolVersion);
+          if (upgrade) {
+            Expect.equals(0, bytesReceived);
+            // port1 is closed by the listener on the detached data.
+          } else {
+            Expect.equals(expectedBytesReceived, bytesReceived);
+          }
+        });
+
+        if (upgraded) {
+          port1.close();
+          httpParser.detachIncoming().listen((List<int> data) {
+            unparsedBytesReceived += data.length;
+          }, onDone: () {
+            Expect.equals(unparsedLength, unparsedBytesReceived);
+            port2.close();
+          });
+        }
+
+        incoming.dataDone.then((_) {
+          port1.close();
+        });
+      });
+
+      method = null;
+      uri = null;
+      headers = null;
+      bytesReceived = 0;
+      unparsedBytesReceived = 0;
+      upgraded = false;
+    }
+
+    void testWrite(List<int> requestData, [int chunkSize = -1]) {
+      if (chunkSize == -1) chunkSize = requestData.length;
+      reset();
+      for (int pos = 0; pos < requestData.length; pos += chunkSize) {
+        int end = min(requestData.length, pos + chunkSize);
+        controller.add(requestData.sublist(pos, end));
+      }
+      controller.close();
+    }
+
+    // Test parsing the request three times delivering the data in
+    // different chunks.
+    List<int> requestData = new Uint8List.fromList(request.codeUnits);
+    testWrite(requestData);
+    testWrite(requestData, 10);
+    testWrite(requestData, 1);
+  }
+
+  static void _testParseRequestLean(
+      String request, String expectedMethod, String expectedUri,
+      {int expectedTransferLength: 0,
+      int expectedBytesReceived: 0,
+      Map<String, String> expectedHeaders: null,
+      bool chunked: false,
+      bool upgrade: false,
+      int unparsedLength: 0,
+      bool connectionClose: false,
+      String expectedVersion: "1.1"}) {
+    _testParseRequest(request, expectedMethod, expectedUri,
+        expectedTransferLength: expectedTransferLength,
+        expectedBytesReceived: expectedBytesReceived,
+        expectedHeaders: expectedHeaders,
+        chunked: chunked,
+        upgrade: upgrade,
+        unparsedLength: unparsedLength,
+        connectionClose: connectionClose,
+        expectedVersion: expectedVersion);
+    // Same test but with only \n instead of \r\n terminating each header line.
+    _testParseRequest(request.replaceAll('\r', ''), expectedMethod, expectedUri,
+        expectedTransferLength: expectedTransferLength,
+        expectedBytesReceived: expectedBytesReceived,
+        expectedHeaders: expectedHeaders,
+        chunked: chunked,
+        upgrade: upgrade,
+        unparsedLength: unparsedLength,
+        connectionClose: connectionClose,
+        expectedVersion: expectedVersion);
+  }
+
+  static void _testParseInvalidRequest(String request) {
+    _HttpParser httpParser;
+    bool errorCalled;
+    StreamController<Uint8List> controller;
+
+    void reset() {
+      httpParser = new _HttpParser.requestParser();
+      controller = new StreamController(sync: true);
+      var port = new ReceivePort();
+      httpParser.listenToStream(controller.stream);
+      var subscription = httpParser.listen((incoming) {
+        Expect.fail("Expected request");
+      });
+      subscription.onError((e) {
+        errorCalled = true;
+      });
+      subscription.onDone(() {
+        port.close();
+        Expect.isTrue(errorCalled);
+      });
+      errorCalled = false;
+    }
+
+    void testWrite(List<int> requestData, [int chunkSize = -1]) {
+      if (chunkSize == -1) chunkSize = requestData.length;
+      reset();
+      for (int pos = 0;
+          pos < requestData.length && !errorCalled;
+          pos += chunkSize) {
+        int end = min(requestData.length, pos + chunkSize);
+        controller.add(requestData.sublist(pos, end));
+      }
+      controller.close();
+    }
+
+    // Test parsing the request three times delivering the data in
+    // different chunks.
+    List<int> requestData = new Uint8List.fromList(request.codeUnits);
+    testWrite(requestData);
+    testWrite(requestData, 10);
+    testWrite(requestData, 1);
+  }
+
+  static void _testParseResponse(
+      String response, int expectedStatusCode, String expectedReasonPhrase,
+      {int expectedTransferLength: 0,
+      int expectedBytesReceived: 0,
+      Map<String, String> expectedHeaders: null,
+      bool chunked: false,
+      bool close: false,
+      String responseToMethod: null,
+      bool connectionClose: false,
+      bool upgrade: false,
+      int unparsedLength: 0,
+      String expectedVersion: "1.1"}) {
+    StreamController<Uint8List> controller;
+    bool upgraded;
+
+    void reset() {
+      _HttpParser httpParser;
+      bool headersCompleteCalled;
+      bool dataEndCalled;
+      bool dataEndClose;
+      int statusCode;
+      String reasonPhrase;
+      _HttpHeaders headers;
+      int contentLength;
+      int bytesReceived;
+      httpParser = new _HttpParser.responseParser();
+      controller = new StreamController(sync: true);
+      var port = new ReceivePort();
+      httpParser.listenToStream(controller.stream);
+      int doneCallCount = 0;
+      // Called when done parsing entire message and done parsing body.
+      // Only executed when both are done.
+      void whenDone() {
+        doneCallCount++;
+        if (doneCallCount < 2) return;
+        Expect.equals(expectedVersion, headers.protocolVersion);
+        Expect.equals(expectedStatusCode, statusCode);
+        Expect.equals(expectedReasonPhrase, reasonPhrase);
+        Expect.isTrue(headersCompleteCalled);
+        Expect.equals(expectedBytesReceived, bytesReceived);
+        if (!upgrade) {
+          Expect.isTrue(dataEndCalled);
+          if (close) Expect.isTrue(dataEndClose);
+          Expect.equals(dataEndClose, connectionClose);
+        }
+      }
+
+      var subscription = httpParser.listen((incoming) {
+        port.close();
+        statusCode = incoming.statusCode;
+        reasonPhrase = incoming.reasonPhrase;
+        headers = incoming.headers;
+        Expect.isFalse(headersCompleteCalled);
+        if (!chunked && !close) {
+          Expect.equals(expectedTransferLength, incoming.transferLength);
+        } else {
+          Expect.equals(-1, incoming.transferLength);
+        }
+        if (expectedHeaders != null) {
+          expectedHeaders.forEach((String name, String value) {
+            Expect.equals(value, headers[name][0]);
+          });
+        }
+        Expect.equals(upgrade, httpParser.upgrade);
+        headersCompleteCalled = true;
+        incoming.listen((List<int> data) {
+          Expect.isTrue(headersCompleteCalled);
+          bytesReceived += data.length;
+        }, onDone: () {
+          dataEndCalled = true;
+          dataEndClose = close;
+          whenDone();
+        });
+      }, onDone: whenDone);
+
+      headersCompleteCalled = false;
+      dataEndCalled = false;
+      dataEndClose = null;
+      statusCode = -1;
+      reasonPhrase = null;
+      headers = null;
+      bytesReceived = 0;
+    }
+
+    void testWrite(List<int> requestData, [int chunkSize = -1]) {
+      if (chunkSize == -1) chunkSize = requestData.length;
+      reset();
+      for (int pos = 0; pos < requestData.length; pos += chunkSize) {
+        int end = min(requestData.length, pos + chunkSize);
+        controller.add(requestData.sublist(pos, end));
+      }
+      if (close) controller.close();
+    }
+
+    // Test parsing the request three times delivering the data in
+    // different chunks.
+    List<int> responseData = new Uint8List.fromList(response.codeUnits);
+    testWrite(responseData);
+    testWrite(responseData, 10);
+    testWrite(responseData, 1);
+  }
+
+  static void _testParseInvalidResponse(String response, [bool close = false]) {
+    void testWrite(List<int> requestData, [int chunkSize = -1]) {
+      _HttpParser httpParser = new _HttpParser.responseParser();
+      StreamController<Uint8List> controller = new StreamController(sync: true);
+      bool errorCalled = false;
+
+      if (chunkSize == -1) chunkSize = requestData.length;
+
+      var port = new ReceivePort();
+      httpParser.listenToStream(controller.stream);
+      var subscription = httpParser.listen((incoming) {
+        incoming.listen((data) {}, onError: (e) {
+          Expect.isFalse(errorCalled);
+          errorCalled = true;
+        });
+      });
+      subscription.onError((e) {
+        Expect.isFalse(errorCalled);
+        errorCalled = true;
+      });
+      subscription.onDone(() {
+        port.close();
+        Expect.isTrue(errorCalled);
+      });
+
+      errorCalled = false;
+      for (int pos = 0;
+          pos < requestData.length && !errorCalled;
+          pos += chunkSize) {
+        int end = min(requestData.length, pos + chunkSize);
+        controller.add(requestData.sublist(pos, end));
+      }
+      controller.close();
+    }
+
+    // Test parsing the request three times delivering the data in
+    // different chunks.
+    List<int> responseData = new Uint8List.fromList(response.codeUnits);
+    testWrite(responseData);
+    testWrite(responseData, 10);
+    testWrite(responseData, 1);
+  }
+
+  static void testParseRequest() {
+    String request;
+    Map<String, String> headers;
+    var methods = [
+      // RFC 2616 methods.
+      "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT",
+      // WebDAV methods from RFC 4918.
+      "PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK",
+      // WebDAV methods from RFC 5323.
+      "SEARCH",
+      // Methods with HTTP prefix.
+      "H", "HT", "HTT", "HTTP", "HX", "HTX", "HTTX", "HTTPX"
+    ];
+    methods = ['GET'];
+    methods.forEach((method) {
+      request = "$method / HTTP/1.1\r\n\r\n";
+      _testParseRequestLean(request, method, "/");
+      request = "$method /index.html HTTP/1.1\r\n\r\n";
+      _testParseRequestLean(request, method, "/index.html");
+    });
+    request = "GET / HTTP/1.0\r\n\r\n";
+    _testParseRequestLean(request, "GET", "/",
+        expectedVersion: "1.0", connectionClose: true);
+
+    request = "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n";
+    _testParseRequestLean(request, "GET", "/", expectedVersion: "1.0");
+
+    request = """
+POST /test HTTP/1.1\r
+AAA: AAA\r
+\r
+""";
+    _testParseRequestLean(request, "POST", "/test");
+
+    request = """
+POST /test HTTP/1.1\r
+\r
+""";
+    _testParseRequestLean(request, "POST", "/test");
+
+    request = """
+POST /test HTTP/1.1\r
+Header-A: AAA\r
+X-Header-B: bbb\r
+\r
+""";
+    headers = new Map();
+    headers["header-a"] = "AAA";
+    headers["x-header-b"] = "bbb";
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
+
+    request = """
+POST /test HTTP/1.1\r
+Empty-Header-1:\r
+Empty-Header-2:\r
+        \r
+\r
+""";
+    headers = new Map();
+    headers["empty-header-1"] = "";
+    headers["empty-header-2"] = "";
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
+
+    request = """
+POST /test HTTP/1.1\r
+Header-A:   AAA\r
+X-Header-B:\t \t bbb\r
+\r
+""";
+    headers = new Map();
+    headers["header-a"] = "AAA";
+    headers["x-header-b"] = "bbb";
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
+
+    request = """
+POST /test HTTP/1.1\r
+Header-A:   AA\r
+ A\r
+X-Header-B:           b\r
+  b\r
+\t    b\r
+\r
+""";
+
+    headers = new Map();
+    headers["header-a"] = "AAA";
+    headers["x-header-b"] = "bbb";
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
+
+    request = """
+POST /test HTTP/1.1\r
+Content-Length: 10\r
+\r
+0123456789""";
+    _testParseRequestLean(request, "POST", "/test",
+        expectedTransferLength: 10, expectedBytesReceived: 10);
+
+    // Test connection close header.
+    request = "GET /test HTTP/1.1\r\nConnection: close\r\n\r\n";
+    _testParseRequest(request, "GET", "/test", connectionClose: true);
+
+    // Test chunked encoding.
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseRequest(request, "POST", "/test",
+        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
+
+    // Test mixing chunked encoding and content length (content length
+    // is ignored).
+    request = """
+POST /test HTTP/1.1\r
+Content-Length: 7\r
+Transfer-Encoding: chunked\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseRequest(request, "POST", "/test",
+        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
+
+    // Test mixing chunked encoding and content length (content length
+    // is ignored).
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+Content-Length: 3\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseRequest(request, "POST", "/test",
+        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
+
+    // Test upper and lower case hex digits in chunked encoding.
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+\r
+1E\r
+012345678901234567890123456789\r
+1e\r
+012345678901234567890123456789\r
+0\r\n\r\n""";
+    _testParseRequest(request, "POST", "/test",
+        expectedTransferLength: -1, expectedBytesReceived: 60, chunked: true);
+
+    // Test chunk extensions in chunked encoding.
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+\r
+1E;xxx\r
+012345678901234567890123456789\r
+1E;yyy=zzz\r
+012345678901234567890123456789\r
+0\r\n\r\n""";
+    _testParseRequest(request, "POST", "/test",
+        expectedTransferLength: -1, expectedBytesReceived: 60, chunked: true);
+
+    // Test HTTP upgrade.
+    request = """
+GET /irc HTTP/1.1\r
+Upgrade: irc/1.2\r
+Connection: Upgrade\r
+\r\n\x01\x01\x01\x01\x01\x02\x02\x02\x02\xFF""";
+    headers = new Map();
+    headers["upgrade"] = "irc/1.2";
+    _testParseRequest(request, "GET", "/irc",
+        expectedHeaders: headers, upgrade: true, unparsedLength: 10);
+
+    // Test HTTP upgrade with protocol data.
+    request = """
+GET /irc HTTP/1.1\r
+Upgrade: irc/1.2\r
+Connection: Upgrade\r
+\r\n""";
+    headers = new Map();
+    headers["upgrade"] = "irc/1.2";
+    _testParseRequest(request, "GET", "/irc",
+        expectedHeaders: headers, upgrade: true);
+
+    // Test websocket upgrade.
+    request = """
+GET /chat HTTP/1.1\r
+Host: server.example.com\r
+Upgrade: websocket\r
+Connection: Upgrade\r
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
+Origin: http://example.com\r
+Sec-WebSocket-Version: 13\r
+\r\n""";
+    headers = new Map();
+    headers["host"] = "server.example.com";
+    headers["upgrade"] = "websocket";
+    headers["sec-websocket-key"] = "dGhlIHNhbXBsZSBub25jZQ==";
+    headers["origin"] = "http://example.com";
+    headers["sec-websocket-version"] = "13";
+    _testParseRequest(request, "GET", "/chat",
+        expectedHeaders: headers, upgrade: true);
+
+    // Test websocket upgrade with protocol data. NOTE: When using the
+    // WebSocket protocol this should never happen as the client
+    // should not send protocol data before processing the request
+    // part of the opening handshake. However the HTTP parser should
+    // still handle this.
+    request = """
+GET /chat HTTP/1.1\r
+Host: server.example.com\r
+Upgrade: websocket\r
+Connection: Upgrade\r
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
+Origin: http://example.com\r
+Sec-WebSocket-Version: 13\r
+\r\n0123456""";
+    headers = new Map();
+    headers["host"] = "server.example.com";
+    headers["upgrade"] = "websocket";
+    headers["sec-websocket-key"] = "dGhlIHNhbXBsZSBub25jZQ==";
+    headers["origin"] = "http://example.com";
+    headers["sec-websocket-version"] = "13";
+    _testParseRequest(request, "GET", "/chat",
+        expectedHeaders: headers, upgrade: true, unparsedLength: 7);
+  }
+
+  static void testParseResponse() {
+    String response;
+    Map<String, String> headers;
+    response = "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 100, "Continue");
+
+    response = "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 100, "Continue");
+
+    response = "HTTP/1.1 100 Continue\r\nContent-Length: 10\r\n\r\n";
+    _testParseResponse(response, 100, "Continue",
+        expectedTransferLength: 10, expectedBytesReceived: 0);
+
+    response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n"
+        "Connection: Close\r\n\r\n";
+    _testParseResponse(response, 200, "OK", connectionClose: true);
+
+    response = "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 200, "OK",
+        expectedVersion: "1.0", connectionClose: true);
+
+    response = "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n"
+        "Connection: Keep-Alive\r\n\r\n";
+    _testParseResponse(response, 200, "OK", expectedVersion: "1.0");
+
+    response = "HTTP/1.1 204 No Content\r\nContent-Length: 11\r\n\r\n";
+    _testParseResponse(response, 204, "No Content",
+        expectedTransferLength: 11, expectedBytesReceived: 0);
+
+    response = "HTTP/1.1 304 Not Modified\r\nContent-Length: 12\r\n\r\n";
+    _testParseResponse(response, 304, "Not Modified",
+        expectedTransferLength: 12, expectedBytesReceived: 0);
+
+    response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 200, "OK");
+
+    response = "HTTP/1.1 404 Not found\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 404, "Not found");
+
+    response = "HTTP/1.1 500 Server error\r\nContent-Length: 0\r\n\r\n";
+    _testParseResponse(response, 500, "Server error");
+
+    // Test response to HEAD request.
+    response = """
+HTTP/1.1 200 OK\r
+Content-Length: 20\r
+Content-Type: text/html\r
+\r\n""";
+    headers = new Map();
+    headers["content-length"] = "20";
+    headers["content-type"] = "text/html";
+    _testParseResponse(response, 200, "OK",
+        responseToMethod: "HEAD",
+        expectedTransferLength: 20,
+        expectedBytesReceived: 0,
+        expectedHeaders: headers);
+
+    // Test content.
+    response = """
+HTTP/1.1 200 OK\r
+Content-Length: 20\r
+\r
+01234567890123456789""";
+    _testParseResponse(response, 200, "OK",
+        expectedTransferLength: 20, expectedBytesReceived: 20);
+
+    // Test upper and lower case hex digits in chunked encoding.
+    response = """
+HTTP/1.1 200 OK\r
+Transfer-Encoding: chunked\r
+\r
+1A\r
+01234567890123456789012345\r
+1f\r
+0123456789012345678901234567890\r
+0\r\n\r\n""";
+    _testParseResponse(response, 200, "OK",
+        expectedTransferLength: -1, expectedBytesReceived: 57, chunked: true);
+
+    // Test connection close header.
+    response = """
+HTTP/1.1 200 OK\r
+Content-Length: 0\r
+Connection: close\r
+\r\n""";
+    _testParseResponse(response, 200, "OK", connectionClose: true);
+
+    // Test HTTP response without any transfer length indications
+    // where closing the connections indicates end of body.
+    response = """
+HTTP/1.1 200 OK\r
+\r
+01234567890123456789012345
+0123456789012345678901234567890
+""";
+    _testParseResponse(response, 200, "OK",
+        expectedTransferLength: -1,
+        expectedBytesReceived: 59,
+        close: true,
+        connectionClose: true);
+
+    // Test HTTP upgrade.
+    response = """
+HTTP/1.1 101 Switching Protocols\r
+Upgrade: irc/1.2\r
+Connection: Upgrade\r
+\r\n""";
+    headers = new Map();
+    headers["upgrade"] = "irc/1.2";
+    _testParseResponse(response, 101, "Switching Protocols",
+        expectedHeaders: headers, upgrade: true);
+
+    // Test HTTP upgrade with protocol data.
+    response = """
+HTTP/1.1 101 Switching Protocols\r
+Upgrade: irc/1.2\r
+Connection: Upgrade\r
+\r\n\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xA0\xB0\xC0\xD0\xE0\xF0""";
+    headers = new Map();
+    headers["upgrade"] = "irc/1.2";
+    _testParseResponse(response, 101, "Switching Protocols",
+        expectedHeaders: headers, upgrade: true, unparsedLength: 16);
+
+    // Test websocket upgrade.
+    response = """
+HTTP/1.1 101 Switching Protocols\r
+Upgrade: websocket\r
+Connection: Upgrade\r
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r
+\r\n""";
+    headers = new Map();
+    headers["upgrade"] = "websocket";
+    headers["sec-websocket-accept"] = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
+    _testParseResponse(response, 101, "Switching Protocols",
+        expectedHeaders: headers, upgrade: true);
+
+    // Test websocket upgrade with protocol data.
+    response = """
+HTTP/1.1 101 Switching Protocols\r
+Upgrade: websocket\r
+Connection: Upgrade\r
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r
+\r\nABCD""";
+    headers = new Map();
+    headers["upgrade"] = "websocket";
+    headers["sec-websocket-accept"] = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
+    _testParseResponse(response, 101, "Switching Protocols",
+        expectedHeaders: headers, upgrade: true, unparsedLength: 4);
+  }
+
+  static void testParseInvalidRequest() {
+    String request;
+    request = "GET /\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "GET / \r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "/ HTTP/1.1\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "GET HTTP/1.1\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = " / HTTP/1.1\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "@ / HTTP/1.1\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "GET / TTP/1.1\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "GET / HTTP/1.\r\n\r\n";
+    _testParseInvalidRequest(request);
+
+    request = "GET / HTTP/1.1\r\nKeep-Alive: False\r\nbadheader\r\n\r\n";
+    _testParseInvalidRequest(request);
+  }
+
+  static void testParseInvalidResponse() {
+    String response;
+
+    response = "HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 \r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 200\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 200 \r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 20A OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "200 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1. 200 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 200 O\rK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 000 OK\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 999 Server Error\r\nContent-Length: 0\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 200 OK\r\nContent-Length: x\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = "HTTP/1.1 200 OK\r\nbadheader\r\n\r\n";
+    _testParseInvalidResponse(response);
+
+    response = """
+HTTP/1.1 200 OK\r
+Transfer-Encoding: chunked\r
+\r
+1A\r
+01234567890123456789012345\r
+1g\r
+0123456789012345678901234567890\r
+0\r\n\r\n""";
+    _testParseInvalidResponse(response);
+  }
+}
+
+void main() {
+  HttpParserTest.runAllTests();
+}
diff --git a/tests/standalone/io/http_proxy_advanced_test.dart b/tests/standalone/io/http_proxy_advanced_test.dart
new file mode 100644
index 0000000..65e4db9
--- /dev/null
+++ b/tests/standalone/io/http_proxy_advanced_test.dart
@@ -0,0 +1,624 @@
+// 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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import 'dart:convert';
+import "package:convert/convert.dart";
+import "package:crypto/crypto.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+final SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+final SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+class Server {
+  late HttpServer server;
+  bool secure;
+  int proxyHops;
+  List<String> directRequestPaths;
+  int requestCount = 0;
+
+  Server(this.proxyHops, this.directRequestPaths, this.secure);
+
+  Future<Server> start() {
+    return (secure
+            ? HttpServer.bindSecure("localhost", 0, serverContext)
+            : HttpServer.bind("localhost", 0))
+        .then((s) {
+      server = s;
+      server.listen(requestHandler);
+      return this;
+    });
+  }
+
+  void requestHandler(HttpRequest request) {
+    var response = request.response;
+    requestCount++;
+    // Check whether a proxy or direct connection is expected.
+    bool direct = directRequestPaths.fold(
+        false, (prev, path) => prev ? prev : path == request.uri.path);
+    if (!secure && !direct && proxyHops > 0) {
+      Expect.isNotNull(request.headers[HttpHeaders.viaHeader]);
+      Expect.equals(1, request.headers[HttpHeaders.viaHeader]!.length);
+      Expect.equals(proxyHops,
+          request.headers[HttpHeaders.viaHeader]![0].split(",").length);
+    } else {
+      Expect.isNull(request.headers[HttpHeaders.viaHeader]);
+    }
+    var body = new StringBuffer();
+    onRequestComplete() {
+      String path = request.uri.path.substring(1);
+      if (path != "A") {
+        String content = "$path$path$path";
+        Expect.equals(content, body.toString());
+      }
+      response.write(request.uri.path);
+      response.close();
+    }
+
+    request.listen((data) {
+      body.write(new String.fromCharCodes(data));
+    }, onDone: onRequestComplete);
+  }
+
+  void shutdown() {
+    server.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<Server> setupServer(int proxyHops,
+    {List<String> directRequestPaths: const <String>[], secure: false}) {
+  Server server = new Server(proxyHops, directRequestPaths, secure);
+  return server.start();
+}
+
+class ProxyServer {
+  final bool ipV6;
+  late HttpServer server;
+  final client = new HttpClient();
+  int requestCount = 0;
+  String? authScheme;
+  String realm = "test";
+  String? username;
+  String? password;
+
+  var ha1;
+  String serverAlgorithm = "MD5";
+  String serverQop = "auth";
+  Set ncs = new Set();
+
+  var nonce = "12345678"; // No need for random nonce in test.
+
+  ProxyServer({this.ipV6: false});
+
+  void useBasicAuthentication(String username, String password) {
+    this.username = username;
+    this.password = password;
+    authScheme = "Basic";
+  }
+
+  void useDigestAuthentication(String username, String password) {
+    this.username = username;
+    this.password = password;
+    authScheme = "Digest";
+
+    // Calculate ha1.
+    var digest = md5.convert("${username}:${realm}:${password}".codeUnits);
+    ha1 = hex.encode(digest.bytes);
+  }
+
+  basicAuthenticationRequired(request) {
+    request.fold(null, (x, y) {}).then((_) {
+      var response = request.response;
+      response.headers
+          .set(HttpHeaders.proxyAuthenticateHeader, "Basic, realm=$realm");
+      response.statusCode = HttpStatus.proxyAuthenticationRequired;
+      response.close();
+    });
+  }
+
+  digestAuthenticationRequired(request, {stale: false}) {
+    request.fold(null, (x, y) {}).then((_) {
+      var response = request.response;
+      response.statusCode = HttpStatus.proxyAuthenticationRequired;
+      StringBuffer authHeader = new StringBuffer();
+      authHeader.write('Digest');
+      authHeader.write(', realm="$realm"');
+      authHeader.write(', nonce="$nonce"');
+      if (stale) authHeader.write(', stale="true"');
+      if (serverAlgorithm != null) {
+        authHeader.write(', algorithm=$serverAlgorithm');
+      }
+      if (serverQop != null) authHeader.write(', qop="$serverQop"');
+      response.headers.set(HttpHeaders.proxyAuthenticateHeader, authHeader);
+      response.close();
+    });
+  }
+
+  Future<ProxyServer> start() {
+    var x = new Completer<ProxyServer>();
+    var host = ipV6 ? "::1" : "localhost";
+    HttpServer.bind(host, 0).then((s) {
+      server = s;
+      x.complete(this);
+      server.listen((HttpRequest request) {
+        requestCount++;
+        if (username != null && password != null) {
+          if (request.headers[HttpHeaders.proxyAuthorizationHeader] == null) {
+            if (authScheme == "Digest") {
+              digestAuthenticationRequired(request);
+            } else {
+              basicAuthenticationRequired(request);
+            }
+            return;
+          } else {
+            Expect.equals(1,
+                request.headers[HttpHeaders.proxyAuthorizationHeader]!.length);
+            String authorization =
+                request.headers[HttpHeaders.proxyAuthorizationHeader]![0];
+            if (authScheme == "Basic") {
+              List<String> tokens = authorization.split(" ");
+              Expect.equals("Basic", tokens[0]);
+              String auth = base64.encode(utf8.encode("$username:$password"));
+              if (auth != tokens[1]) {
+                basicAuthenticationRequired(request);
+                return;
+              }
+            } else {
+              HeaderValue header =
+                  HeaderValue.parse(authorization, parameterSeparator: ",");
+              Expect.equals("Digest", header.value);
+              var uri = header.parameters["uri"];
+              var qop = header.parameters["qop"];
+              var cnonce = header.parameters["cnonce"];
+              var nc = header.parameters["nc"];
+              Expect.equals(username, header.parameters["username"]);
+              Expect.equals(realm, header.parameters["realm"]);
+              Expect.equals("MD5", header.parameters["algorithm"]);
+              Expect.equals(nonce, header.parameters["nonce"]);
+              Expect.equals(request.uri.toString(), uri);
+              if (qop != null) {
+                // A server qop of auth-int is downgraded to none by the client.
+                Expect.equals("auth", serverQop);
+                Expect.equals("auth", header.parameters["qop"]);
+                Expect.isNotNull(cnonce);
+                Expect.isNotNull(nc);
+                Expect.isFalse(ncs.contains(nc));
+                ncs.add(nc);
+              } else {
+                Expect.isNull(cnonce);
+                Expect.isNull(nc);
+              }
+              Expect.isNotNull(header.parameters["response"]);
+
+              var digest = md5.convert("${request.method}:${uri}".codeUnits);
+              var ha2 = hex.encode(digest.bytes);
+
+              var x;
+              if (qop == null || qop == "" || qop == "none") {
+                digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
+              } else {
+                digest = md5.convert(
+                    "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
+              }
+              Expect.equals(
+                  hex.encode(digest.bytes), header.parameters["response"]);
+
+              // Add a bogus Proxy-Authentication-Info for testing.
+              var info = 'rspauth="77180d1ab3d6c9de084766977790f482", '
+                  'cnonce="8f971178", '
+                  'nc=000002c74, '
+                  'qop=auth';
+              request.response.headers.set("Proxy-Authentication-Info", info);
+            }
+          }
+        }
+        // Open the connection from the proxy.
+        if (request.method == "CONNECT") {
+          var tmp = request.uri.toString().split(":");
+          Socket.connect(tmp[0], int.parse(tmp[1])).then((socket) {
+            request.response.reasonPhrase = "Connection established";
+            request.response.detachSocket().then((detached) {
+              socket.cast<List<int>>().pipe(detached);
+              detached.cast<List<int>>().pipe(socket);
+            });
+          });
+        } else {
+          client
+              .openUrl(request.method, request.uri)
+              .then((HttpClientRequest clientRequest) {
+            // Forward all headers.
+            request.headers.forEach((String name, List<String> values) {
+              values.forEach((String value) {
+                if (name != "content-length" && name != "via") {
+                  clientRequest.headers.add(name, value);
+                }
+              });
+            });
+            // Special handling of Content-Length and Via.
+            clientRequest.contentLength = request.contentLength;
+            List<String>? via = request.headers[HttpHeaders.viaHeader];
+            String viaPrefix = via == null ? "" : "${via[0]}, ";
+            clientRequest.headers
+                .add(HttpHeaders.viaHeader, "${viaPrefix}1.1 localhost:$port");
+            // Copy all content.
+            return request.cast<List<int>>().pipe(clientRequest);
+          }).then((clientResponse) {
+            (clientResponse as HttpClientResponse)
+                .cast<List<int>>()
+                .pipe(request.response);
+          });
+        }
+      });
+    });
+    return x.future;
+  }
+
+  void shutdown() {
+    server.close();
+    client.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<ProxyServer> setupProxyServer({ipV6: false}) {
+  ProxyServer proxyServer = new ProxyServer(ipV6: ipV6);
+  return proxyServer.start();
+}
+
+int testProxyIPV6DoneCount = 0;
+void testProxyIPV6() {
+  setupProxyServer(ipV6: true).then((proxyServer) {
+    setupServer(1, directRequestPaths: ["/4"]).then((server) {
+      setupServer(1, directRequestPaths: ["/4"], secure: true)
+          .then((secureServer) {
+        HttpClient client = new HttpClient(context: clientContext);
+
+        List<String> proxy = ["PROXY [::1]:${proxyServer.port}"];
+        client.findProxy = (Uri uri) {
+          // Pick the proxy configuration based on the request path.
+          int index = int.parse(uri.path.substring(1));
+          return proxy[index];
+        };
+
+        for (int i = 0; i < proxy.length; i++) {
+          test(bool secure) {
+            String url = secure
+                ? "https://localhost:${secureServer.port}/$i"
+                : "http://localhost:${server.port}/$i";
+
+            client
+                .postUrl(Uri.parse(url))
+                .then((HttpClientRequest clientRequest) {
+              String content = "$i$i$i";
+              clientRequest.write(content);
+              return clientRequest.close();
+            }).then((HttpClientResponse response) {
+              response.listen((_) {}, onDone: () {
+                testProxyIPV6DoneCount++;
+                if (testProxyIPV6DoneCount == proxy.length * 2) {
+                  Expect.equals(proxy.length, server.requestCount);
+                  Expect.equals(proxy.length, secureServer.requestCount);
+                  proxyServer.shutdown();
+                  server.shutdown();
+                  secureServer.shutdown();
+                  client.close();
+                }
+              });
+            });
+          }
+
+          test(false);
+          test(true);
+        }
+      });
+    });
+  });
+}
+
+int testProxyFromEnviromentDoneCount = 0;
+void testProxyFromEnviroment() {
+  setupProxyServer().then((proxyServer) {
+    setupServer(1).then((server) {
+      setupServer(1, secure: true).then((secureServer) {
+        HttpClient client = new HttpClient(context: clientContext);
+
+        client.findProxy = (Uri uri) {
+          return HttpClient.findProxyFromEnvironment(uri, environment: {
+            "http_proxy": "localhost:${proxyServer.port}",
+            "https_proxy": "localhost:${proxyServer.port}"
+          });
+        };
+
+        const int loopCount = 5;
+        for (int i = 0; i < loopCount; i++) {
+          test(bool secure) {
+            String url = secure
+                ? "https://localhost:${secureServer.port}/$i"
+                : "http://localhost:${server.port}/$i";
+
+            client
+                .postUrl(Uri.parse(url))
+                .then((HttpClientRequest clientRequest) {
+              String content = "$i$i$i";
+              clientRequest.write(content);
+              return clientRequest.close();
+            }).then((HttpClientResponse response) {
+              response.listen((_) {}, onDone: () {
+                testProxyFromEnviromentDoneCount++;
+                if (testProxyFromEnviromentDoneCount == loopCount * 2) {
+                  Expect.equals(loopCount, server.requestCount);
+                  Expect.equals(loopCount, secureServer.requestCount);
+                  proxyServer.shutdown();
+                  server.shutdown();
+                  secureServer.shutdown();
+                  client.close();
+                }
+              });
+            });
+          }
+
+          test(false);
+          test(true);
+        }
+      });
+    });
+  });
+}
+
+int testProxyAuthenticateCount = 0;
+Future testProxyAuthenticate(bool useDigestAuthentication) {
+  testProxyAuthenticateCount = 0;
+  var completer = new Completer();
+
+  setupProxyServer().then((proxyServer) {
+    setupServer(1).then((server) {
+      setupServer(1, secure: true).then((secureServer) {
+        HttpClient client = new HttpClient(context: clientContext);
+
+        Completer step1 = new Completer();
+        Completer step2 = new Completer();
+
+        if (useDigestAuthentication) {
+          proxyServer.useDigestAuthentication("dart", "password");
+        } else {
+          proxyServer.useBasicAuthentication("dart", "password");
+        }
+
+        // Test with no authentication.
+        client.findProxy = (Uri uri) {
+          return "PROXY localhost:${proxyServer.port}";
+        };
+
+        const int loopCount = 2;
+        for (int i = 0; i < loopCount; i++) {
+          test(bool secure) {
+            String url = secure
+                ? "https://localhost:${secureServer.port}/$i"
+                : "http://localhost:${server.port}/$i";
+
+            client
+                .postUrl(Uri.parse(url))
+                .then((HttpClientRequest clientRequest) {
+              String content = "$i$i$i";
+              clientRequest.write(content);
+              return clientRequest.close();
+            }).then((HttpClientResponse response) {
+              Expect.fail("No response expected");
+            }).catchError((e) {
+              testProxyAuthenticateCount++;
+              if (testProxyAuthenticateCount == loopCount * 2) {
+                Expect.equals(0, server.requestCount);
+                Expect.equals(0, secureServer.requestCount);
+                step1.complete(null);
+              }
+            });
+          }
+
+          test(false);
+          test(true);
+        }
+        step1.future.then((_) {
+          testProxyAuthenticateCount = 0;
+          if (useDigestAuthentication) {
+            client.findProxy =
+                (Uri uri) => "PROXY localhost:${proxyServer.port}";
+            client.addProxyCredentials("localhost", proxyServer.port, "test",
+                new HttpClientDigestCredentials("dart", "password"));
+          } else {
+            client.findProxy = (Uri uri) {
+              return "PROXY dart:password@localhost:${proxyServer.port}";
+            };
+          }
+
+          for (int i = 0; i < loopCount; i++) {
+            test(bool secure) {
+              var path = useDigestAuthentication ? "A" : "$i";
+              String url = secure
+                  ? "https://localhost:${secureServer.port}/$path"
+                  : "http://localhost:${server.port}/$path";
+
+              client
+                  .postUrl(Uri.parse(url))
+                  .then((HttpClientRequest clientRequest) {
+                String content = "$i$i$i";
+                clientRequest.write(content);
+                return clientRequest.close();
+              }).then((HttpClientResponse response) {
+                response.listen((_) {}, onDone: () {
+                  testProxyAuthenticateCount++;
+                  Expect.equals(HttpStatus.ok, response.statusCode);
+                  if (testProxyAuthenticateCount == loopCount * 2) {
+                    Expect.equals(loopCount, server.requestCount);
+                    Expect.equals(loopCount, secureServer.requestCount);
+                    step2.complete(null);
+                  }
+                });
+              });
+            }
+
+            test(false);
+            test(true);
+          }
+        });
+
+        step2.future.then((_) {
+          testProxyAuthenticateCount = 0;
+          client.findProxy = (Uri uri) {
+            return "PROXY localhost:${proxyServer.port}";
+          };
+
+          client.authenticateProxy = (host, port, scheme, realm) {
+            client.addProxyCredentials("localhost", proxyServer.port, "realm",
+                new HttpClientBasicCredentials("dart", "password"));
+            return new Future.value(true);
+          };
+
+          for (int i = 0; i < loopCount; i++) {
+            test(bool secure) {
+              String url = secure
+                  ? "https://localhost:${secureServer.port}/A"
+                  : "http://localhost:${server.port}/A";
+
+              client
+                  .postUrl(Uri.parse(url))
+                  .then((HttpClientRequest clientRequest) {
+                String content = "$i$i$i";
+                clientRequest.write(content);
+                return clientRequest.close();
+              }).then((HttpClientResponse response) {
+                response.listen((_) {}, onDone: () {
+                  testProxyAuthenticateCount++;
+                  Expect.equals(HttpStatus.ok, response.statusCode);
+                  if (testProxyAuthenticateCount == loopCount * 2) {
+                    Expect.equals(loopCount * 2, server.requestCount);
+                    Expect.equals(loopCount * 2, secureServer.requestCount);
+                    proxyServer.shutdown();
+                    server.shutdown();
+                    secureServer.shutdown();
+                    client.close();
+                    completer.complete(null);
+                  }
+                });
+              });
+            }
+
+            test(false);
+            test(true);
+          }
+        });
+      });
+    });
+  });
+
+  return completer.future;
+}
+
+int testRealProxyDoneCount = 0;
+void testRealProxy() {
+  setupServer(1).then((server) {
+    HttpClient client = new HttpClient(context: clientContext);
+    client.addProxyCredentials("localhost", 8080, "test",
+        new HttpClientBasicCredentials("dart", "password"));
+
+    List<String> proxy = [
+      "PROXY localhost:8080",
+      "PROXY localhost:8080; PROXY hede.hule.hest:8080",
+      "PROXY hede.hule.hest:8080; PROXY localhost:8080",
+      "PROXY localhost:8080; DIRECT"
+    ];
+
+    client.findProxy = (Uri uri) {
+      // Pick the proxy configuration based on the request path.
+      int index = int.parse(uri.path.substring(1));
+      return proxy[index];
+    };
+
+    for (int i = 0; i < proxy.length; i++) {
+      client
+          .getUrl(Uri.parse("http://localhost:${server.port}/$i"))
+          .then((HttpClientRequest clientRequest) {
+        String content = "$i$i$i";
+        clientRequest.contentLength = content.length;
+        clientRequest.write(content);
+        return clientRequest.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          if (++testRealProxyDoneCount == proxy.length) {
+            Expect.equals(proxy.length, server.requestCount);
+            server.shutdown();
+            client.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+int testRealProxyAuthDoneCount = 0;
+void testRealProxyAuth() {
+  setupServer(1).then((server) {
+    HttpClient client = new HttpClient(context: clientContext);
+
+    List<String> proxy = [
+      "PROXY dart:password@localhost:8080",
+      "PROXY dart:password@localhost:8080; PROXY hede.hule.hest:8080",
+      "PROXY hede.hule.hest:8080; PROXY dart:password@localhost:8080",
+      "PROXY dart:password@localhost:8080; DIRECT"
+    ];
+
+    client.findProxy = (Uri uri) {
+      // Pick the proxy configuration based on the request path.
+      int index = int.parse(uri.path.substring(1));
+      return proxy[index];
+    };
+
+    for (int i = 0; i < proxy.length; i++) {
+      client
+          .getUrl(Uri.parse("http://localhost:${server.port}/$i"))
+          .then((HttpClientRequest clientRequest) {
+        String content = "$i$i$i";
+        clientRequest.contentLength = content.length;
+        clientRequest.write(content);
+        return clientRequest.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          if (++testRealProxyAuthDoneCount == proxy.length) {
+            Expect.equals(proxy.length, server.requestCount);
+            server.shutdown();
+            client.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+main() {
+  testProxyIPV6();
+  testProxyFromEnviroment();
+  // The two invocations use the same global variable for state -
+  // run one after the other.
+  testProxyAuthenticate(false).then((_) => testProxyAuthenticate(true));
+
+  // This test is not normally run. It can be used for locally testing
+  // with a real proxy server (e.g. Apache).
+  // testRealProxy();
+  // testRealProxyAuth();
+}
diff --git a/tests/standalone/io/http_proxy_configuration_test.dart b/tests/standalone/io/http_proxy_configuration_test.dart
new file mode 100644
index 0000000..c94826a
--- /dev/null
+++ b/tests/standalone/io/http_proxy_configuration_test.dart
@@ -0,0 +1,134 @@
+// 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:io";
+import "package:expect/expect.dart";
+
+expect(expected, String uri, environment) {
+  Expect.equals(
+      expected,
+      HttpClient.findProxyFromEnvironment(Uri.parse(uri),
+          environment: environment));
+}
+
+expectDirect(String uri, Map<String, String> environment) {
+  Expect.equals(
+      "DIRECT",
+      HttpClient.findProxyFromEnvironment(Uri.parse(uri),
+          environment: environment));
+}
+
+main() {
+  expectDirect("http://www.google.com", {});
+  expectDirect("http://www.google.com", {"http_proxy": ""});
+  expectDirect("http://www.google.com", {"http_proxy": " "});
+
+  expect("PROXY www.proxy.com:1080", "http://www.google.com",
+      {"http_proxy": "www.proxy.com"});
+  expect("PROXY www.proxys.com:1080", "https://www.google.com",
+      {"https_proxy": "www.proxys.com"});
+  expect("PROXY www.proxy.com:8080", "http://www.google.com",
+      {"http_proxy": "www.proxy.com:8080"});
+  expect("PROXY www.proxys.com:8080", "https://www.google.com",
+      {"https_proxy": "www.proxys.com:8080"});
+  expect("PROXY www.proxy.com:8080", "http://www.google.com", {
+    "http_proxy": "www.proxy.com:8080",
+    "https_proxy": "www.proxys.com:8080"
+  });
+  expect("PROXY www.proxys.com:8080", "https://www.google.com", {
+    "http_proxy": "www.proxy.com:8080",
+    "https_proxy": "www.proxys.com:8080"
+  });
+
+  expect("PROXY [::ffff:1]:1080", "http://www.google.com",
+      {"http_proxy": "[::ffff:1]"});
+  expect("PROXY [::ffff:2]:1080", "https://www.google.com",
+      {"https_proxy": "[::ffff:2]"});
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com",
+      {"http_proxy": "[::ffff:1]:8080"});
+  expect("PROXY [::ffff:2]:8080", "https://www.google.com",
+      {"https_proxy": "[::ffff:2]:8080"});
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com",
+      {"http_proxy": "[::ffff:1]:8080", "https_proxy": "[::ffff:2]:8080"});
+  expect("PROXY [::ffff:2]:8080", "https://www.google.com",
+      {"http_proxy": "[::ffff:1]:8080", "https_proxy": "[::ffff:2]:8080"});
+
+  expect("PROXY www.proxy.com:1080", "http://www.google.com",
+      {"http_proxy": "http://www.proxy.com"});
+  expect("PROXY www.proxy.com:1080", "http://www.google.com",
+      {"http_proxy": "http://www.proxy.com/"});
+  expect("PROXY www.proxy.com:8080", "http://www.google.com",
+      {"http_proxy": "http://www.proxy.com:8080/"});
+  expect("PROXY www.proxy.com:8080", "http://www.google.com",
+      {"http_proxy": "http://www.proxy.com:8080/index.html"});
+  expect("PROXY www.proxy.com:8080", "http://www.google.com", {
+    "http_proxy": "http://www.proxy.com:8080/",
+    "https_proxy": "http://www.proxys.com:8080/"
+  });
+  expect("PROXY www.proxys.com:8080", "https://www.google.com", {
+    "http_proxy": "http://www.proxy.com:8080/",
+    "https_proxy": "http://www.proxys.com:8080/"
+  });
+  expect("PROXY www.proxy.com:8080", "http://www.google.com", {
+    "http_proxy": "http://www.proxy.com:8080/",
+    "https_proxy": "http://www.proxys.com:8080/index.html"
+  });
+  expect("PROXY www.proxys.com:8080", "https://www.google.com", {
+    "http_proxy": "http://www.proxy.com:8080/",
+    "https_proxy": "http://www.proxys.com:8080/index.html"
+  });
+
+  expect("PROXY [::ffff:1]:1080", "http://www.google.com",
+      {"http_proxy": "http://[::ffff:1]"});
+  expect("PROXY [::ffff:1]:1080", "http://www.google.com",
+      {"http_proxy": "http://[::ffff:1]/"});
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com",
+      {"http_proxy": "http://[::ffff:1]:8080/"});
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com",
+      {"http_proxy": "http://[::ffff:1]:8080/index.html"});
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com", {
+    "http_proxy": "http://[::ffff:1]:8080/",
+    "https_proxy": "http://[::ffff:1]:8080/"
+  });
+  expect("PROXY [::ffff:2]:8080", "https://www.google.com", {
+    "http_proxy": "http://[::ffff:1]:8080/",
+    "https_proxy": "http://[::ffff:2]:8080/"
+  });
+  expect("PROXY [::ffff:1]:8080", "http://www.google.com", {
+    "http_proxy": "http://[::ffff:1]:8080/",
+    "https_proxy": "http://[::ffff:1]:8080/index.html"
+  });
+  expect("PROXY [::ffff:2]:8080", "https://www.google.com", {
+    "http_proxy": "http://[::ffff:1]:8080/",
+    "https_proxy": "http://[::ffff:2]:8080/index.html"
+  });
+
+  expectDirect("http://www.google.com",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": "www.google.com"});
+  expectDirect("http://www.google.com",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": "google.com"});
+  expectDirect("http://www.google.com",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": ".com"});
+  expectDirect("http://www.google.com", {
+    "http_proxy": "www.proxy.com:8080",
+    "no_proxy": ",,  , www.google.edu,,.com    "
+  });
+  expectDirect("http://www.google.edu", {
+    "http_proxy": "www.proxy.com:8080",
+    "no_proxy": ",,  , www.google.edu,,.com    "
+  });
+  expectDirect("http://www.google.com", {"https_proxy": "www.proxy.com:8080"});
+
+  expect("PROXY www.proxy.com:8080", "http://[::ffff:1]",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": "["});
+  expect("PROXY www.proxy.com:8080", "http://[::ffff:1]",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": "[]"});
+
+  expectDirect("http://[::ffff:1]",
+      {"http_proxy": "www.proxy.com:8080", "no_proxy": "[::ffff:1]"});
+  expectDirect("http://[::ffff:1]", {
+    "http_proxy": "www.proxy.com:8080",
+    "no_proxy": ",,  , www.google.edu,,[::ffff:1]    "
+  });
+}
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
new file mode 100644
index 0000000..fbdb5ed
--- /dev/null
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -0,0 +1,479 @@
+// 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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import 'dart:convert';
+import "package:convert/convert.dart";
+import "package:crypto/crypto.dart";
+import "package:expect/expect.dart";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+final SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+final SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+class Server {
+  late HttpServer server;
+  bool secure;
+  int proxyHops;
+  List<String> directRequestPaths;
+  int requestCount = 0;
+
+  Server(this.proxyHops, this.directRequestPaths, this.secure);
+
+  Future<Server> start() {
+    return (secure
+            ? HttpServer.bindSecure("localhost", 0, serverContext)
+            : HttpServer.bind("localhost", 0))
+        .then((s) {
+      server = s;
+      server.listen(requestHandler);
+      return this;
+    });
+  }
+
+  void requestHandler(HttpRequest request) {
+    var response = request.response;
+    requestCount++;
+    // Check whether a proxy or direct connection is expected.
+    bool direct = directRequestPaths.fold(
+        false, (prev, path) => prev ? prev : path == request.uri.path);
+    if (!secure && !direct && proxyHops > 0) {
+      Expect.isNotNull(request.headers[HttpHeaders.viaHeader]);
+      Expect.equals(1, request.headers[HttpHeaders.viaHeader]!.length);
+      Expect.equals(proxyHops,
+          request.headers[HttpHeaders.viaHeader]![0].split(",").length);
+    } else {
+      Expect.isNull(request.headers[HttpHeaders.viaHeader]);
+    }
+    var body = new StringBuffer();
+    onRequestComplete() {
+      String path = request.uri.path.substring(1);
+      if (path != "A") {
+        String content = "$path$path$path";
+        Expect.equals(content, body.toString());
+      }
+      response.write(request.uri.path);
+      response.close();
+    }
+
+    request.listen((data) {
+      body.write(new String.fromCharCodes(data));
+    }, onDone: onRequestComplete);
+  }
+
+  void shutdown() {
+    server.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<Server> setupServer(int proxyHops,
+    {List<String> directRequestPaths: const <String>[], secure: false}) {
+  Server server = new Server(proxyHops, directRequestPaths, secure);
+  return server.start();
+}
+
+class ProxyServer {
+  final bool ipV6;
+  late HttpServer server;
+  final client = new HttpClient();
+  int requestCount = 0;
+  String? authScheme;
+  String realm = "test";
+  String? username;
+  String? password;
+
+  var ha1;
+  String serverAlgorithm = "MD5";
+  String serverQop = "auth";
+  Set ncs = new Set();
+
+  var nonce = "12345678"; // No need for random nonce in test.
+
+  ProxyServer({this.ipV6: false});
+
+  void useBasicAuthentication(String username, String password) {
+    this.username = username;
+    this.password = password;
+    authScheme = "Basic";
+  }
+
+  basicAuthenticationRequired(request) {
+    request.fold(null, (x, y) {}).then((_) {
+      var response = request.response;
+      response.headers
+          .set(HttpHeaders.proxyAuthenticateHeader, "Basic, realm=$realm");
+      response.statusCode = HttpStatus.proxyAuthenticationRequired;
+      response.close();
+    });
+  }
+
+  digestAuthenticationRequired(request, {stale: false}) {
+    request.fold(null, (x, y) {}).then((_) {
+      var response = request.response;
+      response.statusCode = HttpStatus.proxyAuthenticationRequired;
+      StringBuffer authHeader = new StringBuffer();
+      authHeader.write('Digest');
+      authHeader.write(', realm="$realm"');
+      authHeader.write(', nonce="$nonce"');
+      if (stale) authHeader.write(', stale="true"');
+      if (serverAlgorithm != null) {
+        authHeader.write(', algorithm=$serverAlgorithm');
+      }
+      if (serverQop != null) authHeader.write(', qop="$serverQop"');
+      response.headers.set(HttpHeaders.proxyAuthenticateHeader, authHeader);
+      response.close();
+    });
+  }
+
+  Future<ProxyServer> start() {
+    var x = new Completer<ProxyServer>();
+    var host = ipV6 ? "::1" : "localhost";
+    HttpServer.bind(host, 0).then((s) {
+      server = s;
+      x.complete(this);
+      server.listen((HttpRequest request) {
+        requestCount++;
+        if (username != null && password != null) {
+          if (request.headers[HttpHeaders.proxyAuthorizationHeader] == null) {
+            if (authScheme == "Digest") {
+              digestAuthenticationRequired(request);
+            } else {
+              basicAuthenticationRequired(request);
+            }
+            return;
+          } else {
+            Expect.equals(1,
+                request.headers[HttpHeaders.proxyAuthorizationHeader]!.length);
+            String authorization =
+                request.headers[HttpHeaders.proxyAuthorizationHeader]![0];
+            if (authScheme == "Basic") {
+              List<String> tokens = authorization.split(" ");
+              Expect.equals("Basic", tokens[0]);
+              String auth = base64.encode(utf8.encode("$username:$password"));
+              if (auth != tokens[1]) {
+                basicAuthenticationRequired(request);
+                return;
+              }
+            } else {
+              HeaderValue header =
+                  HeaderValue.parse(authorization, parameterSeparator: ",");
+              Expect.equals("Digest", header.value);
+              var uri = header.parameters["uri"];
+              var qop = header.parameters["qop"];
+              var cnonce = header.parameters["cnonce"];
+              var nc = header.parameters["nc"];
+              Expect.equals(username, header.parameters["username"]);
+              Expect.equals(realm, header.parameters["realm"]);
+              Expect.equals("MD5", header.parameters["algorithm"]);
+              Expect.equals(nonce, header.parameters["nonce"]);
+              Expect.equals(request.uri.toString(), uri);
+              if (qop != null) {
+                // A server qop of auth-int is downgraded to none by the client.
+                Expect.equals("auth", serverQop);
+                Expect.equals("auth", header.parameters["qop"]);
+                Expect.isNotNull(cnonce);
+                Expect.isNotNull(nc);
+                Expect.isFalse(ncs.contains(nc));
+                ncs.add(nc);
+              } else {
+                Expect.isNull(cnonce);
+                Expect.isNull(nc);
+              }
+              Expect.isNotNull(header.parameters["response"]);
+
+              var digest = md5.convert("${request.method}:${uri}".codeUnits);
+              var ha2 = hex.encode(digest.bytes);
+
+              if (qop == null || qop == "" || qop == "none") {
+                digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits);
+              } else {
+                digest = md5.convert(
+                    "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits);
+              }
+              Expect.equals(
+                  hex.encode(digest.bytes), header.parameters["response"]);
+
+              // Add a bogus Proxy-Authentication-Info for testing.
+              var info = 'rspauth="77180d1ab3d6c9de084766977790f482", '
+                  'cnonce="8f971178", '
+                  'nc=000002c74, '
+                  'qop=auth';
+              request.response.headers.set("Proxy-Authentication-Info", info);
+            }
+          }
+        }
+        // Open the connection from the proxy.
+        if (request.method == "CONNECT") {
+          var tmp = request.uri.toString().split(":");
+          Socket.connect(tmp[0], int.parse(tmp[1])).then((socket) {
+            request.response.reasonPhrase = "Connection established";
+            request.response.detachSocket().then((detached) {
+              socket.cast<List<int>>().pipe(detached);
+              detached.cast<List<int>>().pipe(socket);
+            });
+          });
+        } else {
+          client
+              .openUrl(request.method, request.uri)
+              .then((HttpClientRequest clientRequest) {
+            // Forward all headers.
+            request.headers.forEach((String name, List<String> values) {
+              values.forEach((String value) {
+                if (name != "content-length" && name != "via") {
+                  clientRequest.headers.add(name, value);
+                }
+              });
+            });
+            // Special handling of Content-Length and Via.
+            clientRequest.contentLength = request.contentLength;
+            List<String>? via = request.headers[HttpHeaders.viaHeader];
+            String viaPrefix = via == null ? "" : "${via[0]}, ";
+            clientRequest.headers
+                .add(HttpHeaders.viaHeader, "${viaPrefix}1.1 localhost:$port");
+            // Copy all content.
+            return request.cast<List<int>>().pipe(clientRequest);
+          }).then((clientResponse) {
+            (clientResponse as HttpClientResponse)
+                .cast<List<int>>()
+                .pipe(request.response);
+          });
+        }
+      });
+    });
+    return x.future;
+  }
+
+  void shutdown() {
+    server.close();
+    client.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<ProxyServer> setupProxyServer({ipV6: false}) {
+  ProxyServer proxyServer = new ProxyServer(ipV6: ipV6);
+  return proxyServer.start();
+}
+
+testInvalidProxy() {
+  HttpClient client = new HttpClient(context: clientContext);
+
+  client.findProxy = (Uri uri) => "";
+  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"))
+      .catchError((error) {}, test: (e) => e is HttpException);
+
+  client.findProxy = (Uri uri) => "PROXY www.google.com";
+  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"))
+      .catchError((error) {}, test: (e) => e is HttpException);
+}
+
+int testDirectDoneCount = 0;
+void testDirectProxy() {
+  setupServer(0).then((server) {
+    HttpClient client = new HttpClient(context: clientContext);
+    List<String> proxy = [
+      "DIRECT",
+      " DIRECT ",
+      "DIRECT ;",
+      " DIRECT ; ",
+      ";DIRECT",
+      " ; DIRECT ",
+      ";;DIRECT;;"
+    ];
+
+    client.findProxy = (Uri uri) {
+      int index = int.parse(uri.path.substring(1));
+      return proxy[index];
+    };
+
+    for (int i = 0; i < proxy.length; i++) {
+      client
+          .getUrl(Uri.parse("http://localhost:${server.port}/$i"))
+          .then((HttpClientRequest clientRequest) {
+        String content = "$i$i$i";
+        clientRequest.contentLength = content.length;
+        clientRequest.write(content);
+        return clientRequest.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          testDirectDoneCount++;
+          if (testDirectDoneCount == proxy.length) {
+            Expect.equals(proxy.length, server.requestCount);
+            server.shutdown();
+            client.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+int testProxyDoneCount = 0;
+void testProxy() {
+  setupProxyServer().then((proxyServer) {
+    setupServer(1, directRequestPaths: ["/4"]).then((server) {
+      setupServer(1, directRequestPaths: ["/4"], secure: true)
+          .then((secureServer) {
+        HttpClient client = new HttpClient(context: clientContext);
+
+        List<String> proxy;
+        if (Platform.operatingSystem == "windows") {
+          proxy = [
+            "PROXY localhost:${proxyServer.port}",
+            "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+            "PROXY localhost:${proxyServer.port}",
+            ""
+                " PROXY localhost:${proxyServer.port}",
+            "DIRECT",
+            "PROXY localhost:${proxyServer.port}; DIRECT"
+          ];
+        } else {
+          proxy = [
+            "PROXY localhost:${proxyServer.port}",
+            "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+            "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}",
+            "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+                " PROXY localhost:${proxyServer.port}",
+            "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+            "PROXY localhost:${proxyServer.port}; DIRECT"
+          ];
+        }
+        client.findProxy = (Uri uri) {
+          // Pick the proxy configuration based on the request path.
+          int index = int.parse(uri.path.substring(1));
+          return proxy[index];
+        };
+
+        for (int i = 0; i < proxy.length; i++) {
+          test(bool secure) {
+            String url = secure
+                ? "https://localhost:${secureServer.port}/$i"
+                : "http://localhost:${server.port}/$i";
+
+            client
+                .postUrl(Uri.parse(url))
+                .then((HttpClientRequest clientRequest) {
+              String content = "$i$i$i";
+              clientRequest.write(content);
+              return clientRequest.close();
+            }).then((HttpClientResponse response) {
+              response.listen((_) {}, onDone: () {
+                testProxyDoneCount++;
+                if (testProxyDoneCount == proxy.length * 2) {
+                  Expect.equals(proxy.length, server.requestCount);
+                  Expect.equals(proxy.length, secureServer.requestCount);
+                  proxyServer.shutdown();
+                  server.shutdown();
+                  secureServer.shutdown();
+                  client.close();
+                }
+              });
+            });
+          }
+
+          test(false);
+          test(true);
+        }
+      });
+    });
+  });
+}
+
+int testProxyChainDoneCount = 0;
+void testProxyChain() {
+  // Setup two proxy servers having the first using the second as its proxy.
+  setupProxyServer().then((proxyServer1) {
+    setupProxyServer().then((proxyServer2) {
+      proxyServer1.client.findProxy =
+          (_) => "PROXY localhost:${proxyServer2.port}";
+
+      setupServer(2, directRequestPaths: ["/4"]).then((server) {
+        HttpClient client = new HttpClient(context: clientContext);
+
+        List<String> proxy;
+        if (Platform.operatingSystem == "windows") {
+          proxy = [
+            "PROXY localhost:${proxyServer1.port}",
+            "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+            "PROXY localhost:${proxyServer1.port}",
+            "PROXY localhost:${proxyServer1.port}",
+            "DIRECT",
+            "PROXY localhost:${proxyServer1.port}; DIRECT"
+          ];
+        } else {
+          proxy = [
+            "PROXY localhost:${proxyServer1.port}",
+            "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+            "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}",
+            "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+                " PROXY localhost:${proxyServer1.port}",
+            "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+            "PROXY localhost:${proxyServer1.port}; DIRECT"
+          ];
+        }
+
+        client.findProxy = (Uri uri) {
+          // Pick the proxy configuration based on the request path.
+          int index = int.parse(uri.path.substring(1));
+          return proxy[index];
+        };
+
+        for (int i = 0; i < proxy.length; i++) {
+          client
+              .getUrl(Uri.parse("http://localhost:${server.port}/$i"))
+              .then((HttpClientRequest clientRequest) {
+            String content = "$i$i$i";
+            clientRequest.contentLength = content.length;
+            clientRequest.write(content);
+            return clientRequest.close();
+          }).then((HttpClientResponse response) {
+            response.listen((_) {}, onDone: () {
+              testProxyChainDoneCount++;
+              if (testProxyChainDoneCount == proxy.length) {
+                Expect.equals(proxy.length, server.requestCount);
+                proxyServer1.shutdown();
+                proxyServer2.shutdown();
+                server.shutdown();
+                client.close();
+              }
+            });
+          });
+        }
+      });
+    });
+  });
+}
+
+main() {
+  testInvalidProxy();
+  testDirectProxy();
+  testProxy();
+  testProxyChain();
+}
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
new file mode 100644
index 0000000..6c6a103
--- /dev/null
+++ b/tests/standalone/io/http_read_test.dart
@@ -0,0 +1,214 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:isolate";
+import "dart:io";
+import "package:expect/expect.dart";
+
+class IsolatedHttpServer {
+  IsolatedHttpServer();
+
+  void setServerStartedHandler(void startedCallback(int port)) {
+    _startedCallback = startedCallback;
+  }
+
+  void start([bool chunkedEncoding = false]) {
+    ReceivePort receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startIsolatedHttpServer, receivePort.sendPort);
+    receivePort.first.then((port) {
+      _serverPort = port;
+
+      if (chunkedEncoding) {
+        // Send chunked encoding message to the server.
+        port.send([
+          new IsolatedHttpServerCommand.chunkedEncoding(),
+          _statusPort.sendPort
+        ]);
+      }
+
+      // Send server start message to the server.
+      var command = new IsolatedHttpServerCommand.start();
+      port.send([command, _statusPort.sendPort]);
+    });
+
+    // Handle status messages from the server.
+    _statusPort.listen((var status) {
+      if (status.isStarted) {
+        _startedCallback(status.port);
+      }
+    });
+  }
+
+  void shutdown() {
+    // Send server stop message to the server.
+    _serverPort
+        .send([new IsolatedHttpServerCommand.stop(), _statusPort.sendPort]);
+    _statusPort.close();
+  }
+
+  final _statusPort =
+      new ReceivePort(); // Port for receiving messages from the server.
+  late SendPort _serverPort; // Port for sending messages to the server.
+  var _startedCallback;
+}
+
+class IsolatedHttpServerCommand {
+  static const START = 0;
+  static const STOP = 1;
+  static const CHUNKED_ENCODING = 2;
+
+  IsolatedHttpServerCommand.start() : _command = START;
+  IsolatedHttpServerCommand.stop() : _command = STOP;
+  IsolatedHttpServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING;
+
+  bool get isStart => _command == START;
+  bool get isStop => _command == STOP;
+  bool get isChunkedEncoding => _command == CHUNKED_ENCODING;
+
+  int _command;
+}
+
+class IsolatedHttpServerStatus {
+  static const STARTED = 0;
+  static const STOPPED = 1;
+  static const ERROR = 2;
+
+  IsolatedHttpServerStatus.started(this._port) : _state = STARTED;
+  IsolatedHttpServerStatus.stopped() : _state = STOPPED;
+  IsolatedHttpServerStatus.error() : _state = ERROR;
+
+  bool get isStarted => _state == STARTED;
+  bool get isStopped => _state == STOPPED;
+  bool get isError => _state == ERROR;
+
+  int get port => _port;
+
+  int _state;
+  int _port = 0;
+}
+
+void startIsolatedHttpServer(Object replyToObj) {
+  final replyTo = replyToObj as SendPort;
+  var server = new TestServer();
+  server.init();
+  replyTo.send(server.dispatchSendPort);
+}
+
+class TestServer {
+  // Echo the request content back to the response.
+  void _echoHandler(HttpRequest request) {
+    var response = request.response;
+    Expect.equals("POST", request.method);
+    response.contentLength = request.contentLength;
+    request.cast<List<int>>().pipe(response);
+  }
+
+  // Return a 404.
+  void _notFoundHandler(HttpRequest request) {
+    var response = request.response;
+    response.statusCode = HttpStatus.notFound;
+    response.headers.set("Content-Type", "text/html; charset=UTF-8");
+    response.write("Page not found");
+    response.close();
+  }
+
+  void init() {
+    // Setup request handlers.
+    _requestHandlers["/echo"] = _echoHandler;
+    _dispatchPort.listen(dispatch);
+  }
+
+  SendPort get dispatchSendPort => _dispatchPort.sendPort;
+
+  void dispatch(message) {
+    IsolatedHttpServerCommand command = message[0];
+    SendPort replyTo = message[1];
+    if (command.isStart) {
+      try {
+        HttpServer.bind("127.0.0.1", 0).then((server) {
+          _server = server;
+          _server.listen(_requestReceivedHandler);
+          replyTo.send(new IsolatedHttpServerStatus.started(_server.port));
+        });
+      } catch (e) {
+        replyTo.send(new IsolatedHttpServerStatus.error());
+      }
+    } else if (command.isStop) {
+      _server.close();
+      _dispatchPort.close();
+      replyTo.send(new IsolatedHttpServerStatus.stopped());
+    } else if (command.isChunkedEncoding) {
+      _chunkedEncoding = true;
+    }
+  }
+
+  void _requestReceivedHandler(HttpRequest request) {
+    var requestHandler = _requestHandlers[request.uri.path];
+    if (requestHandler != null) {
+      requestHandler(request);
+    } else {
+      _notFoundHandler(request);
+    }
+  }
+
+  late HttpServer _server; // HTTP server instance.
+  final _dispatchPort = new ReceivePort();
+  final _requestHandlers = {};
+  bool _chunkedEncoding = false;
+}
+
+void testRead(bool chunkedEncoding) {
+  String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  final int kMessageCount = 10;
+
+  IsolatedHttpServer server = new IsolatedHttpServer();
+
+  void runTest(int port) {
+    int count = 0;
+    HttpClient httpClient = new HttpClient();
+    void sendRequest() {
+      httpClient.post("127.0.0.1", port, "/echo").then((request) {
+        if (chunkedEncoding) {
+          request.write(data.substring(0, 10));
+          request.write(data.substring(10, data.length));
+        } else {
+          request.contentLength = data.length;
+          request.add(data.codeUnits);
+        }
+        return request.close();
+      }).then((response) {
+        Expect.equals(HttpStatus.ok, response.statusCode);
+        List<int> body = new List<int>();
+        response.listen(body.addAll, onDone: () {
+          Expect.equals(data, new String.fromCharCodes(body));
+          count++;
+          if (count < kMessageCount) {
+            sendRequest();
+          } else {
+            httpClient.close();
+            server.shutdown();
+          }
+        });
+      });
+    }
+
+    sendRequest();
+  }
+
+  server.setServerStartedHandler(runTest);
+  server.start(chunkedEncoding);
+}
+
+void main() {
+  testRead(true);
+  testRead(false);
+}
diff --git a/tests/standalone/io/http_redirect_test.dart b/tests/standalone/io/http_redirect_test.dart
new file mode 100644
index 0000000..9b19d73
--- /dev/null
+++ b/tests/standalone/io/http_redirect_test.dart
@@ -0,0 +1,450 @@
+// 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 "dart:async";
+import "dart:io";
+
+Future<HttpServer> setupServer() {
+  final completer = new Completer<HttpServer>();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    var handlers = new Map<String, Function>();
+    addRequestHandler(
+        String path, void handler(HttpRequest request, HttpResponse response)) {
+      handlers[path] = handler;
+    }
+
+    server.listen((HttpRequest request) {
+      if (handlers.containsKey(request.uri.path)) {
+        handlers[request.uri.path]!(request, request.response);
+      } else {
+        request.listen((_) {}, onDone: () {
+          request.response.statusCode = 404;
+          request.response.close();
+        });
+      }
+    });
+
+    void addRedirectHandler(int number, int statusCode) {
+      addRequestHandler("/$number",
+          (HttpRequest request, HttpResponse response) {
+        response.redirect(
+            Uri.parse("http://127.0.0.1:${server.port}/${number + 1}"));
+      });
+    }
+
+    // Setup simple redirect.
+    addRequestHandler("/redirect",
+        (HttpRequest request, HttpResponse response) {
+      response.redirect(Uri.parse("http://127.0.0.1:${server.port}/location"),
+          status: HttpStatus.movedPermanently);
+    });
+    addRequestHandler("/location",
+        (HttpRequest request, HttpResponse response) {
+      response.close();
+    });
+
+    // Setup redirects with relative url.
+    addRequestHandler("/redirectUrl",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(HttpHeaders.locationHeader, "/some/relativeUrl");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    addRequestHandler("/some/redirectUrl",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(HttpHeaders.locationHeader, "relativeUrl");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    addRequestHandler("/some/relativeUrl",
+        (HttpRequest request, HttpResponse response) {
+      response.close();
+    });
+
+    addRequestHandler("/some/relativeToAbsolute",
+        (HttpRequest request, HttpResponse response) {
+      response.redirect(Uri.parse("xxx"), status: HttpStatus.seeOther);
+    });
+
+    addRequestHandler("/redirectUrl2",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(HttpHeaders.locationHeader, "location");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    addRequestHandler("/redirectUrl3",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(HttpHeaders.locationHeader, "./location");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    addRequestHandler("/redirectUrl4",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(HttpHeaders.locationHeader, "./a/b/../../location");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    addRequestHandler("/redirectUrl5",
+        (HttpRequest request, HttpResponse response) {
+      response.headers.set(
+          HttpHeaders.locationHeader, "//127.0.0.1:${server.port}/location");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+
+    // Setup redirect chain.
+    int n = 1;
+    addRedirectHandler(n++, HttpStatus.movedPermanently);
+    addRedirectHandler(n++, HttpStatus.movedTemporarily);
+    addRedirectHandler(n++, HttpStatus.seeOther);
+    addRedirectHandler(n++, HttpStatus.temporaryRedirect);
+    for (int i = n; i < 10; i++) {
+      addRedirectHandler(i, HttpStatus.movedPermanently);
+    }
+
+    // Setup redirect loop.
+    addRequestHandler("/A", (HttpRequest request, HttpResponse response) {
+      response.headers
+          .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/B");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+    addRequestHandler("/B", (HttpRequest request, HttpResponse response) {
+      response.headers
+          .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/A");
+      response.statusCode = HttpStatus.movedTemporarily;
+      response.close();
+    });
+
+    // Setup redirect checking headers.
+    addRequestHandler("/src", (HttpRequest request, HttpResponse response) {
+      Expect.equals("value", request.headers.value("X-Request-Header"));
+      response.headers.set(
+          HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/target");
+      response.statusCode = HttpStatus.movedPermanently;
+      response.close();
+    });
+    addRequestHandler("/target", (HttpRequest request, HttpResponse response) {
+      Expect.equals("value", request.headers.value("X-Request-Header"));
+      response.close();
+    });
+
+    // Setup redirect for 301 where POST should not redirect.
+    addRequestHandler("/301src", (HttpRequest request, HttpResponse response) {
+      Expect.equals("POST", request.method);
+      request.listen((_) {}, onDone: () {
+        response.headers.set(HttpHeaders.locationHeader,
+            "http://127.0.0.1:${server.port}/301target");
+        response.statusCode = HttpStatus.movedPermanently;
+        response.close();
+      });
+    });
+    addRequestHandler("/301target",
+        (HttpRequest request, HttpResponse response) {
+      Expect.fail("Redirect of POST should not happen");
+    });
+
+    // Setup redirect for 303 where POST should turn into GET.
+    addRequestHandler("/303src", (HttpRequest request, HttpResponse response) {
+      request.listen((_) {}, onDone: () {
+        Expect.equals("POST", request.method);
+        response.headers.set(HttpHeaders.locationHeader,
+            "http://127.0.0.1:${server.port}/303target");
+        response.statusCode = HttpStatus.seeOther;
+        response.close();
+      });
+    });
+    addRequestHandler("/303target",
+        (HttpRequest request, HttpResponse response) {
+      Expect.equals("GET", request.method);
+      response.close();
+    });
+
+    // Setup redirect where we close the connection.
+    addRequestHandler("/closing", (HttpRequest request, HttpResponse response) {
+      response.headers
+          .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/");
+      response.statusCode = HttpStatus.found;
+      response.persistentConnection = false;
+      response.close();
+    });
+
+    completer.complete(server);
+  });
+  return completer.future;
+}
+
+void checkRedirects(int redirectCount, HttpClientResponse response) {
+  if (redirectCount < 2) {
+    Expect.isTrue(response.redirects.isEmpty);
+  } else {
+    Expect.equals(redirectCount - 1, response.redirects.length);
+    for (int i = 0; i < redirectCount - 2; i++) {
+      Expect.equals(response.redirects[i].location.path, "/${i + 2}");
+    }
+  }
+}
+
+void testManualRedirect() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    int redirectCount = 0;
+    handleResponse(HttpClientResponse response) {
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        redirectCount++;
+        if (redirectCount < 10) {
+          Expect.isTrue(response.isRedirect);
+          checkRedirects(redirectCount, response);
+          response.redirect().then(handleResponse);
+        } else {
+          Expect.equals(HttpStatus.notFound, response.statusCode);
+          server.close();
+          client.close();
+        }
+      });
+    }
+
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/1"))
+        .then((HttpClientRequest request) {
+      request.followRedirects = false;
+      return request.close();
+    }).then(handleResponse);
+  });
+}
+
+void testManualRedirectWithHeaders() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    int redirectCount = 0;
+
+    handleResponse(HttpClientResponse response) {
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        redirectCount++;
+        if (redirectCount < 2) {
+          Expect.isTrue(response.isRedirect);
+          response.redirect().then(handleResponse);
+        } else {
+          Expect.equals(HttpStatus.ok, response.statusCode);
+          server.close();
+          client.close();
+        }
+      });
+    }
+
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/src"))
+        .then((HttpClientRequest request) {
+      request.followRedirects = false;
+      request.headers.add("X-Request-Header", "value");
+      return request.close();
+    }).then(handleResponse);
+  });
+}
+
+void testAutoRedirect() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/redirect"))
+        .then((HttpClientRequest request) {
+      return request.close();
+    }).then((HttpClientResponse response) {
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        Expect.equals(1, response.redirects.length);
+        server.close();
+        client.close();
+      });
+    });
+  });
+}
+
+void testAutoRedirectWithHeaders() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/src"))
+        .then((HttpClientRequest request) {
+      request.headers.add("X-Request-Header", "value");
+      return request.close();
+    }).then((HttpClientResponse response) {
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        Expect.equals(1, response.redirects.length);
+        server.close();
+        client.close();
+      });
+    });
+  });
+}
+
+void testAutoRedirect301POST() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .postUrl(Uri.parse("http://127.0.0.1:${server.port}/301src"))
+        .then((HttpClientRequest request) {
+      return request.close();
+    }).then((HttpClientResponse response) {
+      Expect.equals(HttpStatus.movedPermanently, response.statusCode);
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        Expect.equals(0, response.redirects.length);
+        server.close();
+        client.close();
+      });
+    });
+  });
+}
+
+void testAutoRedirect303POST() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .postUrl(Uri.parse("http://127.0.0.1:${server.port}/303src"))
+        .then((HttpClientRequest request) {
+      return request.close();
+    }).then((HttpClientResponse response) {
+      Expect.equals(HttpStatus.ok, response.statusCode);
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        Expect.equals(1, response.redirects.length);
+        server.close();
+        client.close();
+      });
+    });
+  });
+}
+
+void testAutoRedirectLimit() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    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();
+      client.close();
+    }, test: (e) => e is RedirectException);
+  });
+}
+
+void testRedirectLoop() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    int redirectCount = 0;
+    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();
+      client.close();
+    }, test: (e) => e is RedirectException);
+  });
+}
+
+void testRedirectClosingConnection() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .getUrl(Uri.parse("http://127.0.0.1:${server.port}/closing"))
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}, onDone: () {
+        Expect.equals(1, response.redirects.length);
+        server.close();
+        client.close();
+      });
+    });
+  });
+}
+
+void testRedirectRelativeUrl() {
+  testPath(String path) {
+    setupServer().then((server) {
+      HttpClient client = new HttpClient();
+
+      print(path);
+      client
+          .getUrl(Uri.parse("http://127.0.0.1:${server.port}$path"))
+          .then((request) => request.close())
+          .then((response) {
+        response.listen((_) {}, onDone: () {
+          Expect.equals(HttpStatus.ok, response.statusCode);
+          Expect.equals(1, response.redirects.length);
+          server.close();
+          client.close();
+        });
+      });
+    });
+  }
+
+  testPath("/redirectUrl");
+  testPath("/some/redirectUrl");
+  testPath("/redirectUrl2");
+  testPath("/redirectUrl3");
+  testPath("/redirectUrl4");
+  testPath("/redirectUrl5");
+}
+
+void testRedirectRelativeToAbsolute() {
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    int redirectCount = 0;
+    handleResponse(HttpClientResponse response) {
+      response.listen((_) => Expect.fail("Response data not expected"),
+          onDone: () {
+        Expect.equals(HttpStatus.seeOther, response.statusCode);
+        Expect.equals("xxx", response.headers["Location"]![0]);
+        Expect.isTrue(response.isRedirect);
+        server.close();
+        client.close();
+      });
+    }
+
+    client
+        .getUrl(Uri.parse(
+            "http://127.0.0.1:${server.port}/some/relativeToAbsolute"))
+        .then((HttpClientRequest request) {
+      request.followRedirects = false;
+      return request.close();
+    }).then(handleResponse);
+  });
+}
+
+main() {
+  testManualRedirect();
+  testManualRedirectWithHeaders();
+  testAutoRedirect();
+  testAutoRedirectWithHeaders();
+  testAutoRedirect301POST();
+  testAutoRedirect303POST();
+  testAutoRedirectLimit();
+  testRedirectLoop();
+  testRedirectClosingConnection();
+  testRedirectRelativeUrl();
+  testRedirectRelativeToAbsolute();
+}
diff --git a/tests/standalone/io/http_request_pipeling_test.dart b/tests/standalone/io/http_request_pipeling_test.dart
new file mode 100644
index 0000000..4acb06f
--- /dev/null
+++ b/tests/standalone/io/http_request_pipeling_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:io";
+import "package:expect/expect.dart";
+
+void main() {
+  final int REQUEST_COUNT = 100;
+  int count = 0;
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      count++;
+      request.response.write(request.uri.path);
+      request.response.close();
+      if (request.uri.path == "/done") {
+        request.response.done.then((_) {
+          Expect.equals(REQUEST_COUNT + 1, count);
+          server.close();
+        });
+      }
+    });
+    Socket.connect("127.0.0.1", server.port).then((s) {
+      s.listen((data) {});
+      for (int i = 0; i < REQUEST_COUNT; i++) {
+        s.write("GET /$i HTTP/1.1\r\nX-Header-1: 111\r\n\r\n");
+      }
+      s.write("GET /done HTTP/1.1\r\nConnection: close\r\n\r\n");
+      s.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/http_requested_uri_test.dart b/tests/standalone/io/http_requested_uri_test.dart
new file mode 100644
index 0000000..17fb889
--- /dev/null
+++ b/tests/standalone/io/http_requested_uri_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.
+
+import "dart:async";
+import "dart:io";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+const sendPath = '/path?a=b#c';
+const expectedPath = '/path?a=b';
+
+void test(String expected, Map headers) {
+  asyncStart();
+  HttpServer.bind("localhost", 0).then((server) {
+    expected = expected.replaceAll('%PORT', server.port.toString());
+    server.listen((request) {
+      Expect.equals("$expected$expectedPath", request.requestedUri.toString());
+      request.response.close();
+    });
+    HttpClient client = new HttpClient();
+    client
+        .get("localhost", server.port, sendPath)
+        .then((request) {
+          for (var v in headers.keys) {
+            if (headers[v] != null) {
+              request.headers.set(v, headers[v]);
+            } else {
+              request.headers.removeAll(v);
+            }
+          }
+          return request.close();
+        })
+        .then((response) => response.drain())
+        .then((_) {
+          server.close();
+          asyncEnd();
+        });
+  });
+}
+
+void main() {
+  test('http://localhost:%PORT', {});
+  test('https://localhost:%PORT', {'x-forwarded-proto': 'https'});
+  test('ws://localhost:%PORT', {'x-forwarded-proto': 'ws'});
+  test('http://my-host:321', {'x-forwarded-host': 'my-host:321'});
+  test('http://localhost:%PORT', {'host': null});
+}
diff --git a/tests/standalone/io/http_response_deadline_test.dart b/tests/standalone/io/http_response_deadline_test.dart
new file mode 100644
index 0000000..18ee490
--- /dev/null
+++ b/tests/standalone/io/http_response_deadline_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+void testSimpleDeadline(int connections) {
+  HttpServer.bind('localhost', 0).then((server) {
+    server.listen((request) {
+      request.response.deadline = const Duration(seconds: 1000);
+      request.response.write("stuff");
+      request.response.close();
+    });
+
+    var futures = <Future>[];
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      futures.add(client
+          .get('localhost', server.port, '/')
+          .then((request) => request.close())
+          .then((response) => response.drain()));
+    }
+    Future.wait(futures).then((_) => server.close());
+  });
+}
+
+void testExceedDeadline(int connections) {
+  HttpServer.bind('localhost', 0).then((server) {
+    server.listen((request) {
+      request.response.deadline = const Duration(milliseconds: 100);
+      request.response.contentLength = 10000;
+      request.response.write("stuff");
+    });
+
+    var futures = <Future>[];
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      futures.add(client
+          .get('localhost', server.port, '/')
+          .then((request) => request.close())
+          .then((response) => response.drain())
+          .then((_) {
+        Expect.fail("Expected error");
+      }, onError: (e) {
+        // Expect error.
+      }));
+    }
+    Future.wait(futures).then((_) => server.close());
+  });
+}
+
+void testDeadlineAndDetach(int connections) {
+  HttpServer.bind('localhost', 0).then((server) {
+    server.listen((request) {
+      request.response.deadline = const Duration(milliseconds: 0);
+      request.response.contentLength = 5;
+      request.response.persistentConnection = false;
+      request.response.detachSocket().then((socket) {
+        new Timer(const Duration(milliseconds: 100), () {
+          socket.write('stuff');
+          socket.close();
+          socket.listen(null);
+        });
+      });
+    });
+
+    var futures = <Future>[];
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      futures.add(client
+          .get('localhost', server.port, '/')
+          .then((request) => request.close())
+          .then((response) {
+        return response
+            .fold<BytesBuilder>(new BytesBuilder(), (b, d) => b..add(d))
+            .then((builder) {
+          Expect.equals('stuff', new String.fromCharCodes(builder.takeBytes()));
+        });
+      }));
+    }
+    Future.wait(futures).then((_) => server.close());
+  });
+}
+
+void main() {
+  testSimpleDeadline(10);
+  testExceedDeadline(10);
+  testDeadlineAndDetach(10);
+}
diff --git a/tests/standalone/io/http_reuse_server_port_test.dart b/tests/standalone/io/http_reuse_server_port_test.dart
new file mode 100644
index 0000000..afcaf61
--- /dev/null
+++ b/tests/standalone/io/http_reuse_server_port_test.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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<int> runServer(int port, int connections, bool clean) {
+  var completer = new Completer<int>();
+  HttpServer.bind("127.0.0.1", port).then((server) {
+    int i = 0;
+    server.listen((request) {
+      request.cast<List<int>>().pipe(request.response);
+      i++;
+      if (!clean && i == 10) {
+        int port = server.port;
+        server.close().then((_) => completer.complete(port));
+      }
+    });
+
+    Future.wait(new List.generate(connections, (_) {
+      var client = new HttpClient();
+      return client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) => response.drain())
+          .catchError((e) {
+        if (clean) throw e;
+      });
+    })).then((_) {
+      if (clean) {
+        int port = server.port;
+        server.close().then((_) => completer.complete(port));
+      }
+    });
+  });
+  return completer.future;
+}
+
+void testReusePort() {
+  asyncStart();
+  runServer(0, 10, true).then((int port) {
+    // Stress test the port reusing it 10 times.
+    Future.forEach(new List(10), (_) {
+      return runServer(port, 10, true);
+    }).then((_) {
+      asyncEnd();
+    });
+  });
+}
+
+void testUncleanReusePort() {
+  asyncStart();
+  runServer(0, 10, false).then((int port) {
+    // Stress test the port reusing it 10 times.
+    Future.forEach(new List(10), (_) {
+      return runServer(port, 10, false);
+    }).then((_) {
+      asyncEnd();
+    });
+  });
+}
+
+void main() {
+  testReusePort();
+  testUncleanReusePort();
+}
diff --git a/tests/standalone/io/http_server_close_response_after_error_client.dart b/tests/standalone/io/http_server_close_response_after_error_client.dart
new file mode 100644
index 0000000..beee23a
--- /dev/null
+++ b/tests/standalone/io/http_server_close_response_after_error_client.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:async';
+import 'dart:io';
+
+void main(List<String> arguments) {
+  int port = int.parse(arguments.first);
+  var client = new HttpClient();
+  const MAX = 64;
+  int count = 0;
+  void run() {
+    if (count++ == MAX) exit(0);
+    Socket.connect('127.0.0.1', port).then((socket) {
+      socket.write("POST / HTTP/1.1\r\n");
+      socket.write("Content-Length: 10\r\n");
+      socket.write("\r\n");
+      socket.write("LALALA");
+      socket.destroy();
+      socket.listen(null, onDone: run);
+    });
+  }
+
+  for (int i = 0; i < 4; i++) run();
+}
diff --git a/tests/standalone/io/http_server_close_response_after_error_test.dart b/tests/standalone/io/http_server_close_response_after_error_test.dart
new file mode 100644
index 0000000..eb45423a
--- /dev/null
+++ b/tests/standalone/io/http_server_close_response_after_error_test.dart
@@ -0,0 +1,36 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=http_server_close_response_after_error_client.dart
+
+import 'dart:async';
+import 'dart:io';
+
+const CLIENT_SCRIPT = "http_server_close_response_after_error_client.dart";
+
+void main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.listen(null, onError: (e) {}, onDone: () {
+        request.response.close();
+      });
+    });
+    Process.run(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..addAll([
+                Platform.script.resolve(CLIENT_SCRIPT).toString(),
+                server.port.toString()
+              ]))
+        .then((result) {
+      if (result.exitCode != 0) throw "Bad exit code";
+      server.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/http_server_early_client_close2_test.dart b/tests/standalone/io/http_server_early_client_close2_test.dart
new file mode 100644
index 0000000..1a84dfd
--- /dev/null
+++ b/tests/standalone/io/http_server_early_client_close2_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+
+main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      String name = Platform.script.toFilePath();
+      new File(name)
+          .openRead()
+          .cast<List<int>>()
+          .pipe(request.response)
+          .catchError((e) {/* ignore */});
+    });
+
+    var count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+        socket.write(data);
+        socket.close();
+        socket.done.then((_) {
+          socket.destroy();
+          if (++count < 10) {
+            makeRequest();
+          } else {
+            server.close();
+          }
+        });
+      });
+    }
+
+    makeRequest();
+  });
+}
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
new file mode 100644
index 0000000..33ab0e1
--- /dev/null
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -0,0 +1,165 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+
+Future sendData(List<int> data, int port) {
+  return Socket.connect("127.0.0.1", port).then((socket) {
+    socket.listen((data) {
+      Expect.fail("No data response was expected");
+    });
+    socket.add(data);
+    return socket.close().then((_) {
+      socket.destroy();
+    });
+  });
+}
+
+class EarlyCloseTest {
+  EarlyCloseTest(this.data, [this.exception, this.expectRequest = false]);
+
+  Future execute() {
+    return HttpServer.bind("127.0.0.1", 0).then((server) {
+      Completer c = new Completer();
+
+      bool calledOnRequest = false;
+      bool calledOnError = false;
+      bool calledOnDone = false;
+      ReceivePort port = new ReceivePort();
+      var requestCompleter = new Completer();
+      server.listen((request) {
+        Expect.isTrue(expectRequest);
+        Expect.isFalse(calledOnError);
+        Expect.isFalse(calledOnRequest, "onRequest called multiple times");
+        calledOnRequest = true;
+        request.listen((_) {}, onDone: () {
+          requestCompleter.complete();
+        }, onError: (error) {
+          Expect.isFalse(calledOnError);
+          Expect.equals(exception, error.message);
+          calledOnError = true;
+          if (exception != null) port.close();
+        });
+      }, onDone: () {
+        Expect.equals(expectRequest, calledOnRequest);
+        calledOnDone = true;
+        if (exception == null) port.close();
+        c.complete(null);
+      });
+
+      List<int>? d;
+      if (data is List<int>) d = data;
+      if (data is String) d = data.codeUnits;
+      if (d == null) Expect.fail("Invalid data");
+      sendData(d!, server.port).then((_) {
+        if (!expectRequest) requestCompleter.complete();
+        requestCompleter.future.then((_) => server.close());
+      });
+
+      return c.future;
+    });
+  }
+
+  final data;
+  final String? exception;
+  final bool expectRequest;
+}
+
+void testEarlyClose1() {
+  List<EarlyCloseTest> tests = new List<EarlyCloseTest>();
+  void add(Object data, [String? exception, bool expectRequest = false]) {
+    tests.add(new EarlyCloseTest(data, exception, expectRequest));
+  }
+  // The empty packet is valid.
+
+  // Close while sending header
+  add("G");
+  add("GET /");
+  add("GET / HTTP/1.1");
+  add("GET / HTTP/1.1\r\n");
+
+  // Close while sending content
+  add("GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n",
+      "Connection closed while receiving data", true);
+  add("GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n1",
+      "Connection closed while receiving data", true);
+
+  void runTest(Iterator it) {
+    if (it.moveNext()) {
+      it.current.execute().then((_) {
+        runTest(it);
+      });
+    }
+  }
+
+  runTest(tests.iterator);
+}
+
+testEarlyClose2() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      String name = Platform.script.toFilePath();
+      new File(name)
+          .openRead()
+          .cast<List<int>>()
+          .pipe(request.response)
+          .catchError((e) {/* ignore */});
+    });
+
+    var count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+        socket.write(data);
+        socket.close();
+        socket.done.then((_) {
+          socket.destroy();
+          if (++count < 10) {
+            makeRequest();
+          } else {
+            scheduleMicrotask(server.close);
+          }
+        });
+      });
+    }
+
+    makeRequest();
+  });
+}
+
+void testEarlyClose3() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      var subscription;
+      subscription = request.listen((_) {}, onError: (error) {
+        // subscription.cancel should not trigger an error.
+        subscription.cancel();
+        server.close();
+      });
+    });
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.write("GET / HTTP/1.1\r\n");
+      socket.write("Content-Length: 10\r\n");
+      socket.write("\r\n");
+      socket.write("data");
+      socket.close();
+      socket.listen((_) {}, onError: (_) {});
+      socket.done.catchError((_) {});
+    });
+  });
+}
+
+void main() {
+  testEarlyClose1();
+  testEarlyClose2();
+  testEarlyClose3();
+}
diff --git a/tests/standalone/io/http_server_idle_timeout_test.dart b/tests/standalone/io/http_server_idle_timeout_test.dart
new file mode 100644
index 0000000..247bb6f
--- /dev/null
+++ b/tests/standalone/io/http_server_idle_timeout_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+void testTimeoutAfterRequest() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.idleTimeout = null;
+
+    server.listen((request) {
+      server.idleTimeout = const Duration(milliseconds: 100);
+      request.response.close();
+    });
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+      socket.write(data);
+      socket.listen(null, onDone: () {
+        socket.close();
+        server.close();
+      });
+    });
+  });
+}
+
+void testTimeoutBeforeRequest() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.idleTimeout = const Duration(milliseconds: 100);
+
+    server.listen((request) => request.response.close());
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.listen(null, onDone: () {
+        socket.close();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testTimeoutAfterRequest();
+  testTimeoutBeforeRequest();
+}
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
new file mode 100644
index 0000000..8858c1cd
--- /dev/null
+++ b/tests/standalone/io/http_server_response_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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=http_server_response_test.dart
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+
+// Platform.script may refer to a AOT or JIT snapshot, which are significantly
+// larger.
+File scriptSource = new File(
+    Platform.script.resolve("http_server_response_test.dart").toFilePath());
+
+void testServerRequest(void handler(server, request),
+    {int? bytes, bool closeClient = false}) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.defaultResponseHeaders.clear();
+    server.listen((request) {
+      handler(server, request);
+    });
+
+    var client = new HttpClient();
+    // We only close the client on either
+    // - Bad response headers
+    // - Response done (with optional errors in between).
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      int received = 0;
+      var subscription;
+      subscription = response.listen((data) {
+        if (closeClient) {
+          subscription.cancel();
+          client.close();
+        } else {
+          received += data.length;
+        }
+      }, onDone: () {
+        if (bytes != null) Expect.equals(received, bytes);
+        client.close();
+      }, onError: (error) {
+        Expect.isTrue(error is HttpException);
+      });
+    }).catchError((error) {
+      client.close();
+    }, test: (e) => e is HttpException);
+  });
+}
+
+void testResponseDone() {
+  testServerRequest((server, request) {
+    request.response.close();
+    request.response.done.then((response) {
+      Expect.equals(request.response, response);
+      server.close();
+    });
+  });
+
+  testServerRequest((server, request) {
+    new File("__nonexistent_file_")
+        .openRead()
+        .cast<List<int>>()
+        .pipe(request.response)
+        .catchError((e) {
+      server.close();
+    });
+  });
+
+  testServerRequest((server, request) {
+    request.response.done.then((_) {
+      server.close();
+    });
+    request.response.contentLength = 0;
+    request.response.close();
+  });
+}
+
+void testResponseAddStream() {
+  File file = scriptSource;
+  int bytes = file.lengthSync();
+
+  testServerRequest((server, request) {
+    request.response.addStream(file.openRead()).then((response) {
+      response.close();
+      response.done.then((_) => server.close());
+    });
+  }, bytes: bytes);
+
+  testServerRequest((server, request) {
+    request.response.addStream(file.openRead()).then((response) {
+      request.response.addStream(file.openRead()).then((response) {
+        response.close();
+        response.done.then((_) => server.close());
+      });
+    });
+  }, bytes: bytes * 2);
+
+  testServerRequest((server, request) {
+    var controller = new StreamController<List<int>>(sync: true);
+    request.response.addStream(controller.stream).then((response) {
+      response.close();
+      response.done.then((_) => server.close());
+    });
+    controller.close();
+  }, bytes: 0);
+
+  testServerRequest((server, request) {
+    request.response
+        .addStream(new File("__nonexistent_file_").openRead())
+        .catchError((e) {
+      server.close();
+    });
+  });
+
+  testServerRequest((server, request) {
+    new File("__nonexistent_file_")
+        .openRead()
+        .cast<List<int>>()
+        .pipe(request.response)
+        .catchError((e) {
+      server.close();
+    });
+  });
+}
+
+void testResponseAddStreamClosed() {
+  File file = scriptSource;
+  testServerRequest((server, request) {
+    request.response.addStream(file.openRead()).then((response) {
+      response.close();
+      response.done.then((_) => server.close());
+    });
+  }, closeClient: true);
+
+  testServerRequest((server, request) {
+    int count = 0;
+    write() {
+      request.response.addStream(file.openRead()).then((response) {
+        request.response.write("sync data");
+        count++;
+        if (count < 1000) {
+          write();
+        } else {
+          response.close();
+          response.done.then((_) => server.close());
+        }
+      });
+    }
+
+    write();
+  }, closeClient: true);
+}
+
+void testResponseAddClosed() {
+  File file = scriptSource;
+  testServerRequest((server, request) {
+    request.response.add(file.readAsBytesSync());
+    request.response.close();
+    request.response.done.then((_) => server.close());
+  }, closeClient: true);
+
+  testServerRequest((server, request) {
+    for (int i = 0; i < 1000; i++) {
+      request.response.add(file.readAsBytesSync());
+    }
+    request.response.close();
+    request.response.done.then((_) => server.close());
+  }, closeClient: true);
+
+  testServerRequest((server, request) {
+    int count = 0;
+    write() {
+      request.response.add(file.readAsBytesSync());
+      Timer.run(() {
+        count++;
+        if (count < 1000) {
+          write();
+        } else {
+          request.response.close();
+          request.response.done.then((_) => server.close());
+        }
+      });
+    }
+
+    write();
+  }, closeClient: true);
+}
+
+void testBadResponseAdd() {
+  testServerRequest((server, request) {
+    request.response.contentLength = 0;
+    request.response.add([0]);
+    request.response.close();
+    request.response.done.catchError((error) {
+      server.close();
+    }, test: (e) => e is HttpException);
+  });
+
+  testServerRequest((server, request) {
+    request.response.contentLength = 5;
+    request.response.add([0, 0, 0]);
+    request.response.add([0, 0, 0]);
+    request.response.close();
+    request.response.done.catchError((error) {
+      server.close();
+    }, test: (e) => e is HttpException);
+  });
+
+  testServerRequest((server, request) {
+    request.response.contentLength = 0;
+    request.response.add(new Uint8List(64 * 1024));
+    request.response.add(new Uint8List(64 * 1024));
+    request.response.add(new Uint8List(64 * 1024));
+    request.response.close();
+    request.response.done.catchError((error) {
+      server.close();
+    }, test: (e) => e is HttpException);
+  });
+}
+
+void testBadResponseClose() {
+  testServerRequest((server, request) {
+    request.response.contentLength = 5;
+    request.response.close();
+    request.response.done.catchError((error) {
+      server.close();
+    }, test: (e) => e is HttpException);
+  });
+
+  testServerRequest((server, request) {
+    request.response.contentLength = 5;
+    request.response.add([0]);
+    request.response.close();
+    request.response.done.catchError((error) {
+      server.close();
+    }, test: (e) => e is HttpException);
+  });
+}
+
+void testIgnoreRequestData() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      // Ignore request data.
+      request.response.write("all-okay");
+      request.response.close();
+    });
+
+    var client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/").then((request) {
+      request.contentLength = 1024 * 1024;
+      request.add(new Uint8List(1024 * 1024));
+      return request.close();
+    }).then((response) {
+      response.fold<int>(0, (s, b) => s + b.length).then((bytes) {
+        Expect.equals(8, bytes);
+        server.close();
+      });
+    });
+  });
+}
+
+void testWriteCharCode() {
+  testServerRequest((server, request) {
+    // Test that default is latin-1 (only 2 bytes).
+    request.response.writeCharCode(0xFF);
+    request.response.writeCharCode(0xFF);
+    request.response.close().then((_) {
+      server.close();
+    });
+  }, bytes: 2);
+}
+
+void main() {
+  testResponseDone();
+  testResponseAddStream();
+  testResponseAddStreamClosed();
+  testResponseAddClosed();
+  testBadResponseAdd();
+  testBadResponseClose();
+  testIgnoreRequestData();
+  testWriteCharCode();
+}
diff --git a/tests/standalone/io/http_server_test.dart b/tests/standalone/io/http_server_test.dart
new file mode 100644
index 0000000..911d7bf
--- /dev/null
+++ b/tests/standalone/io/http_server_test.dart
@@ -0,0 +1,218 @@
+// 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:typed_data";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testDefaultResponseHeaders() {
+  checkDefaultHeaders(headers) {
+    Expect.listEquals(
+        headers[HttpHeaders.contentTypeHeader], ['text/plain; charset=utf-8']);
+    Expect.listEquals(headers['X-Frame-Options'], ['SAMEORIGIN']);
+    Expect.listEquals(headers['X-Content-Type-Options'], ['nosniff']);
+    Expect.listEquals(headers['X-XSS-Protection'], ['1; mode=block']);
+  }
+
+  checkDefaultHeadersClear(headers) {
+    Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
+    Expect.isNull(headers['X-Frame-Options']);
+    Expect.isNull(headers['X-Content-Type-Options']);
+    Expect.isNull(headers['X-XSS-Protection']);
+  }
+
+  checkDefaultHeadersClearAB(headers) {
+    Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
+    Expect.isNull(headers['X-Frame-Options']);
+    Expect.isNull(headers['X-Content-Type-Options']);
+    Expect.isNull(headers['X-XSS-Protection']);
+    Expect.listEquals(headers['a'], ['b']);
+  }
+
+  test(bool clearHeaders, Map? defaultHeaders, Function checker) {
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      if (clearHeaders) server.defaultResponseHeaders.clear();
+      if (defaultHeaders != null) {
+        defaultHeaders.forEach(
+            (name, value) => server.defaultResponseHeaders.add(name, value));
+      }
+      checker(server.defaultResponseHeaders);
+      server.listen((request) {
+        request.response.close();
+      });
+
+      HttpClient client = new HttpClient();
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+        checker(response.headers);
+        server.close();
+        client.close();
+      });
+    });
+  }
+
+  test(false, null, checkDefaultHeaders);
+  test(true, null, checkDefaultHeadersClear);
+  test(true, {'a': 'b'}, checkDefaultHeadersClearAB);
+}
+
+void testDefaultResponseHeadersContentType() {
+  test(bool clearHeaders, String requestBody, List<int> responseBody) {
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      if (clearHeaders) server.defaultResponseHeaders.clear();
+      server.listen((request) {
+        request.response.write(requestBody);
+        request.response.close();
+      });
+
+      HttpClient client = new HttpClient();
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+        response.fold<List<int>>([], (a, b) => a..addAll(b)).then((body) {
+          Expect.listEquals(body, responseBody);
+        }).whenComplete(() {
+          server.close();
+          client.close();
+        });
+      });
+    });
+  }
+
+  test(false, 'æøå', [195, 166, 195, 184, 195, 165]);
+  test(true, 'æøå', [230, 248, 229]);
+}
+
+void testListenOn() {
+  late ServerSocket socket;
+  late HttpServer server;
+
+  void test(void onDone()) {
+    Expect.equals(socket.port, server.port);
+
+    HttpClient client = new HttpClient();
+    client.get("127.0.0.1", socket.port, "/").then((request) {
+      return request.close();
+    }).then((response) {
+      response.listen((_) {}, onDone: () {
+        client.close();
+        onDone();
+      });
+    }).catchError((e, trace) {
+      String msg = "Unexpected error in Http Client: $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      Expect.fail(msg);
+    });
+  }
+
+  // Test two connection after each other.
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((s) {
+    socket = s;
+    server = new HttpServer.listenOn(socket);
+    Expect.equals(server.address.address, '127.0.0.1');
+    Expect.equals(server.address.host, '127.0.0.1');
+    server.listen((HttpRequest request) {
+      request.listen((_) {}, onDone: () => request.response.close());
+    });
+
+    test(() {
+      test(() {
+        server.close();
+        Expect.throws(() => server.port);
+        Expect.throws(() => server.address);
+        socket.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+void testHttpServerZone() {
+  asyncStart();
+  Expect.equals(Zone.root, Zone.current);
+  runZoned(() {
+    Expect.notEquals(Zone.root, Zone.current);
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      Expect.notEquals(Zone.root, Zone.current);
+      server.listen((request) {
+        Expect.notEquals(Zone.root, Zone.current);
+        request.response.close();
+        server.close();
+      });
+      new HttpClient()
+          .get("127.0.0.1", server.port, '/')
+          .then((request) => request.close())
+          .then((response) => response.drain())
+          .then((_) => asyncEnd());
+    });
+  });
+}
+
+void testHttpServerZoneError() {
+  asyncStart();
+  Expect.equals(Zone.root, Zone.current);
+  runZoned(() {
+    Expect.notEquals(Zone.root, Zone.current);
+    HttpServer.bind("127.0.0.1", 0).then((server) {
+      Expect.notEquals(Zone.root, Zone.current);
+      server.listen((request) {
+        Expect.notEquals(Zone.root, Zone.current);
+        request.listen((_) {}, onError: (error) {
+          Expect.notEquals(Zone.root, Zone.current);
+          server.close();
+          throw error;
+        });
+      });
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.write('GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n');
+        socket.write('some body');
+        socket.close();
+        socket.listen(null);
+      });
+    });
+  }, onError: (e) {
+    asyncEnd();
+  });
+}
+
+void testHttpServerClientClose() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    runZoned(() {
+      server.listen((request) {
+        request.response.bufferOutput = false;
+        request.response.add(new Uint8List(64 * 1024));
+        new Timer(const Duration(milliseconds: 100), () {
+          request.response.close().then((_) {
+            server.close();
+          });
+        });
+      });
+    }, onError: (e, s) {
+      Expect.fail("Unexpected error: $e(${e.hashCode})\n$s");
+    });
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}).cancel();
+    });
+  });
+}
+
+void main() {
+  testDefaultResponseHeaders();
+  testDefaultResponseHeadersContentType();
+  testListenOn();
+  testHttpServerZone();
+  testHttpServerZoneError();
+  testHttpServerClientClose();
+}
diff --git a/tests/standalone/io/http_session_test.dart b/tests/standalone/io/http_session_test.dart
new file mode 100644
index 0000000..e410498
--- /dev/null
+++ b/tests/standalone/io/http_session_test.dart
@@ -0,0 +1,198 @@
+// 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 'dart:async';
+import 'dart:io';
+
+const SESSION_ID = "DARTSESSID";
+
+String getSessionId(List<Cookie> cookies) {
+  var id = cookies.fold<String?>(null, (last, cookie) {
+    if (last != null) return last;
+    if (cookie.name.toUpperCase() == SESSION_ID) {
+      Expect.isTrue(cookie.httpOnly);
+      return cookie.value;
+    }
+    return null;
+  });
+  Expect.isNotNull(id);
+  return id!;
+}
+
+Future<String> connectGetSession(HttpClient client, int port,
+    [String? session]) {
+  return client.get("127.0.0.1", port, "/").then((request) {
+    if (session != null) {
+      request.cookies.add(new Cookie(SESSION_ID, session));
+    }
+    return request.close();
+  }).then((response) {
+    return response.fold(getSessionId(response.cookies), (v, _) => v);
+  });
+}
+
+void testSessions(int sessionCount) {
+  var client = new HttpClient();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    var sessions = new Set();
+    server.listen((request) {
+      sessions.add(request.session.id);
+      request.response.close();
+    });
+
+    var futures = <Future>[];
+    for (int i = 0; i < sessionCount; i++) {
+      futures.add(connectGetSession(client, server.port).then((session) {
+        Expect.isNotNull(session);
+        Expect.isTrue(sessions.contains(session));
+        return connectGetSession(client, server.port, session).then((session2) {
+          Expect.equals(session2, session);
+          Expect.isTrue(sessions.contains(session2));
+          return session2;
+        });
+      }));
+    }
+    Future.wait(futures).then((clientSessions) {
+      Expect.equals(sessions.length, sessionCount);
+      Expect.setEquals(new Set.from(clientSessions), sessions);
+      server.close();
+      client.close();
+    });
+  });
+}
+
+void testTimeout(int sessionCount) {
+  var client = new HttpClient();
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.sessionTimeout = 1;
+    var timeouts = <Future>[];
+    server.listen((request) {
+      var c = new Completer();
+      timeouts.add(c.future);
+      request.session.onTimeout = () {
+        c.complete(null);
+      };
+      request.response.close();
+    });
+
+    var futures = <Future>[];
+    for (int i = 0; i < sessionCount; i++) {
+      futures.add(connectGetSession(client, server.port));
+    }
+    Future.wait(futures).then((clientSessions) {
+      Future.wait(timeouts).then((_) {
+        futures = <Future>[];
+        for (var id in clientSessions) {
+          futures
+              .add(connectGetSession(client, server.port, id).then((session) {
+            Expect.isNotNull(session);
+            Expect.notEquals(id, session);
+          }));
+        }
+        Future.wait(futures).then((_) {
+          server.close();
+          client.close();
+        });
+      });
+    });
+  });
+}
+
+void testSessionsData() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    bool firstHit = false;
+    bool secondHit = false;
+    server.listen((request) {
+      var c = new Completer();
+      var session = request.session;
+      if (session.isNew) {
+        Expect.isFalse(firstHit);
+        Expect.isFalse(secondHit);
+        firstHit = true;
+        session["data"] = "some data";
+      } else {
+        Expect.isTrue(firstHit);
+        Expect.isFalse(secondHit);
+        secondHit = true;
+        Expect.isTrue(session.containsKey("data"));
+        Expect.equals("some data", session["data"]);
+      }
+      ;
+      request.response.close();
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}, onDone: () {
+        var id = getSessionId(response.cookies);
+        Expect.isNotNull(id);
+        client.get("127.0.0.1", server.port, "/").then((request) {
+          request.cookies.add(new Cookie(SESSION_ID, id));
+          return request.close();
+        }).then((response) {
+          response.listen((_) {}, onDone: () {
+            Expect.isTrue(firstHit);
+            Expect.isTrue(secondHit);
+            Expect.equals(id, getSessionId(response.cookies));
+            server.close();
+            client.close();
+          });
+        });
+      });
+    });
+  });
+}
+
+void testSessionsDestroy() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    bool firstHit = false;
+    server.listen((request) {
+      var session = request.session;
+      if (session.isNew) {
+        Expect.isFalse(firstHit);
+        firstHit = true;
+      } else {
+        Expect.isTrue(firstHit);
+        session.destroy();
+        var session2 = request.session;
+        Expect.notEquals(session.id, session2.id);
+      }
+      ;
+      request.response.close();
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}, onDone: () {
+        var id = getSessionId(response.cookies);
+        Expect.isNotNull(id);
+        client.get("127.0.0.1", server.port, "/").then((request) {
+          request.cookies.add(new Cookie(SESSION_ID, id));
+          return request.close();
+        }).then((response) {
+          response.listen((_) {}, onDone: () {
+            Expect.isTrue(firstHit);
+            Expect.notEquals(id, getSessionId(response.cookies));
+            server.close();
+            client.close();
+          });
+        });
+      });
+    });
+  });
+}
+
+void main() {
+  testSessions(1);
+  testTimeout(5);
+  testSessionsData();
+  testSessionsDestroy();
+}
diff --git a/tests/standalone/io/http_shutdown_test.dart b/tests/standalone/io/http_shutdown_test.dart
new file mode 100644
index 0000000..c04a537
--- /dev/null
+++ b/tests/standalone/io/http_shutdown_test.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "package:expect/expect.dart";
+
+void test1(int totalConnections) {
+  // Server which just closes immediately.
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      request.response.close();
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          count++;
+          if (count == totalConnections) {
+            client.close();
+            server.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+void test2(int totalConnections, int outputStreamWrites) {
+  // Server which responds without waiting for request body.
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      request.response.write("!dlrow ,olleH");
+      request.response.close();
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) {
+        request.contentLength = -1;
+        for (int i = 0; i < outputStreamWrites; i++) {
+          request.write("Hello, world!");
+        }
+        request.done.catchError((_) {});
+        return request.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          count++;
+          if (count == totalConnections) {
+            client.close(force: true);
+            server.close();
+          }
+        }, onError: (e) {} /* ignore */);
+      }).catchError((error) {
+        count++;
+        if (count == totalConnections) {
+          client.close();
+          server.close();
+        }
+      });
+    }
+  });
+}
+
+void test3(int totalConnections) {
+  // Server which responds when request body has been received.
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((HttpRequest request) {
+      request.listen((_) {}, onDone: () {
+        request.response.write("!dlrow ,olleH");
+        request.response.close();
+      });
+    });
+
+    int count = 0;
+    HttpClient client = new HttpClient();
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) {
+        request.contentLength = -1;
+        request.write("Hello, world!");
+        return request.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          count++;
+          if (count == totalConnections) {
+            client.close();
+            server.close();
+          }
+        });
+      });
+    }
+  });
+}
+
+void test4() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((var request) {
+      request.listen((_) {}, onDone: () {
+        new Timer.periodic(new Duration(milliseconds: 100), (timer) {
+          if (server.connectionsInfo().total == 0) {
+            server.close();
+            timer.cancel();
+          }
+        });
+        request.response.close();
+      });
+    });
+
+    var client = new HttpClient();
+    client
+        .get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+      response.listen((_) {}, onDone: () {
+        client.close();
+      });
+    });
+  });
+}
+
+void test5(int totalConnections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.listen((_) {}, onDone: () {
+        request.response.close();
+        request.response.done.catchError((e) {});
+      }, onError: (error) {});
+    }, onError: (error) {});
+
+    // Create a number of client requests and keep then active. Then
+    // close the client and wait for the server to lose all active
+    // connections.
+    var client = new HttpClient();
+    client.maxConnectionsPerHost = totalConnections;
+    for (int i = 0; i < totalConnections; i++) {
+      client
+          .post("127.0.0.1", server.port, "/")
+          .then((request) {
+            request.add([0]);
+            // TODO(sgjesse): Make this test work with
+            //request.response instead of request.close() return
+            //return request.response;
+            request.done.catchError((e) {});
+            return request.close();
+          })
+          .then((response) {})
+          .catchError((e) {},
+              test: (e) => e is HttpException || e is SocketException);
+    }
+    bool clientClosed = false;
+    new Timer.periodic(new Duration(milliseconds: 100), (timer) {
+      if (!clientClosed) {
+        if (server.connectionsInfo().total == totalConnections) {
+          clientClosed = true;
+          client.close(force: true);
+        }
+      } else {
+        if (server.connectionsInfo().total == 0) {
+          server.close();
+          timer.cancel();
+        }
+      }
+    });
+  });
+}
+
+void main() {
+  test1(1);
+  test1(10);
+  test2(1, 10);
+  test2(10, 10);
+  test2(10, 1000);
+  test3(1);
+  test3(10);
+  test4();
+  test5(1);
+  test5(10);
+}
diff --git a/tests/standalone/io/http_stream_close_test.dart b/tests/standalone/io/http_stream_close_test.dart
new file mode 100644
index 0000000..06b9572
--- /dev/null
+++ b/tests/standalone/io/http_stream_close_test.dart
@@ -0,0 +1,51 @@
+// 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:io";
+
+main() {
+  bool serverOnClosed = false;
+  bool clientOnClosed = false;
+  bool requestOnClosed = false;
+
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    var client = new HttpClient();
+
+    checkDone() {
+      if (serverOnClosed && clientOnClosed && requestOnClosed) {
+        server.close();
+        client.close();
+      }
+    }
+
+    server.listen((request) {
+      request.listen((_) {}, onDone: () {
+        request.response.done.then((_) {
+          serverOnClosed = true;
+          checkDone();
+        });
+        request.response.write("hello!");
+        request.response.close();
+      });
+    });
+
+    client
+        .postUrl(Uri.parse("http://127.0.0.1:${server.port}"))
+        .then((request) {
+      request.contentLength = "hello!".length;
+      request.done.then((_) {
+        clientOnClosed = true;
+        checkDone();
+      });
+      request.write("hello!");
+      return request.close();
+    }).then((response) {
+      response.listen((_) {}, onDone: () {
+        requestOnClosed = true;
+        checkDone();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/https_bad_certificate_test.dart b/tests/standalone/io/https_bad_certificate_test.dart
new file mode 100644
index 0000000..96b0144
--- /dev/null
+++ b/tests/standalone/io/https_bad_certificate_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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+// This test verifies that the bad certificate callback works in HttpClient.
+
+import "dart:async";
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+final HOST_NAME = 'localhost';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+class CustomException {}
+
+main() async {
+  var HOST = (await InternetAddress.lookup(HOST_NAME)).first;
+  var server = await HttpServer.bindSecure(HOST, 0, serverContext, backlog: 5);
+  server.listen((request) {
+    request.listen((_) {}, onDone: () {
+      request.response.close();
+    });
+  });
+
+  SecurityContext goodContext = new SecurityContext()
+    ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+  SecurityContext badContext = new SecurityContext();
+  SecurityContext defaultContext = SecurityContext.defaultContext;
+
+  await runClient(server.port, goodContext, true, 'pass');
+  await runClient(server.port, goodContext, false, 'pass');
+  await runClient(server.port, goodContext, 'fisk', 'pass');
+  await runClient(server.port, goodContext, 'exception', 'pass');
+  await runClient(server.port, badContext, true, 'pass');
+  await runClient(server.port, badContext, false, 'fail');
+  await runClient(server.port, badContext, 'fisk', 'fail');
+  await runClient(server.port, badContext, 'exception', 'throw');
+  await runClient(server.port, defaultContext, true, 'pass');
+  await runClient(server.port, defaultContext, false, 'fail');
+  await runClient(server.port, defaultContext, 'fisk', 'fail');
+  await runClient(server.port, defaultContext, 'exception', 'throw');
+  server.close();
+}
+
+Future runClient(
+    int port, SecurityContext context, callbackReturns, result) async {
+  HttpClient client = new HttpClient(context: context);
+  client.badCertificateCallback = (X509Certificate certificate, host, port) {
+    Expect.isTrue(certificate.subject.contains('rootauthority'));
+    Expect.isTrue(certificate.issuer.contains('rootauthority'));
+    // Throw exception if one is requested.
+    if (callbackReturns == 'exception') throw new CustomException();
+    return callbackReturns;
+  };
+
+  try {
+    var request = await client.getUrl(Uri.parse('https://$HOST_NAME:$port/'));
+    Expect.equals('pass', result);
+    await request.close();
+  } catch (error) {
+    Expect.notEquals(result, 'pass');
+    if (result == 'fail') {
+      Expect.isTrue(error is HandshakeException ||
+          (callbackReturns is! bool && error is TypeError));
+    } else if (result == 'throw') {
+      Expect.isTrue(error is CustomException);
+    } else {
+      Expect.fail('Unknown expectation $result');
+    }
+  }
+}
diff --git a/tests/standalone/io/https_client_certificate_test.dart b/tests/standalone/io/https_client_certificate_test.dart
new file mode 100644
index 0000000..07ed5bf
--- /dev/null
+++ b/tests/standalone/io/https_client_certificate_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+const HOST_NAME = "localhost";
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+// TODO: Specify which client certificate roots to trust.
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'))
+// TODO: Set a client certificate here.
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+void main() {
+  asyncStart();
+  HttpServer.bindSecure(HOST_NAME, 0, serverContext,
+          backlog: 5, requestClientCertificate: true)
+      .then((server) {
+    server.listen((HttpRequest request) {
+      Expect.isNotNull(request.certificate);
+      Expect.equals('CN=localhost', request.certificate!.subject);
+      request.response.write("Hello");
+      request.response.close();
+    });
+
+    HttpClient client = new HttpClient(context: clientContext);
+    client
+        .getUrl(Uri.parse("https://$HOST_NAME:${server.port}/"))
+        .then((request) => request.close())
+        .then((response) {
+      Expect.equals('CN=localhost', response.certificate!.subject);
+      Expect.equals('CN=myauthority', response.certificate!.issuer);
+      return response
+          .fold<List<int>>(<int>[], (message, data) => message..addAll(data));
+    }).then((message) {
+      String received = new String.fromCharCodes(message);
+      Expect.equals(received, "Hello");
+      client.close();
+      server.close();
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/https_client_exception_test.dart b/tests/standalone/io/https_client_exception_test.dart
new file mode 100644
index 0000000..6735909
--- /dev/null
+++ b/tests/standalone/io/https_client_exception_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.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testBadHostName() {
+  asyncStart();
+  HttpClient client = new HttpClient();
+  client
+      .getUrl(Uri.parse("https://some.bad.host.name.7654321/"))
+      .then((HttpClientRequest request) {
+    Expect.fail("Should not open a request on bad hostname");
+  }).catchError((error) {
+    asyncEnd(); // Should throw an error on bad hostname.
+  });
+}
+
+void main() {
+  testBadHostName();
+}
diff --git a/tests/standalone/io/https_server_test.dart b/tests/standalone/io/https_server_test.dart
new file mode 100644
index 0000000..6c46d92
--- /dev/null
+++ b/tests/standalone/io/https_server_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.
+//
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testListenOn() {
+  void test(void onDone()) {
+    HttpServer.bindSecure(HOST, 0, serverContext, backlog: 5).then((server) {
+      ReceivePort serverPort = new ReceivePort();
+      server.listen((HttpRequest request) {
+        request.listen((_) {}, onDone: () {
+          request.response.close();
+          serverPort.close();
+        });
+      });
+
+      HttpClient client = new HttpClient(context: clientContext);
+      ReceivePort clientPort = new ReceivePort();
+      client
+          .getUrl(Uri.parse("https://${HOST.host}:${server.port}/"))
+          .then((HttpClientRequest request) {
+        return request.close();
+      }).then((HttpClientResponse response) {
+        response.listen((_) {}, onDone: () {
+          client.close();
+          clientPort.close();
+          server.close();
+          Expect.throws(() => server.port);
+          onDone();
+        });
+      }).catchError((e, trace) {
+        String msg = "Unexpected error in Https client: $e";
+        if (trace != null) msg += "\nStackTrace: $trace";
+        Expect.fail(msg);
+      });
+    });
+  }
+
+  // Test two servers in succession.
+  test(() {
+    test(() {});
+  });
+}
+
+void testEarlyClientClose() {
+  HttpServer.bindSecure(HOST, 0, serverContext).then((server) {
+    server.listen((request) {
+      String name = Platform.script.toFilePath();
+      new File(name)
+          .openRead()
+          .cast<List<int>>()
+          .pipe(request.response)
+          .catchError((e) {/* ignore */});
+    });
+
+    var count = 0;
+    makeRequest() {
+      Socket.connect(HOST, server.port).then((socket) {
+        var data = "Invalid TLS handshake";
+        socket.write(data);
+        socket.close();
+        socket.done.then((_) {
+          socket.destroy();
+          if (++count < 10) {
+            makeRequest();
+          } else {
+            server.close();
+          }
+        });
+      });
+    }
+
+    makeRequest();
+  });
+}
+
+void main() {
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    testListenOn();
+    testEarlyClientClose();
+  });
+}
diff --git a/tests/standalone/io/https_unauthorized_client.dart b/tests/standalone/io/https_unauthorized_client.dart
new file mode 100644
index 0000000..6b7e8f6
--- /dev/null
+++ b/tests/standalone/io/https_unauthorized_client.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.
+
+// Client that makes HttpClient secure gets from a server that replies with
+// a certificate that can't be authenticated.  This checks that all the
+// futures returned from these connection attempts complete (with errors).
+
+import "dart:async";
+import "dart:io";
+
+class ExpectException implements Exception {
+  ExpectException(this.message);
+  String toString() => "ExpectException: $message";
+  String message;
+}
+
+void expect(condition, message) {
+  if (!condition) {
+    throw new ExpectException(message);
+  }
+}
+
+const HOST_NAME = "localhost";
+
+Future runClients(int port) {
+  HttpClient client = new HttpClient();
+
+  var testFutures = <Future>[];
+  for (int i = 0; i < 20; ++i) {
+    testFutures.add(client.getUrl(Uri.parse('https://$HOST_NAME:$port/')).then(
+        (HttpClientRequest request) {
+      expect(false, "Request succeeded");
+    }, onError: (e) {
+      // Remove ArgumentError once null default context is supported.
+      expect(
+          e is HandshakeException || e is SocketException || e is ArgumentError,
+          "Error is wrong type: $e");
+    }));
+  }
+  return Future.wait(testFutures);
+}
+
+void main(List<String> args) {
+  runClients(int.parse(args[0])).then((_) => print('SUCCESS'));
+}
diff --git a/tests/standalone/io/https_unauthorized_test.dart b/tests/standalone/io/https_unauthorized_test.dart
new file mode 100644
index 0000000..ea172be
--- /dev/null
+++ b/tests/standalone/io/https_unauthorized_test.dart
@@ -0,0 +1,72 @@
+// 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.
+//
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/untrusted_server_chain.pem
+// OtherResources=certificates/untrusted_server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=https_unauthorized_client.dart
+
+// This test verifies that secure connections that fail due to
+// unauthenticated certificates throw exceptions in HttpClient.
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "dart:async";
+import "dart:io";
+
+const HOST_NAME = "localhost";
+const CERTIFICATE = "localhost_cert";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext untrustedServerContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/untrusted_server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/untrusted_server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+Future<HttpServer> runServer() {
+  return HttpServer.bindSecure(HOST_NAME, 0, untrustedServerContext, backlog: 5)
+      .then((server) {
+    server.listen((HttpRequest request) {
+      request.listen((_) {}, onDone: () {
+        request.response.close();
+      });
+    }, onError: (e) {
+      if (e is! HandshakeException) throw e;
+    });
+    return server;
+  });
+}
+
+void main() {
+  var clientScript = localFile('https_unauthorized_client.dart');
+  Future clientProcess(int port) {
+    return Process.run(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..addAll([clientScript, port.toString()]))
+        .then((ProcessResult result) {
+      if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
+        print("Client failed");
+        print("  stdout:");
+        print(result.stdout);
+        print("  stderr:");
+        print(result.stderr);
+        Expect.fail('Client subprocess exit code: ${result.exitCode}');
+      }
+    });
+  }
+
+  runServer().then((server) {
+    clientProcess(server.port).then((_) {
+      server.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/internet_address_test.dart b/tests/standalone/io/internet_address_test.dart
new file mode 100644
index 0000000..1832207
--- /dev/null
+++ b/tests/standalone/io/internet_address_test.dart
@@ -0,0 +1,140 @@
+// 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:io';
+
+import "package:expect/expect.dart";
+
+void testDefaultAddresses() {
+  var loopback4 = InternetAddress.loopbackIPv4;
+  Expect.isNotNull(loopback4);
+  Expect.equals(InternetAddressType.IPv4, loopback4.type);
+  Expect.equals("127.0.0.1", loopback4.host);
+  Expect.equals("127.0.0.1", loopback4.address);
+  Expect.listEquals([127, 0, 0, 1], loopback4.rawAddress);
+
+  var loopback6 = InternetAddress.loopbackIPv6;
+  Expect.isNotNull(loopback6);
+  Expect.equals(InternetAddressType.IPv6, loopback6.type);
+  Expect.equals("::1", loopback6.host);
+  Expect.equals("::1", loopback6.address);
+  Expect.listEquals(
+      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback6.rawAddress);
+
+  var any4 = InternetAddress.anyIPv4;
+  Expect.isNotNull(any4);
+  Expect.equals(InternetAddressType.IPv4, any4.type);
+  Expect.equals("0.0.0.0", any4.host);
+  Expect.equals("0.0.0.0", any4.address);
+
+  var any6 = InternetAddress.anyIPv6;
+  Expect.isNotNull(any6);
+  Expect.equals(InternetAddressType.IPv6, any6.type);
+  Expect.equals("::", any6.host);
+  Expect.equals("::", any6.address);
+}
+
+void testConstructor() {
+  var loopback4 = new InternetAddress("127.0.0.1");
+  Expect.equals(InternetAddressType.IPv4, loopback4.type);
+  Expect.equals("127.0.0.1", loopback4.host);
+  Expect.equals("127.0.0.1", loopback4.address);
+  Expect.isFalse(loopback4.isMulticast);
+
+  var loopback6 = new InternetAddress("::1");
+  Expect.equals(InternetAddressType.IPv6, loopback6.type);
+  Expect.equals("::1", loopback6.host);
+  Expect.equals("::1", loopback6.address);
+  Expect.isFalse(loopback6.isMulticast);
+
+  var ip4 = new InternetAddress("10.20.30.40");
+  Expect.equals(InternetAddressType.IPv4, ip4.type);
+  Expect.equals("10.20.30.40", ip4.host);
+  Expect.equals("10.20.30.40", ip4.address);
+  Expect.isFalse(ip4.isMulticast);
+
+  var ip6 = new InternetAddress("10:20::30:40");
+  Expect.equals(InternetAddressType.IPv6, ip6.type);
+  Expect.equals("10:20::30:40", ip6.host);
+  Expect.equals("10:20::30:40", ip6.address);
+  Expect.isFalse(ip6.isMulticast);
+
+  var multicast4 = new InternetAddress("224.1.2.3");
+  Expect.equals(InternetAddressType.IPv4, multicast4.type);
+  Expect.isTrue(multicast4.isMulticast);
+
+  var multicast6 = new InternetAddress("FF00::1:2:3");
+  Expect.equals(InternetAddressType.IPv6, multicast6.type);
+  Expect.isTrue(multicast6.isMulticast);
+
+  Expect.throwsArgumentError(() => new InternetAddress("1.2.3"));
+  Expect.throwsArgumentError(() => new InternetAddress("::FFFF::1"));
+}
+
+void testEquality() {
+  Expect.equals(
+      new InternetAddress("127.0.0.1"), new InternetAddress("127.0.0.1"));
+  Expect.equals(new InternetAddress("127.0.0.1"), InternetAddress.loopbackIPv4);
+  Expect.equals(new InternetAddress("::1"), new InternetAddress("::1"));
+  Expect.equals(new InternetAddress("::1"), InternetAddress.loopbackIPv6);
+  Expect.equals(new InternetAddress("1:2:3:4:5:6:7:8"),
+      new InternetAddress("1:2:3:4:5:6:7:8"));
+  Expect.equals(
+      new InternetAddress("1::2"), new InternetAddress("1:0:0:0:0:0:0:2"));
+  Expect.equals(new InternetAddress("::FFFF:0:0:16.32.48.64"),
+      new InternetAddress("::FFFF:0:0:1020:3040"));
+
+  var set = new Set();
+  set.add(new InternetAddress("127.0.0.1"));
+  set.add(new InternetAddress("::1"));
+  set.add(new InternetAddress("1:2:3:4:5:6:7:8"));
+  Expect.isTrue(set.contains(new InternetAddress("127.0.0.1")));
+  Expect.isTrue(set.contains(InternetAddress.loopbackIPv4));
+  Expect.isFalse(set.contains(new InternetAddress("127.0.0.2")));
+  Expect.isTrue(set.contains(new InternetAddress("::1")));
+  Expect.isTrue(set.contains(InternetAddress.loopbackIPv6));
+  Expect.isFalse(set.contains(new InternetAddress("::2")));
+  Expect.isTrue(set.contains(new InternetAddress("1:2:3:4:5:6:7:8")));
+  Expect.isFalse(set.contains(new InternetAddress("1:2:3:4:5:6:7:9")));
+  Expect.isFalse(set.contains(new InternetAddress("0:2:3:4:5:6:7:8")));
+}
+
+void testLookup() {
+  InternetAddress.lookup("127.0.0.1").then((addresses) {
+    Expect.equals(1, addresses.length);
+    Expect.equals("127.0.0.1", addresses[0].address);
+  });
+
+  InternetAddress.lookup("::1").then((addresses) {
+    Expect.equals(1, addresses.length);
+    Expect.equals("::1", addresses[0].address);
+  });
+}
+
+void testReverseLookup() {
+  InternetAddress.lookup('localhost').then((addrs) {
+    addrs.first.reverse().then((addr) {
+      Expect.isNotNull(addr.host);
+      Expect.isNotNull(addr.rawAddress);
+    });
+  });
+
+  InternetAddress.lookup('127.0.0.1').then((addrs) {
+    Expect.equals('127.0.0.1', addrs.first.host);
+    Expect.listEquals([127, 0, 0, 1], addrs.first.rawAddress);
+    addrs.first.reverse().then((addr) {
+      Expect.isNotNull(addr.host);
+      Expect.notEquals('127.0.0.1', addr.host);
+      Expect.listEquals([127, 0, 0, 1], addr.rawAddress);
+    });
+  });
+}
+
+void main() {
+  testDefaultAddresses();
+  testConstructor();
+  testEquality();
+  testLookup();
+  testReverseLookup();
+}
diff --git a/tests/standalone/io/io_override_test.dart b/tests/standalone/io/io_override_test.dart
new file mode 100644
index 0000000..aafa0ff
--- /dev/null
+++ b/tests/standalone/io/io_override_test.dart
@@ -0,0 +1,249 @@
+// 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:typed_data';
+
+import "package:expect/expect.dart";
+
+class DirectoryMock extends FileSystemEntity implements Directory {
+  final String path = "/mockdir";
+
+  DirectoryMock(String path);
+
+  static DirectoryMock createDirectory(String path) => new DirectoryMock(path);
+  static DirectoryMock getCurrent() => new DirectoryMock("");
+  static void setCurrent(String path) {}
+  static DirectoryMock getSystemTemp() => new DirectoryMock("");
+
+  Uri get uri => throw "";
+  Future<Directory> create({bool recursive: false}) => throw "";
+  void createSync({bool recursive: false}) {}
+  Future<Directory> createTemp([String? prefix]) => throw "";
+  Directory createTempSync([String? prefix]) => throw "";
+  Future<bool> exists() => throw "";
+  bool existsSync() => false;
+  Future<String> resolveSymbolicLinks() => throw "";
+  String resolveSymbolicLinksSync() => throw "";
+  Future<Directory> rename(String newPath) => throw "";
+  Directory renameSync(String newPath) => throw "";
+  Directory get absolute => throw "";
+  Stream<FileSystemEntity> list(
+          {bool recursive: false, bool followLinks: true}) =>
+      throw "";
+  List<FileSystemEntity> listSync(
+          {bool recursive: false, bool followLinks: true}) =>
+      throw "";
+}
+
+class FileMock extends FileSystemEntity implements File {
+  String get path => "/mockfile";
+
+  FileMock(String path);
+
+  static FileMock createFile(String path) => new FileMock(path);
+
+  Future<File> create({bool recursive: false}) => throw "";
+  void createSync({bool recursive: false}) {}
+  Future<File> rename(String newPath) => throw "";
+  File renameSync(String newPath) => throw "";
+  Future<File> copy(String newPath) => throw "";
+  File copySync(String newPath) => throw "";
+  Future<bool> exists() => throw "";
+  bool existsSync() => false;
+  Future<int> length() => throw "";
+  int lengthSync() => throw "";
+  File get absolute => throw "";
+  Future<DateTime> lastAccessed() => throw "";
+  DateTime lastAccessedSync() => throw "";
+  Future setLastAccessed(DateTime time) => throw "";
+  void setLastAccessedSync(DateTime time) {}
+  Future<DateTime> lastModified() => throw "";
+  DateTime lastModifiedSync() => throw "";
+  Future setLastModified(DateTime time) => throw "";
+  void setLastModifiedSync(DateTime time) {}
+  Future<RandomAccessFile> open({FileMode mode: FileMode.read}) => throw "";
+  RandomAccessFile openSync({FileMode mode: FileMode.read}) => throw "";
+  Stream<List<int>> openRead([int? start, int? end]) => throw "";
+  IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) =>
+      throw "";
+  Future<Uint8List> readAsBytes() => throw "";
+  Uint8List readAsBytesSync() => throw "";
+  Future<String> readAsString({Encoding encoding: utf8}) => throw "";
+  String readAsStringSync({Encoding encoding: utf8}) => throw "";
+  Future<List<String>> readAsLines({Encoding encoding: utf8}) => throw "";
+  List<String> readAsLinesSync({Encoding encoding: utf8}) => throw "";
+  Future<File> writeAsBytes(List<int> bytes,
+          {FileMode mode: FileMode.write, bool flush: false}) =>
+      throw "";
+  void writeAsBytesSync(List<int> bytes,
+      {FileMode mode: FileMode.write, bool flush: false}) {}
+  Future<File> writeAsString(String contents,
+          {FileMode mode: FileMode.write,
+          Encoding encoding: utf8,
+          bool flush: false}) =>
+      throw "";
+  void writeAsStringSync(String contents,
+      {FileMode mode: FileMode.write,
+      Encoding encoding: utf8,
+      bool flush: false}) {}
+}
+
+class FileStatMock implements FileStat {
+  final changed = new DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
+  final modified = new DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
+  final accessed = new DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
+  final type = FileSystemEntityType.file;
+  final int mode = 0;
+  final int size = 0;
+
+  FileStatMock();
+
+  static Future<FileStat> stat(String path) {
+    return new Future.value(new FileStatMock());
+  }
+
+  static FileStat statSync(String path) => new FileStatMock();
+
+  String modeString() => throw "";
+}
+
+class FileSystemEntityMock {
+  static Future<bool> identical(String path1, String path2) {
+    return new Future.value(false);
+  }
+
+  static bool identicalSync(String path1, String path2) => false;
+
+  static Future<FileSystemEntityType> getType(String path, bool followLinks) {
+    return new Future.value(FileSystemEntityType.file);
+  }
+
+  static FileSystemEntityType getTypeSync(String path, bool followLinks) {
+    return FileSystemEntityType.file;
+  }
+}
+
+class FileSystemWatcherMock {
+  static Stream<FileSystemEvent> watch(
+      String path, int events, bool recursive) async* {}
+
+  static bool watchSupported() => false;
+}
+
+class LinkMock extends FileSystemEntity implements Link {
+  String get path => "/mocklink";
+
+  LinkMock(String path);
+
+  static Link createLink(String path) => new LinkMock(path);
+
+  Future<Link> create(String target, {bool recursive: false}) => throw "";
+  void createSync(String target, {bool recursive: false}) {}
+  void updateSync(String target) {}
+  Future<Link> update(String target) => throw "";
+  Future<bool> exists() => throw "";
+  bool existsSync() => false;
+  Future<String> resolveSymbolicLinks() => throw "";
+  String resolveSymbolicLinksSync() => throw "";
+  Future<Link> rename(String newPath) => throw "";
+  Link renameSync(String newPath) => throw "";
+  Link get absolute => throw "";
+  Future<String> target() => throw "";
+  String targetSync() => throw "";
+}
+
+Future<Socket> socketConnect(dynamic host, int port,
+    {dynamic sourceAddress, Duration? timeout}) {
+  throw "";
+}
+
+Future<ConnectionTask<Socket>> socketStartConnect(dynamic host, int port,
+    {dynamic sourceAddress}) {
+  throw "";
+}
+
+Future<ServerSocket> serverSocketBind(dynamic address, int port,
+    {int backlog: 0, bool v6Only: false, bool shared: false}) {
+  throw "";
+}
+
+Future<Null> ioOverridesRunTest() async {
+  Future<Null> f = IOOverrides.runZoned(
+    () async {
+      Expect.isTrue(new Directory("directory") is DirectoryMock);
+      Expect.isTrue(Directory.current is DirectoryMock);
+      Expect.isTrue(Directory.systemTemp is DirectoryMock);
+      Expect.isTrue(new File("file") is FileMock);
+      Expect.isTrue(await FileStat.stat("file") is FileStatMock);
+      Expect.isTrue(FileStat.statSync("file") is FileStatMock);
+      Expect.isFalse(await FileSystemEntity.identical("file", "file"));
+      Expect.isFalse(FileSystemEntity.identicalSync("file", "file"));
+      Expect.equals(
+          await FileSystemEntity.type("file"), FileSystemEntityType.file);
+      Expect.equals(
+          FileSystemEntity.typeSync("file"), FileSystemEntityType.file);
+      Expect.isFalse(FileSystemEntity.isWatchSupported);
+      Expect.isNull(new Directory("directory").watch());
+      Expect.isTrue(new Link("link") is LinkMock);
+      Expect.isNull(Socket.connect(null, 0));
+      Expect.isNull(Socket.startConnect(null, 0));
+      Expect.isNull(ServerSocket.bind(null, 0));
+    },
+    createDirectory: DirectoryMock.createDirectory,
+    getCurrentDirectory: DirectoryMock.getCurrent,
+    setCurrentDirectory: DirectoryMock.setCurrent,
+    getSystemTempDirectory: DirectoryMock.getSystemTemp,
+    createFile: FileMock.createFile,
+    stat: FileStatMock.stat,
+    statSync: FileStatMock.statSync,
+    fseIdentical: FileSystemEntityMock.identical,
+    fseIdenticalSync: FileSystemEntityMock.identicalSync,
+    fseGetType: FileSystemEntityMock.getType,
+    fseGetTypeSync: FileSystemEntityMock.getTypeSync,
+    fsWatch: FileSystemWatcherMock.watch,
+    fsWatchIsSupported: FileSystemWatcherMock.watchSupported,
+    createLink: LinkMock.createLink,
+    socketConnect: socketConnect,
+    socketStartConnect: socketStartConnect,
+    serverSocketBind: serverSocketBind,
+  );
+  Expect.isFalse(new Directory("directory") is DirectoryMock);
+  Expect.isTrue(new Directory("directory") is Directory);
+  await f;
+}
+
+class MyIOOverrides extends IOOverrides {
+  Directory createDirectory(String path) => DirectoryMock.createDirectory(path);
+}
+
+globalIOOverridesTest() {
+  IOOverrides.global = new MyIOOverrides();
+  Expect.isTrue(new Directory("directory") is DirectoryMock);
+  IOOverrides.global = null;
+  Directory dir = new Directory("directory");
+  Expect.isTrue(dir is! DirectoryMock);
+  Expect.isTrue(dir is Directory);
+}
+
+globalIOOverridesZoneTest() {
+  IOOverrides.global = new MyIOOverrides();
+  runZoned(() {
+    runZoned(() {
+      Expect.isTrue(new Directory("directory") is DirectoryMock);
+    });
+  });
+  IOOverrides.global = null;
+  Directory dir = new Directory("directory");
+  Expect.isTrue(dir is! DirectoryMock);
+  Expect.isTrue(dir is Directory);
+}
+
+main() async {
+  await ioOverridesRunTest();
+  globalIOOverridesTest();
+  globalIOOverridesZoneTest();
+}
diff --git a/tests/standalone/io/io_sink_test.dart b/tests/standalone/io/io_sink_test.dart
new file mode 100644
index 0000000..daeb997
--- /dev/null
+++ b/tests/standalone/io/io_sink_test.dart
@@ -0,0 +1,122 @@
+// 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:io";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+class TestConsumer implements StreamConsumer<List<int>> {
+  final List expected;
+  final List received = [];
+
+  int addStreamCount = 0;
+  int expcetedAddStreamCount;
+  bool expectClose;
+
+  TestConsumer(this.expected,
+      {this.expectClose: true, this.expcetedAddStreamCount: -1}) {
+    if (expectClose) asyncStart();
+  }
+
+  Future addStream(Stream stream) {
+    addStreamCount++;
+    var sub = stream.listen((v) {
+      received.addAll(v);
+    });
+    sub.pause();
+    scheduleMicrotask(sub.resume);
+    return sub.asFuture();
+  }
+
+  void matches(List list) {
+    Expect.listEquals(list, received);
+  }
+
+  Future close() {
+    return new Future.value().then((_) {
+      if (expectClose) asyncEnd();
+      Expect.listEquals(expected, received);
+      if (expcetedAddStreamCount >= 0) {
+        Expect.equals(expcetedAddStreamCount, addStreamCount);
+      }
+    });
+  }
+}
+
+void testClose() {
+  var sink = new IOSink(new TestConsumer([], expcetedAddStreamCount: 0));
+  sink.close();
+}
+
+void testAddClose() {
+  var sink = new IOSink(new TestConsumer([0]));
+  sink.add([0]);
+  sink.close();
+
+  sink = new IOSink(new TestConsumer([0, 1, 2]));
+  sink.add([0]);
+  sink.add([1]);
+  sink.add([2]);
+  sink.close();
+}
+
+void testAddFlush() {
+  var consumer = new TestConsumer([0, 1, 2]);
+  var sink = new IOSink(consumer);
+  sink.add([0]);
+  sink.flush().then((s) {
+    consumer.matches([0]);
+    s.add([1]);
+    s.add([2]);
+    s.flush().then((s) {
+      consumer.matches([0, 1, 2]);
+      s.close();
+    });
+  });
+}
+
+void testAddStreamClose() {
+  {
+    var sink = new IOSink(new TestConsumer([0]));
+    var controller = new StreamController<List<int>>(sync: true);
+    sink.addStream(controller.stream).then((_) {
+      sink.close();
+    });
+    controller.add([0]);
+    controller.close();
+  }
+  {
+    var sink = new IOSink(new TestConsumer([0, 1, 2]));
+    var controller = new StreamController<List<int>>(sync: true);
+    sink.addStream(controller.stream).then((_) {
+      sink.close();
+    });
+    controller.add([0]);
+    controller.add([1]);
+    controller.add([2]);
+    controller.close();
+  }
+}
+
+void testAddStreamAddClose() {
+  {
+    var sink = new IOSink(new TestConsumer([0, 1]));
+    var controller = new StreamController<List<int>>(sync: true);
+    sink.addStream(controller.stream).then((_) {
+      sink.add([1]);
+      sink.close();
+    });
+    controller.add([0]);
+    controller.close();
+  }
+}
+
+void main() {
+  testClose();
+  testAddClose();
+  testAddFlush();
+  testAddStreamClose();
+  testAddStreamAddClose();
+}
diff --git a/tests/standalone/io/issue_22636_test.dart b/tests/standalone/io/issue_22636_test.dart
new file mode 100644
index 0000000..85ed32d
--- /dev/null
+++ b/tests/standalone/io/issue_22636_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This test checks that setting writeEventsEnabled on a socket that is
+// closed for read (the other end has closed for write) does not send
+// an additional READ_CLOSED event.
+
+import "dart:async";
+import "dart:io";
+import "package:expect/expect.dart";
+
+final Duration delay = new Duration(milliseconds: 100);
+final List<int> data = new List.generate(100, (i) => i % 20 + 65);
+late RawServerSocket server;
+late RawSocket client;
+bool serverReadClosedReceived = false;
+bool serverFirstWrite = true;
+
+void serverListen(RawSocket serverSide) {
+  void serveData(RawSocketEvent event) {
+    switch (event) {
+      case RawSocketEvent.write:
+        serverSide.write(data);
+        if (serverFirstWrite) {
+          serverFirstWrite = false;
+          new Future.delayed(delay, () {
+            serverSide.writeEventsEnabled = true;
+          });
+        } else {
+          new Future.delayed(delay, () {
+            Expect.isTrue(serverReadClosedReceived);
+            serverSide.shutdown(SocketDirection.send);
+            server.close();
+          });
+        }
+        break;
+      case RawSocketEvent.readClosed:
+        Expect.isFalse(serverReadClosedReceived);
+        serverReadClosedReceived = true;
+        break;
+    }
+  }
+
+  serverSide.listen(serveData);
+}
+
+test() async {
+  server = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  server.listen(serverListen);
+  client = await RawSocket.connect(InternetAddress.loopbackIPv4, server.port);
+  client.shutdown(SocketDirection.send);
+  client.listen((RawSocketEvent event) {
+    if (event == RawSocketEvent.read) {
+      client.read();
+    }
+  });
+}
+
+void main() {
+  test();
+}
diff --git a/tests/standalone/io/issue_22637_test.dart b/tests/standalone/io/issue_22637_test.dart
new file mode 100644
index 0000000..82f8ab2
--- /dev/null
+++ b/tests/standalone/io/issue_22637_test.dart
@@ -0,0 +1,66 @@
+// 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 test checks that a shutdown(SocketDirection.send) of a socket,
+// when the other end is already closed, does not discard unread data
+// that remains in the connection.
+
+import "dart:io";
+import "dart:async";
+import "package:expect/expect.dart";
+
+late RawServerSocket server;
+late RawSocket client;
+Duration delay = new Duration(milliseconds: 100);
+
+void serverListen(RawSocket serverSide) {
+  var data = new List.generate(200, (i) => i % 20 + 65);
+  var offset = 0;
+  void serveData(RawSocketEvent event) {
+    if (event == RawSocketEvent.write) {
+      while (offset < data.length) {
+        var written = serverSide.write(data, offset);
+        offset += written;
+        if (written == 0) {
+          serverSide.writeEventsEnabled = true;
+          return;
+        }
+      }
+      serverSide.close();
+      server.close();
+    }
+  }
+
+  serverSide.listen(serveData);
+}
+
+void clientListen(RawSocketEvent event) {
+  if (event == RawSocketEvent.read) {
+    client.readEventsEnabled = false;
+    new Future.delayed(delay, () {
+      var data = client.read(100);
+      if (data == null) {
+        // If there is no data ready to read, wait until there is data
+        // that can be read, before running the rest of the test.
+        client.readEventsEnabled = true;
+        return;
+      }
+      client.shutdown(SocketDirection.send);
+      data = client.read(100);
+      Expect.isNotNull(data);
+      client.close();
+    });
+  }
+}
+
+test() async {
+  server = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  server.listen(serverListen);
+  client = await RawSocket.connect(InternetAddress.loopbackIPv4, server.port);
+  client.listen(clientListen);
+}
+
+void main() {
+  test();
+}
diff --git a/tests/standalone/io/issue_26954_test.dart b/tests/standalone/io/issue_26954_test.dart
new file mode 100644
index 0000000..f5fca78
--- /dev/null
+++ b/tests/standalone/io/issue_26954_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+final List<int> _UTF8_PLS_CERTIFICATE = utf8.encode('''
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
+oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
+1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
+PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
+BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
+B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
+phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
+YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
+UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
+2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
+PkLkXmoIod8=
+-----END CERTIFICATE-----''');
+
+main() {
+  // create context for establishing socket later
+  final _context = SecurityContext.defaultContext;
+  _context.useCertificateChainBytes(_UTF8_PLS_CERTIFICATE);
+}
diff --git a/tests/standalone/io/issue_30687_test.dart b/tests/standalone/io/issue_30687_test.dart
new file mode 100644
index 0000000..96b514d
--- /dev/null
+++ b/tests/standalone/io/issue_30687_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+
+main() async {
+  Link link1 = new Link(
+      Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
+  Link link2 = new Link(
+      Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+
+  Directory target1 = new Directory(
+      Directory.systemTemp.path + Platform.pathSeparator + 'target1');
+  Directory target2 = new Directory(
+      Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+
+  target1.createSync();
+  target2.createSync();
+
+  Expect.isTrue(target1.existsSync());
+  Expect.isTrue(target2.existsSync());
+
+  link1.createSync(target1.path);
+  link2.createSync(target2.path);
+  Expect.isTrue(link1.existsSync());
+  Expect.isTrue(link2.existsSync());
+
+  try {
+    Link renamed = await link1.rename(link2.path);
+    Expect.isFalse(link1.existsSync());
+    Expect.isTrue(renamed.existsSync());
+    Expect.equals(renamed.path, link2.path);
+  } finally {
+    target1.delete();
+    target2.delete();
+    link2.delete();
+    if (link1.existsSync()) {
+      link1.delete();
+    }
+  }
+}
diff --git a/tests/standalone/io/issue_31492_test.dart b/tests/standalone/io/issue_31492_test.dart
new file mode 100644
index 0000000..ed3c67e
--- /dev/null
+++ b/tests/standalone/io/issue_31492_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.
+
+// Testing that HttpClient throws an exception if a connection is opened after
+// the client is closed. https://github.com/dart-lang/sdk/issues/31492
+
+import "dart:io";
+import "package:expect/expect.dart";
+
+void main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.listen((_) {});
+    });
+    var client = new HttpClient();
+    client.close();
+    Expect.throws<StateError>(() => client.post("127.0.0.1", server.port, "/"));
+    server.close();
+  });
+}
diff --git a/tests/standalone/io/link_async_test.dart b/tests/standalone/io/link_async_test.dart
new file mode 100644
index 0000000..0b33f61
--- /dev/null
+++ b/tests/standalone/io/link_async_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.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+// Test the dart:io Link class.
+
+class FutureExpect {
+  static Future isTrue(Future<bool> result) =>
+      result.then((value) => Expect.isTrue(value));
+  static Future isFalse(Future<bool> result) =>
+      result.then((value) => Expect.isFalse(value));
+  static Future equals(expected, Future result) =>
+      result.then((value) => Expect.equals(expected, value));
+  static Future listEquals(expected, Future result) =>
+      result.then((value) => Expect.listEquals(expected, value));
+  static Future throws(Future result) => result.then((value) {
+        throw new ExpectException(
+            "FutureExpect.throws received $value instead of an exception");
+      }, onError: (_) => null);
+}
+
+Future testCreate() {
+  return Directory.systemTemp.createTemp('dart_link_async').then((baseDir) {
+    if (isRelative(baseDir.path)) {
+      Expect.fail(
+          'Link tests expect absolute paths to system temporary directories. '
+          'A relative path in TMPDIR gives relative paths to them.');
+    }
+    String base = baseDir.path;
+    String link = join(base, 'link');
+    String target = join(base, 'target');
+    return new Directory(target)
+        .create()
+        .then((_) => new Link(link).create(target))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(link)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(target)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(link, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+            FileSystemEntity.type(target, followLinks: false)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(link)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(target)))
+        .then((_) => FutureExpect.isTrue(new Directory(link).exists()))
+        .then((_) => FutureExpect.isTrue(new Directory(target).exists()))
+        .then((_) => FutureExpect.isTrue(new Link(link).exists()))
+        .then((_) => FutureExpect.isFalse(new Link(target).exists()))
+        .then((_) => FutureExpect.equals(target, new Link(link).target()))
+        .then((_) => FutureExpect.throws(new Link(target).target()))
+        .then((_) {
+      String createdThroughLink = join(base, 'link', 'createdThroughLink');
+      String createdDirectly = join(base, 'target', 'createdDirectly');
+      String createdFile = join(base, 'link', 'createdFile');
+      return new Directory(createdThroughLink)
+          .create()
+          .then((_) => new Directory(createdDirectly).create())
+          .then((_) => new File(createdFile).create())
+          .then((_) =>
+              FutureExpect.isTrue(new Directory(createdThroughLink).exists()))
+          .then((_) =>
+              FutureExpect.isTrue(new Directory(createdDirectly).exists()))
+          .then((_) => FutureExpect.isTrue(
+              new Directory(join(base, 'link', 'createdDirectly')).exists()))
+          .then((_) => FutureExpect.isTrue(
+              new Directory(join(base, 'target', 'createdThroughLink'))
+                  .exists()))
+          .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+              FileSystemEntity.type(createdThroughLink, followLinks: false)))
+          .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+              FileSystemEntity.type(createdDirectly, followLinks: false)))
+
+          // Test FileSystemEntity.identical on files, directories, and links,
+          // reached by different paths.
+          .then(
+              (_) => FutureExpect.isTrue(FileSystemEntity.identical(createdDirectly, createdDirectly)))
+          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(createdDirectly, createdThroughLink)))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdDirectly, join(base, 'link', 'createdDirectly'))))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdThroughLink, join(base, 'target', 'createdThroughLink'))))
+          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(target, link)))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(link, link)))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(target, target)))
+          .then((_) => new Link(link).target())
+          .then((linkTarget) => FutureExpect.isTrue(FileSystemEntity.identical(target, linkTarget)))
+          .then((_) => new File(".").resolveSymbolicLinks())
+          .then((fullCurrentDir) => FutureExpect.isTrue(FileSystemEntity.identical(".", fullCurrentDir)))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdFile, createdFile)))
+          .then((_) => FutureExpect.isFalse(FileSystemEntity.identical(createdFile, createdDirectly)))
+          .then((_) => FutureExpect.isTrue(FileSystemEntity.identical(createdFile, join(base, 'link', 'createdFile'))))
+          .then((_) => FutureExpect.throws(FileSystemEntity.identical(createdFile, join(base, 'link', 'does_not_exist'))))
+          .then((_) => testDirectoryListing(base, baseDir))
+          .then((_) => new Directory(target).delete(recursive: true))
+          .then((_) {
+        var futures = <Future>[];
+        for (bool recursive in [true, false]) {
+          for (bool followLinks in [true, false]) {
+            var result = baseDir.listSync(
+                recursive: recursive, followLinks: followLinks);
+            Expect.equals(1, result.length);
+            Expect.isTrue(result[0] is Link);
+            futures.add(FutureExpect.isTrue(baseDir
+                .list(recursive: recursive, followLinks: followLinks)
+                .single
+                .then((element) => element is Link)));
+          }
+        }
+        return Future.wait(futures);
+      }).then((_) => baseDir.delete(recursive: true));
+    });
+  });
+}
+
+Future testCreateLoopingLink(_) {
+  return Directory.systemTemp
+      .createTemp('dart_link_async')
+      .then((dir) => dir.path)
+      .then((String base) => new Directory(join(base, 'a', 'b', 'c'))
+          .create(recursive: true)
+          .then((_) => new Link(join(base, 'a', 'b', 'c', 'd'))
+              .create(join(base, 'a', 'b')))
+          .then((_) =>
+              new Link(join(base, 'a', 'b', 'c', 'e')).create(join(base, 'a')))
+          .then((_) => new Directory(join(base, 'a'))
+              .list(recursive: true, followLinks: false)
+              .last)
+          // This directory listing must terminate, even though it contains loops.
+          .then((_) => new Directory(join(base, 'a'))
+              .list(recursive: true, followLinks: true)
+              .last)
+          // This directory listing must terminate, even though it contains loops.
+          .then((_) => new Directory(join(base, 'a', 'b', 'c'))
+              .list(recursive: true, followLinks: true)
+              .last)
+          .then((_) => new Directory(base).delete(recursive: true))
+          .then((_) => FutureExpect.isFalse(new Directory(base).exists())));
+}
+
+Future testRename(_) {
+  Future testRename(String base, String target) {
+    late Link link1;
+    late Link link2;
+    return new Link(join(base, 'c')).create(target).then((link) {
+      link1 = link;
+      Expect.isTrue(link1.existsSync());
+      return link1.rename(join(base, 'd'));
+    }).then((link) {
+      link2 = link;
+      Expect.isFalse(link1.existsSync());
+      Expect.isTrue(link2.existsSync());
+      return link2.delete();
+    }).then((_) => Expect.isFalse(link2.existsSync()));
+  }
+
+  Future testUpdate(String base, String target1, String target2) {
+    late Link link1;
+    return new Link(join(base, 'c')).create(target1).then((link) {
+      link1 = link;
+      Expect.isTrue(link1.existsSync());
+      return link1.update(target2);
+    }).then((Link link) {
+      Expect.isTrue(link1.existsSync());
+      Expect.isTrue(link.existsSync());
+      return FutureExpect.equals(target2, link.target())
+          .then((_) => FutureExpect.equals(target2, link1.target()))
+          .then((_) => link.delete());
+    }).then((_) => Expect.isFalse(link1.existsSync()));
+  }
+
+  return Directory.systemTemp.createTemp('dart_link_async').then((baseDir) {
+    String base = baseDir.path;
+    var targetsFutures = <Future>[];
+    targetsFutures.add(new Directory(join(base, 'a')).create());
+    if (Platform.isWindows) {
+      // Currently only links to directories are supported on Windows.
+      targetsFutures.add(new Directory(join(base, 'b')).create());
+    } else {
+      targetsFutures.add(new File(join(base, 'b')).create());
+    }
+    return Future.wait(targetsFutures).then((targets) {
+      return testRename(base, targets[0].path)
+          .then((_) => testRename(base, targets[1].path))
+          .then((_) => testUpdate(base, targets[0].path, targets[1].path))
+          .then((_) => baseDir.delete(recursive: true));
+    });
+  });
+}
+
+Future testDirectoryListing(String base, Directory baseDir) {
+  Map makeExpected(bool recursive, bool followLinks) {
+    Map expected = new Map();
+    expected['target'] = 'Directory';
+    expected['link'] = followLinks ? 'Directory' : 'Link';
+    if (recursive) {
+      expected[join('target', 'createdDirectly')] = 'Directory';
+      expected[join('target', 'createdThroughLink')] = 'Directory';
+      expected[join('target', 'createdFile')] = 'File';
+      if (followLinks) {
+        expected[join('link', 'createdDirectly')] = 'Directory';
+        expected[join('link', 'createdThroughLink')] = 'Directory';
+        expected[join('link', 'createdFile')] = 'File';
+      }
+    }
+    return expected;
+  }
+
+  void checkEntity(FileSystemEntity x, Map expected) {
+    String ending = relative(x.path, from: base);
+    Expect.isNotNull(expected[ending]);
+    Expect.isTrue(x.toString().startsWith(expected[ending]));
+    expected[ending] = 'Found';
+  }
+
+  var futures = <Future>[];
+  for (bool recursive in [true, false]) {
+    for (bool followLinks in [true, false]) {
+      Map expected = makeExpected(recursive, followLinks);
+      for (var x
+          in baseDir.listSync(recursive: recursive, followLinks: followLinks)) {
+        checkEntity(x, expected);
+      }
+      for (var v in expected.values) {
+        Expect.equals('Found', v);
+      }
+      expected = makeExpected(recursive, followLinks);
+      futures.add(baseDir
+          .list(recursive: recursive, followLinks: followLinks)
+          .forEach((entity) => checkEntity(entity, expected))
+          .then((_) {
+        for (var v in expected.values) {
+          Expect.equals('Found', v);
+        }
+      }));
+    }
+  }
+  return Future.wait(futures);
+}
+
+Future checkExists(String filePath) =>
+    new File(filePath).exists().then(Expect.isTrue);
+
+Future testRelativeLinks(_) {
+  return Directory.systemTemp
+      .createTemp('dart_link_async')
+      .then((tempDirectory) {
+    String temp = tempDirectory.path;
+    String oldWorkingDirectory = Directory.current.path;
+    // Make directories and files to test links.
+    return new Directory(join(temp, 'dir1', 'dir2'))
+        .create(recursive: true)
+        .then((_) => new File(join(temp, 'dir1', 'file1')).create())
+        .then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
+        // Make links whose path and/or target is given by a relative path.
+        .then((_) => new Link(join(temp, 'dir1', 'link1_2')).create('dir2'))
+        .then((_) => Directory.current = temp)
+        .then((_) => new Link('link0_2').create(join('dir1', 'dir2')))
+        .then((_) => new Link(join('dir1', 'link1_0')).create('..'))
+        .then((_) => Directory.current = 'dir1')
+        .then((_) => new Link(join('..', 'link0_1')).create('dir1'))
+        .then(
+            (_) => new Link(join('dir2', 'link2_1')).create(join(temp, 'dir1')))
+        .then((_) => new Link(join(temp, 'dir1', 'dir2', 'link2_0'))
+            .create(join('..', '..')))
+        // Test that the links go to the right targets.
+        .then((_) => checkExists(join('..', 'link0_1', 'file1')))
+        .then((_) => checkExists(join('..', 'link0_2', 'file2')))
+        .then((_) => checkExists(join('link1_0', 'dir1', 'file1')))
+        .then((_) => checkExists(join('link1_2', 'file2')))
+        .then((_) => checkExists(join('dir2', 'link2_0', 'dir1', 'file1')))
+        .then((_) => checkExists(join('dir2', 'link2_1', 'file1')))
+        // Clean up
+        .whenComplete(() => Directory.current = oldWorkingDirectory)
+        .whenComplete(() => tempDirectory.delete(recursive: true));
+  });
+}
+
+main() {
+  asyncStart();
+  testCreate()
+      .then(testCreateLoopingLink)
+      .then(testRename)
+      .then(testRelativeLinks)
+      .then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/link_test.dart b/tests/standalone/io/link_test.dart
new file mode 100644
index 0000000..3e36111
--- /dev/null
+++ b/tests/standalone/io/link_test.dart
@@ -0,0 +1,324 @@
+// 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:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "dart:async";
+import "dart:io";
+
+// Test the dart:io Link class.
+
+testCreateSync() {
+  asyncStart();
+  String base = Directory.systemTemp.createTempSync('dart_link').path;
+  if (isRelative(base)) {
+    Expect.fail(
+        'Link tests expect absolute paths to system temporary directories. '
+        'A relative path in TMPDIR gives relative paths to them.');
+  }
+  String link = join(base, 'link');
+  String target = join(base, 'target');
+  new Directory(target).createSync();
+  new Link(link).createSync(target);
+  Expect.equals(
+      FileSystemEntityType.directory, FileSystemEntity.typeSync(link));
+  Expect.equals(
+      FileSystemEntityType.directory, FileSystemEntity.typeSync(target));
+  Expect.equals(FileSystemEntityType.link,
+      FileSystemEntity.typeSync(link, followLinks: false));
+  Expect.equals(FileSystemEntityType.directory,
+      FileSystemEntity.typeSync(target, followLinks: false));
+  Expect.isTrue(FileSystemEntity.isLinkSync(link));
+  Expect.isFalse(FileSystemEntity.isLinkSync(target));
+  Expect.isTrue(new Directory(link).existsSync());
+  Expect.isTrue(new Directory(target).existsSync());
+  Expect.isTrue(new Link(link).existsSync());
+  Expect.isFalse(new Link(target).existsSync());
+  Expect.equals(target, new Link(link).targetSync());
+  Expect.throws(() => new Link(target).targetSync());
+
+  String createdThroughLink = join(base, 'link', 'createdThroughLink');
+  String createdDirectly = join(base, 'target', 'createdDirectly');
+  new Directory(createdThroughLink).createSync();
+  new Directory(createdDirectly).createSync();
+  Expect.isTrue(new Directory(createdThroughLink).existsSync());
+  Expect.isTrue(new Directory(createdDirectly).existsSync());
+  Expect.isTrue(
+      new Directory(join(base, 'link', 'createdDirectly')).existsSync());
+  Expect.isTrue(
+      new Directory(join(base, 'target', 'createdThroughLink')).existsSync());
+  Expect.equals(FileSystemEntityType.directory,
+      FileSystemEntity.typeSync(createdThroughLink, followLinks: false));
+  Expect.equals(FileSystemEntityType.directory,
+      FileSystemEntity.typeSync(createdDirectly, followLinks: false));
+
+  // Test FileSystemEntity.identical on files, directories, and links,
+  // reached by different paths.
+  Expect.isTrue(
+      FileSystemEntity.identicalSync(createdDirectly, createdDirectly));
+  Expect.isFalse(
+      FileSystemEntity.identicalSync(createdDirectly, createdThroughLink));
+  Expect.isTrue(FileSystemEntity.identicalSync(
+      createdDirectly, join(base, 'link', 'createdDirectly')));
+  Expect.isTrue(FileSystemEntity.identicalSync(
+      createdThroughLink, join(base, 'target', 'createdThroughLink')));
+
+  Expect.isFalse(FileSystemEntity.identicalSync(target, link));
+  Expect.isTrue(FileSystemEntity.identicalSync(link, link));
+  Expect.isTrue(FileSystemEntity.identicalSync(target, target));
+  Expect.isTrue(
+      FileSystemEntity.identicalSync(target, new Link(link).targetSync()));
+  String absolutePath = new File(".").resolveSymbolicLinksSync();
+  Expect.isTrue(FileSystemEntity.identicalSync(".", absolutePath));
+
+  String createdFile = join(base, 'target', 'createdFile');
+  new File(createdFile).createSync();
+  Expect.isTrue(FileSystemEntity.identicalSync(createdFile, createdFile));
+  Expect.isFalse(FileSystemEntity.identicalSync(createdFile, createdDirectly));
+  Expect.isTrue(FileSystemEntity.identicalSync(
+      createdFile, join(base, 'link', 'createdFile')));
+  Expect.throws(() => FileSystemEntity.identicalSync(
+      createdFile, join(base, 'link', 'does_not_exist')));
+
+  var baseDir = new Directory(base);
+
+  Map makeExpected(bool recursive, bool followLinks) {
+    Map expected = new Map();
+    expected['target'] = 'Directory';
+    expected['link'] = followLinks ? 'Directory' : 'Link';
+    if (recursive) {
+      expected[join('target', 'createdDirectly')] = 'Directory';
+      expected[join('target', 'createdThroughLink')] = 'Directory';
+      expected[join('target', 'createdFile')] = 'File';
+      if (followLinks) {
+        expected[join('link', 'createdDirectly')] = 'Directory';
+        expected[join('link', 'createdThroughLink')] = 'Directory';
+        expected[join('link', 'createdFile')] = 'File';
+      }
+    }
+    return expected;
+  }
+
+  void checkEntity(FileSystemEntity x, Map expected) {
+    String ending = relative(x.path, from: base);
+    Expect.isNotNull(expected[ending]);
+    Expect.isTrue(x.toString().startsWith(expected[ending]));
+    expected[ending] = 'Found';
+  }
+
+  var futures = <Future>[];
+  for (bool recursive in [true, false]) {
+    for (bool followLinks in [true, false]) {
+      Map expected = makeExpected(recursive, followLinks);
+      for (var x
+          in baseDir.listSync(recursive: recursive, followLinks: followLinks)) {
+        checkEntity(x, expected);
+      }
+      for (var v in expected.values) {
+        Expect.equals('Found', v);
+      }
+      expected = makeExpected(recursive, followLinks);
+      // We use Stream.reduce to run a function on each entry, and return
+      // a future that completes when done.
+      var f = new Completer();
+      futures.add(f.future);
+      baseDir.list(recursive: recursive, followLinks: followLinks).listen(
+          (entity) {
+        checkEntity(entity, expected);
+      }, onDone: () {
+        for (var v in expected.values) {
+          Expect.equals('Found', v);
+        }
+        f.complete(null);
+      });
+    }
+  }
+  Future.wait(futures).then((_) {
+    new Directory(target).deleteSync(recursive: true);
+    for (bool recursive in [true, false]) {
+      for (bool followLinks in [true, false]) {
+        var result =
+            baseDir.listSync(recursive: recursive, followLinks: followLinks);
+        Expect.equals(1, result.length);
+        Expect.isTrue(result[0] is Link);
+      }
+    }
+    baseDir.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+testCreateLoopingLink() {
+  asyncStart();
+  String base = Directory.systemTemp.createTempSync('dart_link').path;
+  new Directory(join(base, 'a', 'b', 'c'))
+      .create(recursive: true)
+      .then((_) =>
+          new Link(join(base, 'a', 'b', 'c', 'd')).create(join(base, 'a', 'b')))
+      .then((_) =>
+          new Link(join(base, 'a', 'b', 'c', 'e')).create(join(base, 'a')))
+      .then((_) => new Directory(join(base, 'a'))
+          .list(recursive: true, followLinks: false)
+          .last)
+      .then((_) =>
+          // This directory listing must terminate, even though it contains loops.
+          new Directory(join(base, 'a'))
+              .list(recursive: true, followLinks: true)
+              .last)
+      .then((_) =>
+          // This directory listing must terminate, even though it contains loops.
+          new Directory(join(base, 'a', 'b', 'c'))
+              .list(recursive: true, followLinks: true)
+              .last)
+      .whenComplete(() {
+    new Directory(base).deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
+
+testRenameSync() {
+  testRename(String base, String target) {
+    Link link1 = new Link(join(base, 'c'))..createSync(target);
+    Expect.isTrue(link1.existsSync());
+    Link link2 = link1.renameSync(join(base, 'd'));
+    Expect.isFalse(link1.existsSync());
+    Expect.isTrue(link2.existsSync());
+    link2.deleteSync();
+    Expect.isFalse(link2.existsSync());
+  }
+
+  testRenameToLink(String base, String target) {
+    Link link1 = Link(join(base, '1'))..createSync(target);
+    Link link2 = Link(join(base, '2'))..createSync(target);
+    Expect.isTrue(link1.existsSync());
+    Expect.isTrue(link2.existsSync());
+    Link renamed = link1.renameSync(link2.path);
+    Expect.isFalse(link1.existsSync());
+    Expect.isTrue(renamed.existsSync());
+    renamed.deleteSync();
+    Expect.isFalse(renamed.existsSync());
+  }
+
+  testRenameToTarget(String linkName, String target, bool isDirectory) {
+    Link link = Link(linkName)..createSync(target);
+    Expect.isTrue(link.existsSync());
+    try {
+      Link renamed = link.renameSync(target);
+      if (isDirectory) {
+        Expect.fail('Renaming a link to the name of an existing directory ' +
+            'should fail');
+      }
+      Expect.isTrue(renamed.existsSync());
+      renamed.deleteSync();
+    } on FileSystemException catch (_) {
+      if (isDirectory) {
+        return;
+      }
+      Expect.fail('Renaming a link to the name of an existing file should ' +
+          'not fail');
+    }
+  }
+
+  Directory baseDir = Directory.systemTemp.createTempSync('dart_link');
+  String base = baseDir.path;
+  Directory dir = new Directory(join(base, 'a'))..createSync();
+  File file = new File(join(base, 'b'))..createSync();
+
+  testRename(base, file.path);
+  testRename(base, dir.path);
+
+  testRenameToLink(base, file.path);
+
+  testRenameToTarget(join(base, 'fileLink'), file.path, false);
+  testRenameToTarget(join(base, 'dirLink'), dir.path, true);
+
+  baseDir.deleteSync(recursive: true);
+}
+
+void testLinkErrorSync() {
+  Expect.throws(
+      () => new Link('some-dir-that-doent exist/some link file/bla/fisk')
+          .createSync('bla bla bla/b lalal/blfir/sdfred/es'),
+      (e) => e is FileSystemException);
+}
+
+checkExists(String filePath) => Expect.isTrue(new File(filePath).existsSync());
+
+testRelativeLinksSync() {
+  Directory tempDirectory = Directory.systemTemp.createTempSync('dart_link');
+  String temp = tempDirectory.path;
+  String oldWorkingDirectory = Directory.current.path;
+  // Make directories and files to test links.
+  new Directory(join(temp, 'dir1', 'dir2')).createSync(recursive: true);
+  new File(join(temp, 'dir1', 'file1')).createSync();
+  new File(join(temp, 'dir1', 'dir2', 'file2')).createSync();
+  // Make links whose path and/or target is given by a relative path.
+  new Link(join(temp, 'dir1', 'link1_2')).createSync('dir2');
+  Directory.current = temp;
+  new Link('link0_2').createSync(join('dir1', 'dir2'));
+  new Link(join('dir1', 'link1_0')).createSync('..');
+  Directory.current = 'dir1';
+  new Link(join('..', 'link0_1')).createSync('dir1');
+  new Link(join('dir2', 'link2_1')).createSync(join(temp, 'dir1'));
+  new Link(join(temp, 'dir1', 'dir2', 'link2_0')).createSync(join('..', '..'));
+  // Test that the links go to the right targets.
+  checkExists(join('..', 'link0_1', 'file1'));
+  checkExists(join('..', 'link0_2', 'file2'));
+  checkExists(join('link1_0', 'dir1', 'file1'));
+  checkExists(join('link1_2', 'file2'));
+  checkExists(join('dir2', 'link2_0', 'dir1', 'file1'));
+  checkExists(join('dir2', 'link2_1', 'file1'));
+  // Clean up
+  Directory.current = oldWorkingDirectory;
+  tempDirectory.deleteSync(recursive: true);
+}
+
+testIsDir() async {
+  // Only run on Platforms that supports file watcher
+  if (!Platform.isWindows && !Platform.isLinux && !Platform.isMacOS) return;
+  Directory sandbox = Directory.systemTemp.createTempSync();
+  Directory dir = new Directory(sandbox.path + Platform.pathSeparator + "dir");
+  dir.createSync();
+  File target = new File(sandbox.path + Platform.pathSeparator + "target");
+  target.createSync();
+
+  var eventCompleter = new Completer<FileSystemEvent>();
+  var subscription;
+  // Check for link pointing to file
+  subscription = dir.watch().listen((FileSystemEvent event) {
+    if (event.path.endsWith('link')) {
+      eventCompleter.complete(event);
+      subscription.cancel();
+    }
+  });
+  Link link = new Link(dir.path + Platform.pathSeparator + "link");
+  link.createSync(target.path);
+  var event = await eventCompleter.future;
+  Expect.isFalse(event.isDirectory);
+
+  // Check for link pointing to directory
+  eventCompleter = new Completer<FileSystemEvent>();
+  subscription = dir.watch().listen((FileSystemEvent event) {
+    if (event.path.endsWith('link2')) {
+      eventCompleter.complete(event);
+      subscription.cancel();
+    }
+  });
+  link = new Link(dir.path + Platform.pathSeparator + "link2");
+  link.createSync(dir.path);
+  event = await eventCompleter.future;
+  Expect.isFalse(event.isDirectory);
+
+  sandbox.deleteSync(recursive: true);
+}
+
+main() {
+  testCreateSync();
+  testCreateLoopingLink();
+  testRenameSync();
+  testLinkErrorSync();
+  testRelativeLinksSync();
+  testIsDir();
+}
diff --git a/tests/standalone/io/link_uri_test.dart b/tests/standalone/io/link_uri_test.dart
new file mode 100644
index 0000000..755812b
--- /dev/null
+++ b/tests/standalone/io/link_uri_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.
+
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testFromUri() {
+  asyncStart();
+  Directory originalWorkingDirectory = Directory.current;
+  Directory.systemTemp.createTemp('dart_file').then((temp) {
+    File target = new File(temp.path + '/target');
+    target.createSync();
+
+    String linkname = temp.path + '/from_uri';
+    Uri linkUri = new Uri.file(linkname);
+    Link link = new Link.fromUri(linkUri);
+    Expect.isTrue(linkUri.isAbsolute);
+    Expect.isTrue(linkUri.path.startsWith('/'));
+    link.createSync(target.path);
+    Expect.isTrue(new Link.fromUri(linkUri).existsSync());
+    Expect.isTrue(new Link.fromUri(Uri.base.resolveUri(linkUri)).existsSync());
+    Directory.current = temp.path;
+    Expect.isTrue(new Link.fromUri(Uri.parse('from_uri')).existsSync());
+    Expect.isTrue(new Link.fromUri(Uri.base.resolve('from_uri')).existsSync());
+    Directory.current = originalWorkingDirectory;
+    link.deleteSync();
+    target.deleteSync();
+    temp.deleteSync();
+    asyncEnd();
+  });
+}
+
+void testFromUriUnsupported() {
+  Expect.throwsUnsupportedError(
+      () => new Link.fromUri(Uri.parse('http://localhost:8080/index.html')));
+  Expect.throwsUnsupportedError(
+      () => new Link.fromUri(Uri.parse('ftp://localhost/tmp/xxx')));
+  Expect.throwsUnsupportedError(
+      () => new Link.fromUri(Uri.parse('name#fragment')));
+}
+
+void main() {
+  testFromUri();
+  testFromUriUnsupported();
+}
diff --git a/tests/standalone/io/locale_name_test.dart b/tests/standalone/io/locale_name_test.dart
new file mode 100644
index 0000000..7298ca7
--- /dev/null
+++ b/tests/standalone/io/locale_name_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+main() {
+  try {
+    Platform.localeName;
+  } catch (e, s) {
+    Expect.fail("Platform.localeName threw: $e\n$s\n");
+  }
+  Expect.isNotNull(Platform.localeName);
+  Expect.isTrue(Platform.localeName is String);
+}
diff --git a/tests/standalone/io/many_directory_operations_test.dart b/tests/standalone/io/many_directory_operations_test.dart
new file mode 100644
index 0000000..7e33403
--- /dev/null
+++ b/tests/standalone/io/many_directory_operations_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.
+//
+// Dart test program for testing using a lot of native port operations.
+
+import "dart:io";
+
+main() {
+  for (var i = 0; i < 10000; i++) {
+    new Directory(".").exists().then((result) => null);
+  }
+}
diff --git a/tests/standalone/io/many_file_operations_test.dart b/tests/standalone/io/many_file_operations_test.dart
new file mode 100644
index 0000000..294e9c6
--- /dev/null
+++ b/tests/standalone/io/many_file_operations_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.
+//
+// Dart test program for testing using a lot of native port operations.
+
+import "dart:io";
+
+main() {
+  for (var i = 0; i < 10000; i++) {
+    File f = new File("xxx");
+    f.exists().then((result) => null);
+  }
+}
diff --git a/tests/standalone/io/named_pipe_script_test.dart b/tests/standalone/io/named_pipe_script_test.dart
new file mode 100644
index 0000000..932b46c
--- /dev/null
+++ b/tests/standalone/io/named_pipe_script_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Testing file input stream, VM-only, standalone test.
+
+import "dart:convert";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() async {
+  asyncStart();
+  // Reading a script from a named pipe is only supported on Linux and MacOS.
+  if (!Platform.isLinux && !Platform.isMacOS) {
+    print("This test is only supported on Linux and MacOS.");
+    asyncEnd();
+    return;
+  }
+
+  final String script = 'main() { print("Hello, World!"); }';
+  final String stdinPipePath = '/dev/fd/0';
+
+  // If there's no file system access to the pipe, then we can't do a meaningful
+  // test.
+  if (!await (new File(stdinPipePath).exists())) {
+    print("Couldn't find $stdinPipePath.");
+    asyncEnd();
+    return;
+  }
+
+  StringBuffer output = new StringBuffer();
+  Process process = await Process.start(
+      Platform.executable,
+      []
+        ..addAll(Platform.executableArguments)
+        ..add(stdinPipePath));
+  bool stdinWriteFailed = false;
+  process.stdout.transform(utf8.decoder).listen(output.write);
+  process.stderr.transform(utf8.decoder).listen((data) {
+    if (!stdinWriteFailed) {
+      Expect.fail(data);
+      process.kill();
+    }
+  });
+  process.stdin.done.catchError((e) {
+    // If the write to stdin fails, then give up. We can't test the thing we
+    // wanted to test.
+    stdinWriteFailed = true;
+    process.kill();
+  });
+  process.stdin.writeln(script);
+  await process.stdin.flush();
+  await process.stdin.close();
+
+  int status = await process.exitCode;
+  if (!stdinWriteFailed) {
+    Expect.equals(0, status);
+    Expect.equals("Hello, World!\n", output.toString());
+  }
+  asyncEnd();
+}
diff --git a/tests/standalone/io/namespace_test.dart b/tests/standalone/io/namespace_test.dart
new file mode 100644
index 0000000..601278f
--- /dev/null
+++ b/tests/standalone/io/namespace_test.dart
@@ -0,0 +1,222 @@
+// 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:io";
+
+import "package:expect/expect.dart";
+
+const String file1str = "file1";
+
+void doTestSync() {
+  // Stuff that should exist.
+  Directory dir1 = new Directory("/dir1");
+  Directory dir2 = new Directory("/dir1/dir2");
+  File file1 = new File("/dir1/dir2/file1");
+
+  Expect.isTrue(dir1.existsSync());
+  Expect.isTrue(dir2.existsSync());
+  Expect.isTrue(file1.existsSync());
+  Expect.equals(file1str, file1.readAsStringSync());
+
+  // Relative paths since cwd of the namespace should be "/".
+  Directory dir1rel = new Directory("dir1");
+  Directory dir2rel = new Directory("dir1/dir2");
+  File file1rel = new File("dir1/dir2/file1");
+
+  Expect.equals("/", Directory.current.path);
+  Expect.isTrue(dir1rel.existsSync());
+  Expect.isTrue(dir2rel.existsSync());
+  Expect.isTrue(file1rel.existsSync());
+  Expect.equals(file1str, file1.readAsStringSync());
+
+  // Stuff that should not exist.
+  Expect.isFalse(new Directory("/tmp").existsSync());
+  Expect.isFalse(new File("/tmp").existsSync());
+  Expect.isFalse(new File(Platform.script.path).existsSync());
+  Expect.isFalse(new File(Platform.executable).existsSync());
+  Expect.isFalse(new File(Platform.resolvedExecutable).existsSync());
+
+  // File operations in the namespace.
+  // copy.
+  File file2 = file1.copySync("/file2");
+  Expect.isTrue(file2.existsSync());
+  Expect.equals(file1.readAsStringSync(), file2.readAsStringSync());
+  // create.
+  File file3 = new File("/file3")..createSync();
+  Expect.isTrue(file3.existsSync());
+  // last{Accessed,Modified}.
+  DateTime time = new DateTime.fromMillisecondsSinceEpoch(0);
+  file2.setLastAccessedSync(time);
+  file2.setLastModifiedSync(time);
+  Expect.equals(time, file2.lastAccessedSync());
+  Expect.equals(time, file2.lastModifiedSync());
+  Expect.equals(file1str.length, file2.lengthSync());
+  // open.
+  RandomAccessFile file2raf = file2.openSync();
+  Expect.equals(file1str.codeUnitAt(0), file2raf.readByteSync());
+  file2raf.closeSync();
+  // rename.
+  File file4 = new File("file4");
+  file3.renameSync(file4.path);
+  Expect.isFalse(file3.existsSync());
+  Expect.isTrue(file4.existsSync());
+  // delete.
+  file4.deleteSync();
+  Expect.isFalse(file4.existsSync());
+  // stat.
+  FileStat stat = file2.statSync();
+  Expect.equals(time, stat.modified);
+
+  // Directory operaions in the namespace.
+  // absolute.
+  Expect.equals(dir1.path, dir1rel.absolute.path);
+  // create
+  Directory dir3 = new Directory("/dir3");
+  dir3.createSync();
+  Expect.isTrue(dir3.existsSync());
+  // createTemp
+  Directory dir3temp = dir3.createTempSync();
+  Expect.isTrue(dir3temp.existsSync());
+  // listSync
+  List fses = Directory.current.listSync();
+  Expect.isTrue(fses.any((fse) => fse.path == dir3.path));
+  // rename.
+  Directory dir4 = new Directory("dir4");
+  dir3.renameSync(dir4.path);
+  Expect.isTrue(dir4.existsSync());
+  // delete.
+  dir4.deleteSync(recursive: true);
+  Expect.isFalse(dir4.existsSync());
+  // stat.
+  FileStat dirstat = dir2.statSync();
+  Expect.equals(FileSystemEntityType.directory, dirstat.type);
+}
+
+doTestAsync() async {
+  // Stuff that should exist.
+  Directory dir1 = new Directory("/dir1");
+  Directory dir2 = new Directory("/dir1/dir2");
+  File file1 = new File("/dir1/dir2/file1");
+
+  Expect.isTrue(await dir1.exists());
+  Expect.isTrue(await dir2.exists());
+  Expect.isTrue(await file1.exists());
+  Expect.equals(file1str, await file1.readAsString());
+
+  // Relative paths since cwd of the namespace should be "/".
+  Directory dir1rel = new Directory("dir1");
+  Directory dir2rel = new Directory("dir1/dir2");
+  File file1rel = new File("dir1/dir2/file1");
+
+  Expect.equals("/", Directory.current.path);
+  Expect.isTrue(await dir1rel.exists());
+  Expect.isTrue(await dir2rel.exists());
+  Expect.isTrue(await file1rel.exists());
+  Expect.equals(file1str, await file1.readAsString());
+
+  // Stuff that should not exist.
+  Expect.isFalse(await new Directory("/tmp").exists());
+  Expect.isFalse(await new File("/tmp").exists());
+  Expect.isFalse(await new File(Platform.script.path).exists());
+  Expect.isFalse(await new File(Platform.executable).exists());
+  Expect.isFalse(await new File(Platform.resolvedExecutable).exists());
+
+  // File operations in the namespace.
+  // copy.
+  File file2 = await file1.copy("/file2");
+  Expect.isTrue(await file2.exists());
+  Expect.equals(await file1.readAsString(), await file2.readAsString());
+  // create.
+  File file3 = new File("/file3");
+  await file3.create();
+  Expect.isTrue(await file3.exists());
+  // last{Accessed,Modified}.
+  DateTime time = new DateTime.fromMillisecondsSinceEpoch(0);
+  await file2.setLastAccessed(time);
+  await file2.setLastModified(time);
+  Expect.equals(time, await file2.lastAccessed());
+  Expect.equals(time, await file2.lastModified());
+  Expect.equals(file1str.length, await file2.length());
+  // open.
+  RandomAccessFile file2raf = await file2.open();
+  Expect.equals(file1str.codeUnitAt(0), await file2raf.readByte());
+  await file2raf.close();
+  // rename.
+  File file4 = new File("file4");
+  await file3.rename(file4.path);
+  Expect.isFalse(await file3.exists());
+  Expect.isTrue(await file4.exists());
+  // delete.
+  await file4.delete();
+  Expect.isFalse(await file4.exists());
+  // stat.
+  FileStat stat = await file2.stat();
+  Expect.equals(time, stat.modified);
+
+  // Directory operaions in the namespace.
+  // absolute.
+  Expect.equals(dir1.path, dir1rel.absolute.path);
+  // create
+  Directory dir3 = new Directory("/dir3");
+  await dir3.create();
+  Expect.isTrue(await dir3.exists());
+  // createTemp
+  Directory dir3temp = await dir3.createTemp();
+  Expect.isTrue(await dir3temp.exists());
+  // listSync
+  List fses = await Directory.current.list().toList();
+  Expect.isTrue(fses.any((fse) => fse.path == dir3.path));
+  // rename.
+  Directory dir4 = new Directory("dir4");
+  dir3.renameSync(dir4.path);
+  Expect.isTrue(await dir4.exists());
+  // delete.
+  dir4.deleteSync(recursive: true);
+  Expect.isFalse(await dir4.exists());
+  // stat.
+  FileStat dirstat = await dir2.stat();
+  Expect.equals(FileSystemEntityType.directory, dirstat.type);
+}
+
+void setupTest() {
+  // Create a namespace in /tmp.
+  Directory namespace = Directory.systemTemp.createTempSync("namespace");
+  try {
+    // Create some stuff that should be visible.
+    Directory dir1 = new Directory("${namespace.path}/dir1")..createSync();
+    Directory dir2 = new Directory("${dir1.path}/dir2")..createSync();
+    File file1 = new File("${dir2.path}/file1")
+      ..createSync()
+      ..writeAsStringSync(file1str);
+
+    // Run the test and capture stdout.
+    var args = <String>[]..addAll(Platform.executableArguments);
+    args.addAll([
+      "--namespace=${namespace.path}",
+      Platform.script.toFilePath(),
+      "--run"
+    ]);
+    var pr = Process.runSync(Platform.executable, args);
+    if (pr.exitCode != 0) {
+      print("stdout:\n${pr.stdout}");
+      print("stderr:\n${pr.stderr}");
+    }
+    Expect.equals(0, pr.exitCode);
+  } finally {
+    namespace.deleteSync(recursive: true);
+  }
+}
+
+main(List<String> arguments) async {
+  if (!Platform.isLinux) {
+    return;
+  }
+  if (arguments.contains("--run")) {
+    doTestSync();
+    await doTestAsync();
+  } else {
+    setupTest();
+  }
+}
diff --git a/tests/standalone/io/network_interface_test.dart b/tests/standalone/io/network_interface_test.dart
new file mode 100644
index 0000000..bfdd20e
--- /dev/null
+++ b/tests/standalone/io/network_interface_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 'dart:io';
+
+import "package:expect/expect.dart";
+
+void testListLoopback() {
+  NetworkInterface.list(includeLoopback: false).then((list) {
+    for (var i in list) {
+      for (var a in i.addresses) {
+        Expect.isFalse(a.isLoopback);
+      }
+    }
+  });
+
+  NetworkInterface.list(includeLoopback: true).then((list) {
+    Expect.isTrue(list.any((i) => i.addresses.any((a) => a.isLoopback)));
+  });
+}
+
+void testListLinkLocal() {
+  NetworkInterface.list(includeLinkLocal: false).then((list) {
+    for (var i in list) {
+      for (var a in i.addresses) {
+        Expect.isFalse(a.isLinkLocal);
+      }
+    }
+  });
+}
+
+void testListIndex() {
+  var set = new Set();
+  NetworkInterface.list(includeLoopback: true).then((list) {
+    for (var i in list) {
+      Expect.isNotNull(i.index);
+      Expect.isFalse(set.contains(i.index));
+      set.add(i.index);
+      Expect.isTrue(set.contains(i.index));
+    }
+  });
+}
+
+void main() {
+  if (!NetworkInterface.listSupported) {
+    return;
+  }
+  testListLoopback();
+  testListLinkLocal();
+  testListIndex();
+}
diff --git a/tests/standalone/io/non_utf8_directory_test.dart b/tests/standalone/io/non_utf8_directory_test.dart
new file mode 100644
index 0000000..0dea9aa
--- /dev/null
+++ b/tests/standalone/io/non_utf8_directory_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:test/test.dart';
+
+Future main() async {
+  var asyncDir;
+  var syncDir;
+
+  test('Non-UTF8 Directory Listing', () async {
+    final tmp =
+        await Directory.systemTemp.createTemp('non_utf8_directory_test_async');
+    try {
+      final rawPath = new Uint8List.fromList([182]);
+      asyncDir = new Directory.fromRawPath(rawPath);
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          await asyncDir.create();
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          await tmp.delete(recursive: true);
+          return;
+        }
+      } else {
+        await asyncDir.create();
+      }
+      expect(await asyncDir.exists(), isTrue);
+
+      await for (final e in tmp.list()) {
+        // FIXME(bkonyi): reenable when rawPath is exposed.
+        /*
+        if (Platform.isWindows) {
+          // Windows replaces invalid characters with � when creating file system
+          // entities.
+          final raw = e.rawPath;
+          expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+        } else {
+          expect(e.rawPath.last, 182);
+        }
+        */
+      }
+      await asyncDir.delete(recursive: true);
+    } finally {
+      await tmp.delete(recursive: true);
+    }
+  });
+
+  test('Non-UTF8 Directory Sync Listing', () {
+    final tmp =
+        Directory.systemTemp.createTempSync('non_utf8_directory_test_sync');
+    try {
+      final rawPath = new Uint8List.fromList([182]);
+      syncDir = new Directory.fromRawPath(rawPath);
+
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          syncDir.createSync();
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          tmp.deleteSync(recursive: true);
+          return;
+        }
+      } else {
+        syncDir.createSync();
+      }
+      expect(syncDir.existsSync(), isTrue);
+
+      for (final e in tmp.listSync()) {
+        // FIXME(bkonyi): reenable when rawPath is exposed.
+        /*
+        if (Platform.isWindows) {
+          // Windows replaces invalid characters with � when creating file system
+          // entities.
+          final raw = e.rawPath;
+          expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+        } else {
+          expect(e.rawPath.last, 182);
+        }
+        */
+      }
+      syncDir.deleteSync(recursive: true);
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  });
+}
diff --git a/tests/standalone/io/non_utf8_file_test.dart b/tests/standalone/io/non_utf8_file_test.dart
new file mode 100644
index 0000000..4ea6ed4
--- /dev/null
+++ b/tests/standalone/io/non_utf8_file_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:test/test.dart';
+
+Future main() async {
+  var asyncFile;
+  var syncFile;
+
+  test('Non-UTF8 Filename', () async {
+    final tmp =
+        await Directory.systemTemp.createTemp('non_utf8_file_test_async');
+    try {
+      final rawPath = new Uint8List.fromList([182]);
+      asyncFile = new File.fromRawPath(rawPath);
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          await asyncFile.create();
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          await tmp.delete(recursive: true);
+          return;
+        }
+      } else {
+        await asyncFile.create();
+      }
+      expect(await asyncFile.exists(), isTrue);
+
+      for (final file in tmp.listSync()) {
+        // FIXME(bkonyi): reenable when rawPath is exposed.
+        /*
+        if (Platform.isWindows) {
+          // Windows replaces invalid characters with � when creating file system
+          // entities.
+          final raw = file.rawPath;
+          expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+        } else {
+          expect(file.rawPath.last, 182);
+        }
+        */
+        // FIXME(bkonyi): this isn't true on some versions of MacOS. Why?
+        if (!Platform.isMacOS && !Platform.isIOS) {
+          expect(file.path.endsWith('�'), isTrue);
+        }
+      }
+      await asyncFile.delete();
+    } finally {
+      await tmp.delete(recursive: true);
+    }
+  });
+
+  test('Non-UTF8 Filename Sync', () {
+    final tmp = Directory.systemTemp.createTempSync('non_utf8_file_test_sync');
+    try {
+      final rawPath = new Uint8List.fromList([182]);
+      syncFile = new File.fromRawPath(rawPath);
+
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          syncFile.createSync();
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          tmp.deleteSync(recursive: true);
+          return;
+        }
+      } else {
+        syncFile.createSync();
+      }
+      expect(syncFile.existsSync(), isTrue);
+
+      for (final file in tmp.listSync()) {
+        // FIXME(bkonyi): reenable when rawPath is exposed.
+        /*
+        if (Platform.isWindows) {
+          // Windows replaces invalid characters with � when creating file system
+          // entities.
+          final raw = file.rawPath;
+          expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+        } else {
+          expect(file.rawPath.last, 182);
+        }
+        */
+        // FIXME(bkonyi): this isn't true on some versions of MacOS. Why?
+        if (!Platform.isMacOS && !Platform.isIOS) {
+          expect(file.path.endsWith('�'), isTrue);
+        }
+      }
+      syncFile.deleteSync();
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  });
+}
diff --git a/tests/standalone/io/non_utf8_link_test.dart b/tests/standalone/io/non_utf8_link_test.dart
new file mode 100644
index 0000000..aadd30a
--- /dev/null
+++ b/tests/standalone/io/non_utf8_link_test.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:path/path.dart';
+import 'package:test/test.dart';
+
+Future main() async {
+  var asyncLink;
+  var syncLink;
+  const dirName = 'foobar';
+
+  test('Non-UTF8 Link', () async {
+    Directory tmp =
+        await Directory.systemTemp.createTemp('non_utf8_link_test_async');
+    try {
+      tmp = new Directory(await tmp.resolveSymbolicLinks());
+      final path = join(tmp.path, dirName);
+      final rawPath =
+          utf8.encode(path).sublist(0, path.length - dirName.length).toList();
+      rawPath.add(47);
+      rawPath.add(182);
+
+      final f = new Directory(path);
+      await f.create();
+      expect(await f.exists(), isTrue);
+
+      final rawName = new Uint8List.fromList(rawPath);
+      asyncLink = new Link.fromRawPath(rawName);
+
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          asyncLink = await asyncLink.create(path);
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          await tmp.delete(recursive: true);
+          return;
+        }
+      } else {
+        asyncLink = await asyncLink.create(path);
+      }
+      expect(await asyncLink.exists(), isTrue);
+
+      await for (final e in tmp.list()) {
+        if (e is Link) {
+          // FIXME(bkonyi): reenable when rawPath is exposed.
+          /*
+          if (Platform.isWindows) {
+            // Windows replaces invalid characters with � when creating file system
+            // entities.
+            final raw = e.rawPath;
+            expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+          } else {
+            expect(e.rawPath.last, 182);
+          }
+          */
+          expect(e.path, path);
+        }
+      }
+
+      // FIXME(bkonyi): reenable when rawPath is exposed.
+      // expect(asyncLink.absolute.rawPath, rawPath);
+      expect(await asyncLink.resolveSymbolicLinks(), path);
+      expect(await asyncLink.target(), path);
+      await asyncLink.delete();
+    } finally {
+      await tmp.delete(recursive: true);
+    }
+  });
+
+  test('Non-UTF8 Link Sync', () {
+    Directory tmp =
+        Directory.systemTemp.createTempSync('non_utf8_link_test_sync');
+    try {
+      tmp = new Directory(tmp.resolveSymbolicLinksSync());
+      final path = join(tmp.path, dirName);
+      final rawPath =
+          utf8.encode(path).sublist(0, path.length - dirName.length).toList();
+      rawPath.add(47); // '/'
+      rawPath.add(182); // invalid UTF-8 character.
+
+      final f = new Directory(path);
+      f.createSync();
+      expect(f.existsSync(), isTrue);
+
+      final rawName = new Uint8List.fromList(rawPath);
+      syncLink = new Link.fromRawPath(rawName);
+
+      if (Platform.isMacOS || Platform.isIOS) {
+        try {
+          syncLink.createSync(path);
+        } on FileSystemException catch (e) {
+          // Macos doesn't support non-UTF-8 paths.
+          tmp.deleteSync(recursive: true);
+          return;
+        }
+      } else {
+        syncLink.createSync(path);
+      }
+      expect(syncLink.existsSync(), isTrue);
+
+      for (final e in tmp.listSync()) {
+        if (e is Link) {
+          // FIXME(bkonyi): reenable when rawPath is exposed.
+          /*
+          if (Platform.isWindows) {
+            // Windows replaces invalid characters with � when creating file system
+            // entities.
+            final raw = e.rawPath;
+            expect(raw.sublist(raw.length - 3), [239, 191, 189]);
+          } else {
+            expect(e.rawPath.last, 182);
+          }
+          */
+          expect(e.path, path);
+        }
+      }
+      // FIXME(bkonyi): reenable when rawPath is exposed.
+      // expect(syncLink.absolute.rawPath, rawPath);
+      expect(syncLink.resolveSymbolicLinksSync(), path);
+      expect(syncLink.targetSync(), path);
+      syncLink.deleteSync();
+    } finally {
+      tmp.deleteSync(recursive: true);
+    }
+  });
+}
diff --git a/tests/standalone/io/non_utf8_output_test.dart b/tests/standalone/io/non_utf8_output_test.dart
new file mode 100644
index 0000000..d714087
--- /dev/null
+++ b/tests/standalone/io/non_utf8_output_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test emits non-UTF-8 formatted data.
+// It should have the test expectation: NonUtf8Output.
+
+import 'dart:io';
+
+main() {
+  String german = "German characters: aäbcdefghijklmnoöpqrsßtuüvwxyz";
+  stdout.add(german.runes.toList());
+}
diff --git a/tests/standalone/io/parent_test.dart b/tests/standalone/io/parent_test.dart
new file mode 100644
index 0000000..9e9438c
--- /dev/null
+++ b/tests/standalone/io/parent_test.dart
@@ -0,0 +1,119 @@
+// 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 program for testing file I/O.
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+late String tempDirectory;
+
+void main() {
+  if (Platform.isWindows) {
+    testWindowsCases();
+  } else {
+    testPosixCases();
+  }
+  asyncStart();
+  createTempDirectories().then(testObjects).whenComplete(() {
+    asyncEnd();
+    new Directory(tempDirectory).delete(recursive: true);
+  });
+}
+
+testPosixCases() {
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir/file'));
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir/file/'));
+  Expect.equals('/dir', FileSystemEntity.parentOf('/dir//file//'));
+  Expect.equals('/', FileSystemEntity.parentOf('/dir'));
+  Expect.equals('/', FileSystemEntity.parentOf('/dir///'));
+  Expect.equals('/', FileSystemEntity.parentOf('/'));
+
+  Expect.equals('.', FileSystemEntity.parentOf('file'));
+  Expect.equals('.', FileSystemEntity.parentOf('file//'));
+  Expect.equals('.', FileSystemEntity.parentOf(''));
+  Expect.equals('.', FileSystemEntity.parentOf('..'));
+  Expect.equals('.', FileSystemEntity.parentOf('.'));
+  Expect.equals('.', FileSystemEntity.parentOf(''));
+  Expect.equals('/', FileSystemEntity.parentOf('/'));
+  Expect.equals('/', FileSystemEntity.parentOf('//'));
+  Expect.equals('/', FileSystemEntity.parentOf('//file///'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file/'));
+  Expect.equals('dir', FileSystemEntity.parentOf('dir/file//'));
+  Expect.equals('dir/subdir', FileSystemEntity.parentOf('dir/subdir/file'));
+  Expect.equals('dir//subdir', FileSystemEntity.parentOf('dir//subdir//file/'));
+  Expect.equals(
+      'dir/sub.dir', FileSystemEntity.parentOf('dir/sub.dir/fi le///'));
+  Expect.equals('dir/..', FileSystemEntity.parentOf('dir/../file/'));
+  Expect.equals('dir/..', FileSystemEntity.parentOf('dir/../..'));
+  Expect.equals('.', FileSystemEntity.parentOf('./..'));
+  Expect.equals('..', FileSystemEntity.parentOf('../.'));
+}
+
+testWindowsCases() {
+  Expect.equals(r'C:/dir', FileSystemEntity.parentOf(r'C:/dir/file'));
+  Expect.equals(r'C:/dir', FileSystemEntity.parentOf(r'C:/dir/file/'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\file'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\file\'));
+  Expect.equals(r'C:\dir', FileSystemEntity.parentOf(r'C:\dir\\file\\'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\dir'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\dir\/\'));
+  Expect.equals(r'C:\', FileSystemEntity.parentOf(r'C:\'));
+  // FileSystemEntity.isAbsolute returns false for 'C:'.
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'C:'));
+
+  Expect.equals(r'\\server\share\dir',
+      FileSystemEntity.parentOf(r'\\server\share\dir\file'));
+  Expect.equals(r'\\server\share\dir',
+      FileSystemEntity.parentOf(r'\\server\share\dir\file\'));
+  Expect.equals(
+      r'\\server\share', FileSystemEntity.parentOf(r'\\server\share\file'));
+  Expect.equals(r'\\server\', FileSystemEntity.parentOf(r'\\server\share'));
+  Expect.equals(r'\\server\', FileSystemEntity.parentOf(r'\\server\share\'));
+  Expect.equals(r'\\server\', FileSystemEntity.parentOf(r'\\server\'));
+  Expect.equals(r'\\server/', FileSystemEntity.parentOf(r'\\server/'));
+  Expect.equals(r'\\serve', FileSystemEntity.parentOf(r'\\serve'));
+
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'file'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r''));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'..'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r'.'));
+  Expect.equals(r'.', FileSystemEntity.parentOf(r''));
+  Expect.equals(r'/', FileSystemEntity.parentOf(r'/'));
+  Expect.equals(r'\', FileSystemEntity.parentOf(r'\'));
+  Expect.equals(r'\', FileSystemEntity.parentOf(r'\file\\/'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir\file'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir\file\'));
+  Expect.equals(r'dir', FileSystemEntity.parentOf(r'dir/file/'));
+  Expect.equals(r'dir\subdir', FileSystemEntity.parentOf(r'dir\subdir\file'));
+  Expect.equals(
+      r'dir\sub.dir', FileSystemEntity.parentOf(r'dir\sub.dir\fi le'));
+}
+
+Future createTempDirectories() {
+  return Directory.systemTemp
+      .createTemp('dart_parent_')
+      .then((dir) => tempDirectory = dir.path)
+      .then((_) => new File(join(tempDirectory, 'file1')).create())
+      .then((_) => new Link(join(tempDirectory, 'link1')).create('.'))
+      .then((_) => new Directory(join(tempDirectory, 'dir1')).create());
+}
+
+testObjects(var ignored) {
+  ['file1', 'link1', 'dir1', 'file2', 'link2', 'dir2'].map(testPath);
+}
+
+testPath(String path) {
+  Expect.equals(tempDirectory, new File(join(tempDirectory, path)).parent.path);
+  Expect.equals(tempDirectory, new Link(join(tempDirectory, path)).parent.path);
+  Expect.equals(
+      tempDirectory, new Directory(join(tempDirectory, path)).parent.path);
+}
diff --git a/tests/standalone/io/pipe_server_test.dart b/tests/standalone/io/pipe_server_test.dart
new file mode 100644
index 0000000..52d93b6
--- /dev/null
+++ b/tests/standalone/io/pipe_server_test.dart
@@ -0,0 +1,122 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// OtherResources=readline_test1.dat
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+library ServerTest;
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+part "testing_server.dart";
+
+String getDataFilename(String path) =>
+    Platform.script.resolve(path).toFilePath();
+
+bool compareFileContent(String fileName1, String fileName2) {
+  var contents1 = new File(fileName1).readAsStringSync();
+  var contents2 = new File(fileName2).readAsStringSync();
+  return contents1 == contents2;
+}
+
+// This test does:
+//  1. Opens a socket to the testing server.
+//  2. Pipes the content of a file to that sockets input stream.
+//  3. Creates a temp file.
+//  4. Pipes the socket output stream to the temp file.
+//  5. Expects the original file and the temp file to be equal.
+class PipeServerGame {
+  int count = 0;
+
+  PipeServerGame.start() : _messages = 0 {
+    initialize();
+  }
+
+  void runTest() {
+    void connectHandler() {
+      String srcFileName = getDataFilename("readline_test1.dat");
+      Stream fileInput = new File(srcFileName).openRead();
+      fileInput.cast<List<int>>().pipe(_socket).then((_) {
+        var tempDir = Directory.systemTemp.createTempSync('dart_pipe_server');
+        var dstFileName = tempDir.path + "/readline_test1.dat";
+        var dstFile = new File(dstFileName);
+        dstFile.createSync();
+        var fileOutput = dstFile.openWrite();
+        _socket.cast<List<int>>().pipe(fileOutput).then((_) {
+          // Check that the resulting file is equal to the initial
+          // file.
+          bool result = compareFileContent(srcFileName, dstFileName);
+          new File(dstFileName).deleteSync();
+          tempDir.deleteSync();
+          Expect.isTrue(result);
+
+          // Run this twice.
+          if (count++ < 2) {
+            runTest();
+          } else {
+            shutdown();
+          }
+        });
+      });
+    }
+
+    // Connect to the server.
+    Socket.connect(TestingServer.HOST, _port).then((s) {
+      _socket = s;
+      connectHandler();
+    });
+  }
+
+  void initialize() {
+    var receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startPipeServer, receivePort.sendPort);
+    receivePort.first.then((msg) {
+      this._port = msg[0];
+      this._closeSendPort = msg[1];
+      runTest();
+    });
+  }
+
+  void shutdown() {
+    _closeSendPort.send(null);
+    asyncEnd();
+  }
+
+  late int _port;
+  late SendPort _closeSendPort;
+  late Socket _socket;
+  int _messages = 0;
+}
+
+void startPipeServer(Object replyPortObj) {
+  SendPort replyPort = replyPortObj as SendPort;
+  var server = new PipeServer();
+  server.init().then((port) {
+    replyPort.send([port, server.closeSendPort]);
+  });
+}
+
+// The testing server will simply pipe each connecting sockets input
+// stream to its output stream.
+class PipeServer extends TestingServer {
+  void onConnection(Socket connection) {
+    connection.cast<List<int>>().pipe(connection);
+  }
+}
+
+main() {
+  asyncStart();
+  PipeServerGame echoServerGame = new PipeServerGame.start();
+}
diff --git a/tests/standalone/io/platform_os_version_test.dart b/tests/standalone/io/platform_os_version_test.dart
new file mode 100644
index 0000000..fff7335
--- /dev/null
+++ b/tests/standalone/io/platform_os_version_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+main() {
+  var version = Platform.operatingSystemVersion;
+  Expect.isNotNull(version);
+  Expect.isTrue(version is String);
+}
diff --git a/tests/standalone/io/platform_resolved_executable_test.dart b/tests/standalone/io/platform_resolved_executable_test.dart
new file mode 100644
index 0000000..919f9d8
--- /dev/null
+++ b/tests/standalone/io/platform_resolved_executable_test.dart
@@ -0,0 +1,158 @@
+// 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.
+//
+// Process test program to test process communication.
+
+library PlatformExecutableTest;
+
+import "dart:io";
+
+const _SCRIPT_KEY = '_test_script';
+
+void expectEquals(a, b) {
+  if (a != b) {
+    throw 'Expected: $a\n'
+        '  Actual: $b';
+  }
+}
+
+void verify(String exePath, {String? altPath}) {
+  var env = {_SCRIPT_KEY: 'yes'};
+  if (altPath != null) {
+    env['PATH'] = altPath;
+  }
+
+  var processResult = Process.runSync(
+      exePath, [...Platform.executableArguments, scriptPath],
+      includeParentEnvironment: false, runInShell: true, environment: env);
+
+  if (processResult.exitCode != 0) {
+    throw 'Error with process\n'
+        '$scriptPath'
+        'Exit code: ${processResult.exitCode}\n'
+        '   STDOUT: ${processResult.stdout}\n'
+        '   STDERR: ${processResult.stderr}\n';
+  }
+
+  var result = processResult.stdout.trim();
+  expectEquals(Platform.resolvedExecutable, result);
+}
+
+void testDartExecShouldNotBeInCurrentDir() {
+  var type = FileSystemEntity.typeSync(platformExeName);
+  expectEquals(FileSystemEntityType.notFound, type);
+}
+
+void testShouldFailOutsidePath() {
+  var threw = false;
+  try {
+    Process.runSync(platformExeName, ['--version'],
+        includeParentEnvironment: false,
+        environment: {_SCRIPT_KEY: 'yes', 'PATH': ''});
+  } catch (_) {
+    threw = true;
+  }
+
+  if (!threw) {
+    throw 'Expected running the dart executable – "$platformExeName" without'
+        ' the parent environment or path to fail.';
+  }
+}
+
+void testShouldSucceedWithSourcePlatformExecutable() {
+  verify(Platform.resolvedExecutable);
+}
+
+void testExeSymLinked(Directory dir) {
+  var dirUri = new Uri.directory(dir.path);
+  var link = new Link.fromUri(dirUri.resolve('dart_exe_link'));
+  link.createSync(Platform.resolvedExecutable);
+  verify(link.path);
+}
+
+void testPathToDirWithExeSymLinked(Directory dir) {
+  var dirUri = new Uri.directory(dir.path);
+  var link = new Link.fromUri(dirUri.resolve('dart_exe_link'));
+  link.createSync(Platform.resolvedExecutable);
+  verify('dart_exe_link', altPath: dir.path);
+}
+
+/// Create a sym-link to the SDK directory and run 'dart' from that path
+void testExeDirSymLinked(Directory dir) {
+  var dirUri = new Uri.directory(dir.path);
+
+  var linkDirUri = dirUri.resolve('dart_bin_dir_link');
+  var link = new Link.fromUri(linkDirUri);
+
+  var exeFile = new File(Platform.resolvedExecutable);
+
+  link.createSync(exeFile.parent.path);
+
+  var linkedBin =
+      new Uri.directory(linkDirUri.toFilePath()).resolve(platformExeName);
+
+  verify(linkedBin.toFilePath());
+}
+
+void testPathPointsToSymLinkedSDKPath(Directory dir) {
+  var dirUri = new Uri.directory(dir.path);
+
+  var linkDirUri = dirUri.resolve('dart_bin_dir_link');
+  var link = new Link.fromUri(linkDirUri);
+
+  var exeFile = new File(Platform.resolvedExecutable);
+
+  link.createSync(exeFile.parent.path);
+
+  verify(platformExeName, altPath: link.path);
+}
+
+void testPathToSDKDir() {
+  var exeFile = new File(Platform.resolvedExecutable);
+  var binDirPath = exeFile.parent.path;
+
+  verify(platformExeName, altPath: binDirPath);
+}
+
+void withTempDir(void test(Directory dir)) {
+  var tempDir = Directory.systemTemp.createTempSync('dart.sdk.test.');
+  try {
+    test(tempDir);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+String get platformExeName {
+  var raw = new Uri.file(Platform.resolvedExecutable);
+  return raw.pathSegments.last;
+}
+
+String get scriptPath => Platform.script.toFilePath();
+
+void main() {
+  // The same script is used for both running the tests and as for starting
+  // child verifying the value of Platform.resolvedExecutable. If the
+  // environment variable _SCRIPT_KEY is set this is a child process which
+  // should print the value of Platform.resolvedExecutable.
+  if (Platform.environment.containsKey(_SCRIPT_KEY)) {
+    print(Platform.resolvedExecutable);
+    return;
+  }
+
+  testDartExecShouldNotBeInCurrentDir();
+  testShouldSucceedWithSourcePlatformExecutable(); //# 00: ok
+  // dart:io does not support linking to files in Windows.
+  if (!Platform.isWindows) {
+    withTempDir(testExeSymLinked); //# 01: ok
+  }
+  withTempDir(testExeDirSymLinked); //# 02: ok
+  testPathToSDKDir(); //# 03: ok
+  withTempDir(testPathPointsToSymLinkedSDKPath); //# 04: ok
+  // dart:io does not support linking to files in Windows.
+  if (!Platform.isWindows) {
+    withTempDir(testPathToDirWithExeSymLinked); //# 05: ok
+  }
+  testShouldFailOutsidePath(); //# 06: ok
+}
diff --git a/tests/standalone/io/platform_test.dart b/tests/standalone/io/platform_test.dart
new file mode 100644
index 0000000..e337c5c
--- /dev/null
+++ b/tests/standalone/io/platform_test.dart
@@ -0,0 +1,168 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+test() {
+  Expect.isTrue(Platform.numberOfProcessors > 0);
+  var os = Platform.operatingSystem;
+  Expect.isTrue(
+      os == "android" || os == "linux" || os == "macos" || os == "windows");
+  Expect.equals(Platform.isLinux, Platform.operatingSystem == "linux");
+  Expect.equals(Platform.isMacOS, Platform.operatingSystem == "macos");
+  Expect.equals(Platform.isWindows, Platform.operatingSystem == "windows");
+  Expect.equals(Platform.isAndroid, Platform.operatingSystem == "android");
+  var sep = Platform.pathSeparator;
+  Expect.isTrue(sep == '/' || (os == 'windows' && sep == '\\'));
+  var hostname = Platform.localHostname;
+  Expect.isTrue(hostname is String && hostname != "");
+  var environment = Platform.environment;
+  Expect.isTrue(environment is Map<String, String>);
+  if (!Platform.isWindows) {
+    Expect.isTrue(Platform.executable.endsWith('dart'));
+    Expect.isTrue(Platform.resolvedExecutable.endsWith('dart'));
+  } else {
+    Expect.isTrue(Platform.executable.endsWith('dart.exe'));
+    Expect.isTrue(Platform.resolvedExecutable.endsWith('dart.exe'));
+  }
+  if (!Platform.isWindows) {
+    Expect.isTrue(Platform.resolvedExecutable.startsWith('/'));
+  } else {
+    // This assumes that tests (both locally and on the bots) are
+    // running off a location referred to by a drive letter. If a UNC
+    // location is used or long names ("\\?\" prefix) is used this
+    // needs to be fixed.
+    Expect.equals(Platform.resolvedExecutable.substring(1, 3), ':\\');
+  }
+  // Move directory to be sure script is correct.
+  var oldDir = Directory.current;
+  Directory.current = Directory.current.parent;
+  Expect.isTrue(Platform.script.path
+      .endsWith('tests/standalone_2/io/platform_test.dart'));
+  Expect.isTrue(Platform.script.toFilePath().startsWith(oldDir.path));
+  // Restore dir.
+  Directory.current = oldDir;
+  var pkgRootString = Platform.packageRoot;
+  if (pkgRootString != null) {
+    Directory packageRoot = new Directory.fromUri(Uri.parse(pkgRootString));
+    Expect.isTrue(packageRoot.existsSync());
+    Expect.isTrue(new Directory("${packageRoot.path}/expect").existsSync());
+    Expect.isTrue(Platform.executableArguments.any((arg) {
+      if (!arg.startsWith("--package-root=")) {
+        return false;
+      }
+      // Cut out the '--package-root=' prefix.
+      arg = arg.substring(15);
+      return pkgRootString.contains(arg);
+    }));
+  }
+}
+
+void f(reply) {
+  reply.send({
+    "Platform.executable": Platform.executable,
+    "Platform.script": Platform.script,
+    "Platform.packageRoot": Platform.packageRoot,
+    "Platform.executableArguments": Platform.executableArguments
+  });
+}
+
+testIsolate() {
+  asyncStart();
+  ReceivePort port = new ReceivePort();
+  var remote = Isolate.spawn(f, port.sendPort);
+  port.first.then((results) {
+    Expect.equals(Platform.executable, results["Platform.executable"]);
+
+    Uri uri = results["Platform.script"];
+    // SpawnFunction retains the script url of the parent which in this
+    // case was a relative path.
+    Expect.equals("file", uri.scheme);
+    Expect.isTrue(
+        uri.path.endsWith('tests/standalone_2/io/platform_test.dart'));
+    Expect.equals(Platform.packageRoot, results["Platform.packageRoot"]);
+    Expect.listEquals(
+        Platform.executableArguments, results["Platform.executableArguments"]);
+    asyncEnd();
+  });
+}
+
+testVersion() {
+  checkValidVersion(String version) {
+    RegExp re = new RegExp(r'(\d+)\.(\d+)\.(\d+)(-dev\.([^\.]*)\.([^\.]*))?');
+    var match = re.firstMatch(version)!;
+    var major = int.parse(match.group(1)!);
+    // Major version.
+    Expect.isTrue(major == 1 || major == 2);
+    // Minor version.
+    Expect.isTrue(int.parse(match.group(2)!) >= 0);
+    // Patch version.
+    Expect.isTrue(int.parse(match.group(3)!) >= 0);
+    // Dev
+    if (match.group(4) != null) {
+      // Dev prerelease minor version
+      Expect.isTrue(int.parse(match.group(5)!) >= 0);
+      // Dev prerelease patch version
+      Expect.isTrue(int.parse(match.group(6)!) >= 0);
+    }
+  }
+
+  checkInvalidVersion(String version) {
+    try {
+      checkValidVersion(version);
+    } on FormatException {
+      return;
+    } on ExpectException {
+      return;
+    }
+    Expect.testError("checkValidVersion accepts invalid version: $version");
+  }
+
+  String stripAdditionalInfo(String version) {
+    var index = version.indexOf(' ');
+    if (index == -1) return version;
+    return version.substring(0, index);
+  }
+
+  // Sanity-checks for `checkValidVersion`.
+  // Ensure we can match valid versions.
+  checkValidVersion('1.9.0');
+  checkValidVersion('2.0.0');
+  checkValidVersion('1.9.0-dev.0.0');
+  checkValidVersion('1.9.0-edge');
+  checkValidVersion('1.9.0-edge.r41234');
+  // Check stripping of additional information.
+  checkValidVersion(stripAdditionalInfo(
+      '1.9.0-dev.1.2 (Wed Feb 25 02:22:19 2015) on "linux_ia32"'));
+  // Reject some invalid versions.
+  checkInvalidVersion('1.9');
+  checkInvalidVersion('..');
+  checkInvalidVersion('1..');
+  checkInvalidVersion('1.9.');
+  checkInvalidVersion('1.9.0-dev..');
+  checkInvalidVersion('1.9.0-dev..0');
+  checkInvalidVersion('1.9.0-dev.0.');
+  checkInvalidVersion('1.9.0-dev.x.y');
+  checkInvalidVersion('x');
+  checkInvalidVersion('x.y.z');
+
+  // Test current version.
+  checkValidVersion(stripAdditionalInfo(Platform.version));
+}
+
+main() {
+  // This tests assumes paths relative to dart main directory
+  Directory.current = Platform.script.resolve('../../..').toFilePath();
+  test();
+  testIsolate();
+  testVersion();
+}
diff --git a/tests/standalone/io/print_env.dart b/tests/standalone/io/print_env.dart
new file mode 100644
index 0000000..4337451
--- /dev/null
+++ b/tests/standalone/io/print_env.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.
+
+import "dart:io";
+
+main(List<String> arguments) {
+  if (!Platform.script.isAbsolute) {
+    throw "Platform.script is not absolute: ${Platform.script}";
+  }
+  print(Platform.environment[arguments[0]]);
+}
diff --git a/tests/standalone/io/print_sync_script.dart b/tests/standalone/io/print_sync_script.dart
new file mode 100644
index 0000000..ea42729
--- /dev/null
+++ b/tests/standalone/io/print_sync_script.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.
+
+import 'dart:io';
+
+String get bigString {
+  var buffer = new StringBuffer();
+  for (var i = 0; i < 1000; i++) {
+    buffer.write(i);
+    for (var i = 0; i < 200; i++) {
+      buffer.write('=');
+    }
+    buffer.writeln();
+  }
+  return buffer.toString();
+}
+
+main() {
+  stdout; // Be sure to mark stdout as non-blocking.
+  print(bigString);
+}
diff --git a/tests/standalone/io/print_sync_test.dart b/tests/standalone/io/print_sync_test.dart
new file mode 100644
index 0000000..c23df59
--- /dev/null
+++ b/tests/standalone/io/print_sync_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.
+
+// OtherResources=print_sync_script.dart
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void main() {
+  asyncStart();
+  Process.run(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(
+                Platform.script.resolve('print_sync_script.dart').toFilePath()))
+      .then((out) {
+    asyncEnd();
+    Expect.equals(1002, out.stdout.split('\n').length);
+  });
+}
diff --git a/tests/standalone/io/process_broken_pipe_test.dart b/tests/standalone/io/process_broken_pipe_test.dart
new file mode 100644
index 0000000..7791fd4
--- /dev/null
+++ b/tests/standalone/io/process_broken_pipe_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.
+//
+// Process test program to test closed stdin from child process.
+
+import "package:expect/expect.dart";
+import "dart:io";
+import "dart:isolate";
+
+import "process_test_util.dart";
+
+main() {
+  // Running dart without arguments makes it close right away.
+  var future = Process.start(Platform.executable, []);
+  future.then((process) {
+    process.stdin.done.catchError((e) {
+      // Accept errors on stdin.
+    });
+
+    // Drain stdout and stderr.
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+
+    // Write to the stdin after the process is terminated to test
+    // writing to a broken pipe.
+    process.exitCode.then((code) {
+      process.stdin.add([0]);
+    });
+  });
+}
diff --git a/tests/standalone/io/process_check_arguments_script.dart b/tests/standalone/io/process_check_arguments_script.dart
new file mode 100644
index 0000000..4c19479
--- /dev/null
+++ b/tests/standalone/io/process_check_arguments_script.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.
+//
+// Utility script to check that arguments are correctly passed from
+// one dart process to another using the dart:io process interface.
+import "dart:io";
+import "dart:math";
+
+class Expect {
+  static void isTrue(x) {
+    if (!x) {
+      throw new StateError("Not true");
+    }
+  }
+
+  static void equals(x, y) {
+    if (x != y) {
+      throw new StateError("Not equal");
+    }
+  }
+}
+
+main(List<String> arguments) {
+  Expect.isTrue(
+      Platform.script.path.endsWith('process_check_arguments_script.dart'));
+  var expected_num_args = int.parse(arguments[0]);
+  var contains_quote = int.parse(arguments[1]);
+  Expect.equals(expected_num_args, arguments.length);
+  for (var i = 2; i < arguments.length; i++) {
+    Expect.isTrue((contains_quote == 0) || arguments[i].contains('"'));
+  }
+}
diff --git a/tests/standalone/io/process_check_arguments_test.dart b/tests/standalone/io/process_check_arguments_test.dart
new file mode 100644
index 0000000..c79c00e
--- /dev/null
+++ b/tests/standalone/io/process_check_arguments_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";
+import "dart:io";
+import "process_test_util.dart";
+
+test(args) {
+  var future = Process.start(Platform.executable,
+      []..addAll(Platform.executableArguments)..addAll(args));
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(0, exitCode);
+    });
+    // Drain stdout and stderr.
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+  });
+}
+
+main() {
+  // Get the Dart script file which checks arguments.
+  var scriptFile =
+      new File("tests/standalone_2/io/process_check_arguments_script.dart");
+  if (!scriptFile.existsSync()) {
+    scriptFile = new File(
+        "../tests/standalone_2/io/process_check_arguments_script.dart");
+  }
+  test([scriptFile.path, '3', '0', 'a']);
+  test([scriptFile.path, '3', '0', 'a b']);
+  test([scriptFile.path, '3', '0', 'a\tb']);
+  test([scriptFile.path, '3', '1', 'a\tb"']);
+  test([scriptFile.path, '3', '1', 'a"\tb']);
+  test([scriptFile.path, '3', '1', 'a"\t\\\\"b"']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a\t\t\t\tb']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a    b']);
+}
diff --git a/tests/standalone/io/process_detached_script.dart b/tests/standalone/io/process_detached_script.dart
new file mode 100644
index 0000000..b1f9ab9
--- /dev/null
+++ b/tests/standalone/io/process_detached_script.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.
+//
+// Simple script hanging for testing a detached process.
+
+import 'dart:io';
+import 'dart:isolate';
+
+void main(List<String> args) {
+  new ReceivePort().listen(print);
+
+  // If an argument 'echo' is passed echo stdin to stdout and stderr.
+  if (args.length == 1 && args[0] == 'echo') {
+    stdin.fold<List<int>>(<int>[], (p, e) => p..addAll(e)).then((message) {
+      stdout.add(message);
+      stderr.add(message);
+      stdout.close();
+      stderr.close();
+    });
+  }
+}
diff --git a/tests/standalone/io/process_detached_test.dart b/tests/standalone/io/process_detached_test.dart
new file mode 100644
index 0000000..f970fa6
--- /dev/null
+++ b/tests/standalone/io/process_detached_test.dart
@@ -0,0 +1,87 @@
+// 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.
+
+// OtherResources=process_detached_script.dart
+
+// Process test program to test detached processes.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+import "process_test_util.dart";
+
+void test() {
+  asyncStart();
+  var script =
+      Platform.script.resolve('process_detached_script.dart').toFilePath();
+  var future = Process.start(
+      Platform.executable,
+      []
+        ..addAll(Platform.executableArguments)
+        ..add(script),
+      mode: ProcessStartMode.detached);
+  future.then((process) {
+    Expect.isNotNull(process.pid);
+    Expect.isTrue(process.pid is int);
+    Expect.isNull(process.exitCode);
+    Expect.isNull(process.stderr);
+    Expect.isNull(process.stdin);
+    Expect.isNull(process.stdout);
+    Expect.isTrue(process.kill());
+  }).whenComplete(() {
+    asyncEnd();
+  });
+}
+
+void testWithStdio() {
+  asyncStart();
+  var script =
+      Platform.script.resolve('process_detached_script.dart').toFilePath();
+  var future = Process.start(Platform.executable,
+      []..addAll(Platform.executableArguments)..addAll([script, 'echo']),
+      mode: ProcessStartMode.detachedWithStdio);
+  future.then((process) {
+    Expect.isNotNull(process.pid);
+    Expect.isTrue(process.pid is int);
+    Expect.isNull(process.exitCode);
+    var message = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    process.stdin.add(message);
+    process.stdin.flush().then((_) => process.stdin.close());
+    var f1 = process.stdout.fold<List<int>>([], (p, e) => p..addAll(e));
+    var f2 = process.stderr.fold<List<int>>([], (p, e) => p..addAll(e));
+    return Future.wait([f1, f2]).then((values) {
+      Expect.listEquals(values[0] as List, message);
+      Expect.listEquals(values[1] as List, message);
+    }).whenComplete(() {
+      Expect.isTrue(process.kill());
+    });
+  }).whenComplete(() {
+    asyncEnd();
+  });
+}
+
+void testFailure() {
+  asyncStart();
+  Directory.systemTemp.createTemp('dart_detached_process').then((temp) {
+    var future =
+        Process.start(temp.path, ['a', 'b'], mode: ProcessStartMode.detached);
+    future.then((process) {
+      Expect.fail('Starting process from invalid executable succeeded');
+    }, onError: (e) {
+      Expect.isTrue(e is ProcessException);
+    }).whenComplete(() {
+      temp.deleteSync();
+      asyncEnd();
+    });
+  });
+}
+
+main() {
+  test();
+  testWithStdio();
+  testFailure();
+}
diff --git a/tests/standalone/io/process_echo_util.dart b/tests/standalone/io/process_echo_util.dart
new file mode 100644
index 0000000..1c6d17e
--- /dev/null
+++ b/tests/standalone/io/process_echo_util.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.
+
+import "dart:io";
+
+void main(List<String> arguments) {
+  arguments.forEach(print);
+}
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
new file mode 100644
index 0000000..ca56130
--- /dev/null
+++ b/tests/standalone/io/process_environment_test.dart
@@ -0,0 +1,79 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+import "process_test_util.dart";
+
+runEnvironmentProcess(
+    Map<String, String> environment, name, includeParent, callback) {
+  var dartExecutable = Platform.executable;
+  var printEnv = 'tests/standalone_2/io/print_env.dart';
+  if (!new File(printEnv).existsSync()) {
+    printEnv = '../$printEnv';
+  }
+  Process.run(dartExecutable,
+          []..addAll(Platform.executableArguments)..addAll([printEnv, name]),
+          environment: environment, includeParentEnvironment: includeParent)
+      .then((result) {
+    if (result.exitCode != 0) {
+      print('print_env.dart subprocess failed '
+          'with exit code ${result.exitCode}');
+      print('stdout:');
+      print(result.stdout);
+      print('stderr:');
+      print(result.stderr);
+    }
+    Expect.equals(0, result.exitCode);
+    callback(result.stdout);
+  });
+}
+
+testEnvironment() {
+  asyncStart();
+  Map env = Platform.environment;
+  Expect.isFalse(env.isEmpty);
+  // Check that some value in the environment stays the same when passed
+  // to another process.
+  for (var k in env.keys) {
+    runEnvironmentProcess({}, k, true, (output) {
+      // Only check startsWith. The print statements will add
+      // newlines at the end.
+      Expect.isTrue(output.startsWith(env[k]));
+      // Add a new variable and check that it becomes an environment
+      // variable in the child process.
+      var copy = new Map<String, String>.from(env);
+      var name = 'MYENVVAR';
+      while (env.containsKey(name)) name = '${name}_';
+      copy[name] = 'value';
+      runEnvironmentProcess(copy, name, true, (output) {
+        Expect.isTrue(output.startsWith('value'));
+        asyncEnd();
+      });
+    });
+    // Only check one value to not spin up too many processes testing the
+    // same things.
+    break;
+  }
+}
+
+testNoIncludeEnvironment() {
+  asyncStart();
+  var env = Platform.environment;
+  Expect.isTrue(env.containsKey('PATH'));
+  env = new Map.from(env);
+  env.remove('PATH');
+  runEnvironmentProcess(env, "PATH", false, (output) {
+    Expect.isTrue(output.startsWith("null"));
+    asyncEnd();
+  });
+}
+
+main() {
+  testEnvironment();
+  testNoIncludeEnvironment();
+}
diff --git a/tests/standalone/io/process_exit_test.dart b/tests/standalone/io/process_exit_test.dart
new file mode 100644
index 0000000..c42c50c
--- /dev/null
+++ b/tests/standalone/io/process_exit_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.
+//
+// Process test program to test process communication.
+
+library ProcessExitTest;
+
+import "dart:io";
+import "package:expect/expect.dart";
+import "process_test_util.dart";
+
+testExit() {
+  var future =
+      Process.start(getProcessTestFileName(), const ["0", "0", "99", "0"]);
+  future.then((process) {
+    process.exitCode.then((int exitCode) {
+      Expect.equals(exitCode, 99);
+    });
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+  });
+}
+
+testExitRun() {
+  Process.run(getProcessTestFileName(), const ["0", "0", "99", "0"])
+      .then((result) {
+    Expect.equals(result.exitCode, 99);
+    Expect.equals(result.stdout, '');
+    Expect.equals(result.stderr, '');
+  });
+}
+
+main() {
+  testExit();
+  testExitRun();
+}
diff --git a/tests/standalone/io/process_info_test.dart b/tests/standalone/io/process_info_test.dart
new file mode 100644
index 0000000..72f2260
--- /dev/null
+++ b/tests/standalone/io/process_info_test.dart
@@ -0,0 +1,19 @@
+// 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:io";
+
+import "package:expect/expect.dart";
+
+main() {
+  int currentRss = ProcessInfo.currentRss;
+  print('currentRss = $currentRss');
+  Expect.isTrue(currentRss > 0);
+
+  int maxRss = ProcessInfo.maxRss;
+  print('maxRss = $maxRss');
+  Expect.isTrue(maxRss > 0);
+
+  Expect.isTrue(currentRss <= maxRss);
+}
diff --git a/tests/standalone/io/process_inherit_stdio_script.dart b/tests/standalone/io/process_inherit_stdio_script.dart
new file mode 100644
index 0000000..c771dab
--- /dev/null
+++ b/tests/standalone/io/process_inherit_stdio_script.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.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:async_helper/async_helper.dart";
+
+void main(List<String> args) {
+  String arg = args[0];
+  if (arg == "--child") {
+    print(args[1]);
+    return;
+  }
+  asyncStart();
+  var script =
+      Platform.script.resolve('process_inherit_stdio_script.dart').toFilePath();
+  var future = Process.start(
+      Platform.executable,
+      []
+        ..addAll(Platform.executableArguments)
+        ..addAll([script, "--child", "foo"]),
+      mode: ProcessStartMode.inheritStdio);
+  future.then((process) {
+    process.exitCode.then((c) {
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/process_inherit_stdio_test.dart b/tests/standalone/io/process_inherit_stdio_test.dart
new file mode 100644
index 0000000..964440f
--- /dev/null
+++ b/tests/standalone/io/process_inherit_stdio_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// OtherResources=process_inherit_stdio_script.dart
+
+// Process test program to test 'inherit stdio' processes.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+import "process_test_util.dart";
+
+main() {
+  asyncStart();
+  // process_inherit_stdio_script.dart spawns a process in inheritStdio mode
+  // that prints to its stdout. Since that child process inherits the stdout
+  // of the process spawned here, we should see it.
+  var script =
+      Platform.script.resolve('process_inherit_stdio_script.dart').toFilePath();
+  var future = Process.start(Platform.executable,
+      []..addAll(Platform.executableArguments)..addAll([script, "foo"]));
+  Completer<String> s = new Completer();
+  future.then((process) {
+    StringBuffer buf = new StringBuffer();
+    process.stdout.transform(utf8.decoder).listen((data) {
+      buf.write(data);
+    }, onDone: () {
+      s.complete(buf.toString());
+    });
+  });
+  s.future.then((String result) {
+    Expect.isTrue(result.contains("foo"));
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/process_kill_test.dart b/tests/standalone/io/process_kill_test.dart
new file mode 100644
index 0000000..9816d41
--- /dev/null
+++ b/tests/standalone/io/process_kill_test.dart
@@ -0,0 +1,49 @@
+// 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.
+//
+// Process test program to test process communication.
+
+library ProcessKillTest;
+
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+import "process_test_util.dart";
+
+testKill() {
+  asyncStart();
+  // Start a process that will hang waiting for input until killed.
+  Process.start(getProcessTestFileName(), const ["0", "1", "0", "0"]).then((p) {
+    p.exitCode.then((exitCode) {
+      // Process killed from the side so exit code is not 0.
+      Expect.isTrue(exitCode != 0);
+      // Killing a process that is already dead returns false.
+      Expect.isFalse(p.kill());
+      asyncEnd();
+    });
+    Expect.isTrue(p.kill());
+  });
+}
+
+testKillPid() {
+  asyncStart();
+  // Start a process that will hang waiting for input until killed.
+  Process.start(getProcessTestFileName(), const ["0", "1", "0", "0"]).then((p) {
+    p.exitCode.then((exitCode) {
+      // Process killed from the side so exit code is not 0.
+      Expect.isTrue(exitCode != 0);
+      // Killing a process that is already dead returns false.
+      Expect.isFalse(Process.killPid(p.pid));
+      asyncEnd();
+    });
+    Expect.isTrue(Process.killPid(p.pid));
+  });
+}
+
+main() {
+  testKill();
+  testKillPid();
+}
diff --git a/tests/standalone/io/process_non_ascii_test.dart b/tests/standalone/io/process_non_ascii_test.dart
new file mode 100644
index 0000000..fd08f06
--- /dev/null
+++ b/tests/standalone/io/process_non_ascii_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:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var executable = new File(Platform.executable).resolveSymbolicLinksSync();
+  var tempDir = Directory.systemTemp.createTempSync('dart_process_non_ascii');
+  var nonAsciiDir = new Directory('${tempDir.path}/æøå');
+  nonAsciiDir.createSync();
+  var nonAsciiFile = new File('${nonAsciiDir.path}/æøå.dart');
+  nonAsciiFile.writeAsStringSync("""
+import 'dart:io';
+
+main() {
+  if ('æøå' != new File('æøå.txt').readAsStringSync()) {
+    throw new StateError("not equal");
+  }
+}
+""");
+  var nonAsciiTxtFile = new File('${nonAsciiDir.path}/æøå.txt');
+  nonAsciiTxtFile.writeAsStringSync('æøå');
+  var script = nonAsciiFile.path;
+  // Note: we prevent this child process from using Crashpad handler because
+  // this introduces an issue with deleting the temporary directory.
+  Process.run(
+      executable,
+      []
+        ..addAll(Platform.executableArguments)
+        ..add(script),
+      workingDirectory: nonAsciiDir.path,
+      environment: {'DART_CRASHPAD_HANDLER': ''}).then((result) {
+    Expect.equals(0, result.exitCode);
+    tempDir.deleteSync(recursive: true);
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/process_path_environment_test.dart b/tests/standalone/io/process_path_environment_test.dart
new file mode 100644
index 0000000..ba9e805
--- /dev/null
+++ b/tests/standalone/io/process_path_environment_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 the executable is looked up on the user's PATH when spawning a
+// process and environment variables are passed in.
+
+import "dart:io";
+import "package:expect/expect.dart";
+
+main() {
+  // Pick an app that we expect to be on the PATH that returns 0 when run with
+  // no arguments.
+  var executable = 'true';
+  var args = <String>[];
+  if (Platform.operatingSystem == 'windows') {
+    executable = 'cmd.exe';
+    args = ['/C', 'echo', '"ok"'];
+  }
+
+  var environment = new Map<String, String>.from(Platform.environment);
+  environment['whatever'] = 'something';
+
+  Process.run(executable, args, environment: environment).then((result) {
+    Expect.equals(0, result.exitCode);
+  });
+}
diff --git a/tests/standalone/io/process_path_test.dart b/tests/standalone/io/process_path_test.dart
new file mode 100644
index 0000000..59fd488
--- /dev/null
+++ b/tests/standalone/io/process_path_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 that the executable is looked up on the user's PATH when spawning a
+// process.
+
+import "dart:io";
+import "package:expect/expect.dart";
+
+main() {
+  // Pick an app that we expect to be on the PATH that returns 0 when run with
+  // no arguments.
+  var executable = 'true';
+  var args = <String>[];
+  if (Platform.operatingSystem == 'windows') {
+    executable = 'cmd.exe';
+    args = ['/C', 'echo', '"ok"'];
+  }
+
+  Process.run(executable, args).then((result) {
+    Expect.equals(0, result.exitCode);
+  });
+}
diff --git a/tests/standalone/io/process_pid_test.dart b/tests/standalone/io/process_pid_test.dart
new file mode 100644
index 0000000..a965421
--- /dev/null
+++ b/tests/standalone/io/process_pid_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.
+//
+// Process test program to test process communication.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  Expect.isTrue(pid > 0);
+  var futures = <Future>[];
+  futures.add(Process.start(Platform.executable, ['--version']));
+  futures.add(Process.run(Platform.executable, ['--version']));
+  Future.wait(futures).then((results) {
+    Expect.isTrue(results[0].pid > 0);
+    Expect.isTrue(results[1].pid > 0);
+    Expect.equals(0, results[1].exitCode);
+    results[0].exitCode.then((exitCode) {
+      Expect.equals(0, exitCode);
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/process_run_output_test.dart b/tests/standalone/io/process_run_output_test.dart
new file mode 100644
index 0000000..11b111a
--- /dev/null
+++ b/tests/standalone/io/process_run_output_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.
+//
+// Test script for testing that output is handled correctly for
+// non-interactive processes started with Process.run.
+
+import "package:expect/expect.dart";
+import "dart:convert";
+import "dart:io";
+import "process_test_util.dart";
+
+checkOutput(String encoding, output) {
+  if (encoding == 'ascii') {
+    Expect.equals(output, 'abc');
+  } else if (encoding == 'latin1') {
+    Expect.equals(output, 'æøå');
+  } else if (encoding == 'utf8') {
+    Expect.listEquals(output.codeUnits, [955]);
+  } else if (encoding == 'binary') {
+    print(output);
+    Expect.listEquals(output, [0, 1, 2]);
+  }
+}
+
+test(scriptFile, String encoding, stream) {
+  var enc;
+  if (encoding == 'ascii') {
+    enc = ascii;
+  } else if (encoding == 'latin1') {
+    enc = latin1;
+  } else if (encoding == 'utf8') {
+    enc = utf8;
+  } else if (encoding == 'binary') {
+    enc = null;
+  }
+
+  var args = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..addAll([scriptFile, encoding, stream]);
+
+  if (stream == 'stdout') {
+    Process.run(Platform.executable, args, stdoutEncoding: enc).then((result) {
+      Expect.equals(result.exitCode, 0);
+      Expect.equals(result.stderr, '');
+      checkOutput(encoding, result.stdout);
+    });
+  } else {
+    Process.run(Platform.executable, args, stderrEncoding: enc).then((result) {
+      Expect.equals(result.exitCode, 0);
+      Expect.equals(result.stdout, '');
+      checkOutput(encoding, result.stderr);
+    });
+  }
+}
+
+main() {
+  var scriptFile =
+      new File("tests/standalone_2/io/process_std_io_script2.dart");
+  if (!scriptFile.existsSync()) {
+    scriptFile =
+        new File("../tests/standalone_2/io/process_std_io_script2.dart");
+  }
+  Expect.isTrue(scriptFile.existsSync());
+  test(scriptFile.path, 'ascii', 'stdout');
+  test(scriptFile.path, 'ascii', 'stderr');
+  test(scriptFile.path, 'latin1', 'stdout');
+  test(scriptFile.path, 'latin1', 'stderr');
+  test(scriptFile.path, 'utf8', 'stdout');
+  test(scriptFile.path, 'utf8', 'stderr');
+  test(scriptFile.path, 'binary', 'stdout');
+  test(scriptFile.path, 'binary', 'stderr');
+}
diff --git a/tests/standalone/io/process_run_test.dart b/tests/standalone/io/process_run_test.dart
new file mode 100644
index 0000000..a4a470a
--- /dev/null
+++ b/tests/standalone/io/process_run_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:path/path.dart" as path;
+
+import "process_test_util.dart";
+
+void testProcessRunBinaryOutput() {
+  var result = Process.runSync(
+      getProcessTestFileName(), const ["0", "0", "0", "0"],
+      stdoutEncoding: null);
+  Expect.isTrue(result.stdout is List<int>);
+  Expect.isTrue(result.stderr is String);
+
+  result = Process.runSync(getProcessTestFileName(), const ["0", "0", "0", "0"],
+      stderrEncoding: null);
+  Expect.isTrue(result.stdout is String);
+  Expect.isTrue(result.stderr is List<int>);
+
+  result = Process.runSync(getProcessTestFileName(), const ["0", "0", "0", "0"],
+      stdoutEncoding: null, stderrEncoding: null);
+  Expect.isTrue(result.stdout is List<int>);
+  Expect.isTrue(result.stderr is List<int>);
+}
+
+void testProcessPathWithSpace() {
+  // Bug: https://github.com/dart-lang/sdk/issues/37751
+  var processTest = new File(getProcessTestFileName());
+  var dir = Directory.systemTemp.createTempSync('process_run_test');
+  try {
+    File(path.join(dir.path, 'path')).createSync();
+    var innerDir = Directory(path.join(dir.path, 'path with space'));
+    innerDir.createSync();
+    processTest = processTest.copySync(path.join(
+        innerDir.path, 'process_run_test${getPlatformExecutableExtension()}'));
+    // It will run executables without throwing exception.
+    var result = Process.runSync(processTest.path, []);
+    // Kill the isolate because next test reuse the exe file.
+    Process.killPid(result.pid);
+    // Manually escape the path
+    if (Platform.isWindows) {
+      result = Process.runSync('"${processTest.path}"', []);
+      Process.killPid(result.pid);
+    }
+    result = Process.runSync('${processTest.path}', []);
+    Process.killPid(result.pid);
+  } catch (e) {
+    Expect.fail('System should find process_run_test executable');
+    print(e);
+  } finally {
+    // Clean up the temp files and directory
+    dir.deleteSync(recursive: true);
+  }
+}
+
+void main() {
+  testProcessRunBinaryOutput();
+  testProcessPathWithSpace();
+}
diff --git a/tests/standalone/io/process_segfault_test.dart b/tests/standalone/io/process_segfault_test.dart
new file mode 100644
index 0000000..9fe0ede
--- /dev/null
+++ b/tests/standalone/io/process_segfault_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.
+//
+// Process test program to test process communication.
+
+library ProcessSegfaultTest;
+
+import "dart:io";
+import "package:expect/expect.dart";
+import "process_test_util.dart";
+
+testExit() {
+  var future =
+      Process.start(getProcessTestFileName(), const ["0", "0", "1", "1"]);
+  future.then((process) {
+    process.exitCode.then((int exitCode) {
+      Expect.isTrue(exitCode != 0);
+    });
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+  });
+}
+
+testExitRun() {
+  Process.run(getProcessTestFileName(), const ["0", "0", "1", "1"])
+      .then((result) {
+    Expect.isTrue(result.exitCode != 0);
+    Expect.equals(result.stdout, '');
+    Expect.equals(result.stderr, '');
+  });
+}
+
+main() {
+  testExit();
+  testExitRun();
+}
diff --git a/tests/standalone/io/process_set_exit_code_script.dart b/tests/standalone/io/process_set_exit_code_script.dart
new file mode 100644
index 0000000..38a8075
--- /dev/null
+++ b/tests/standalone/io/process_set_exit_code_script.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:io";
+
+main() {
+  if (exitCode != 0) {
+    throw "Bad initial exit-code";
+  }
+  stdout.write("standard out");
+  stderr.write("standard error");
+  exitCode = 25;
+  if (exitCode != 25) {
+    throw "Exit-code not set correctly";
+  }
+}
diff --git a/tests/standalone/io/process_set_exit_code_test.dart b/tests/standalone/io/process_set_exit_code_test.dart
new file mode 100644
index 0000000..b8c7e12
--- /dev/null
+++ b/tests/standalone/io/process_set_exit_code_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.
+
+// OtherResources=process_set_exit_code_script.dart
+
+// Process test program to test process communication.
+
+library ProcessSetExitCodeTest;
+
+import "dart:io";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+main() {
+  var executable = Platform.executable;
+  var exitCodeScript =
+      Platform.script.resolve('process_set_exit_code_script.dart').toFilePath();
+  Process.run(
+          executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(exitCodeScript))
+      .then((result) {
+    Expect.equals("standard out", result.stdout);
+    Expect.equals("standard error", result.stderr);
+    Expect.equals(25, result.exitCode);
+  });
+}
diff --git a/tests/standalone/io/process_shell_test.dart b/tests/standalone/io/process_shell_test.dart
new file mode 100644
index 0000000..5c766b0
--- /dev/null
+++ b/tests/standalone/io/process_shell_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.
+
+// OtherResources=process_echo_util.dart
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:path/path.dart";
+import "package:async_helper/async_helper.dart";
+
+void testRunShell() {
+  test(args) {
+    asyncStart();
+    var script = Platform.script.resolve("process_echo_util.dart").toFilePath();
+    Process.run(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..add(script)
+              ..addAll(args),
+            runInShell: true)
+        .then((process_result) {
+      var result;
+      if (Platform.operatingSystem == "windows") {
+        result = process_result.stdout.split("\r\n");
+      } else {
+        result = process_result.stdout.split("\n");
+      }
+      if (result.length - 1 != args.length) {
+        throw "wrong number of args: $args vs $result";
+      }
+      for (int i = 0; i < args.length; i++) {
+        if (args[i] != result[i]) {
+          throw "bad result at $i: '${args[i]}' vs '${result[i]}'";
+        }
+      }
+      asyncEnd();
+    });
+  }
+
+  test(["\""]);
+  test(["a b"]);
+  test(["'"]);
+  test(["'", "'"]);
+  test(["'\"\"'\"'\"'"]);
+  test(["'\"\"'", "\"'\"'"]);
+  test(["'\\\"\\\"'\\", "\"\\'\"'"]);
+  test(["'\$HOME'"]);
+  test(["'\$tmp'"]);
+  test(["arg'"]);
+  test(["arg\\'", "'\\arg"]);
+}
+
+void testBadRunShell() {
+  test(exe, [List<String> args = const []]) {
+    asyncStart();
+    Process.run(exe, args, runInShell: true).then((result) {
+      if (result.exitCode == 0) {
+        throw "error expected";
+      }
+      asyncEnd();
+    });
+  }
+
+  test("'\"'");
+  test("'\$HOME'");
+}
+
+void main() {
+  testRunShell();
+  testBadRunShell();
+}
diff --git a/tests/standalone/io/process_start_exception_test.dart b/tests/standalone/io/process_start_exception_test.dart
new file mode 100644
index 0000000..3a9642e
--- /dev/null
+++ b/tests/standalone/io/process_start_exception_test.dart
@@ -0,0 +1,49 @@
+// 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.
+//
+// Process test program to errors during startup of the process.
+
+import 'dart:async';
+import 'dart:io';
+import "package:expect/expect.dart";
+
+// ENOENT and ERROR_FILE_NOT_FOUND on Windows both have the same value.
+// Note: we are setting PATH to an empty string in tests below because on
+// POSIX systems if target binary name does not contain `/` then it is
+// searched through PATH and if it is not found anywhere in the PATH
+// but some folder in PATH is inaccessible then underlying execvp(...)
+// call will return EACCES (13) instead of ENOENT.
+// For example on some Android devices PATH would include /sbin with is
+// inaccessible - so this test will fail.
+const ENOENT = 2;
+
+testStartError() {
+  Future<Process> processFuture = Process.start(
+      "__path_to_something_that_should_not_exist__", const [],
+      environment: {"PATH": ""});
+  processFuture
+      .then((p) => Expect.fail('got process despite start error'))
+      .catchError((error) {
+    Expect.isTrue(error is ProcessException);
+    Expect.equals(ENOENT, error.errorCode, error.toString());
+  });
+}
+
+testRunError() {
+  Future<ProcessResult> processFuture = Process.run(
+      "__path_to_something_that_should_not_exist__", const [],
+      environment: {"PATH": ""});
+
+  processFuture
+      .then((result) => Expect.fail("exit handler called"))
+      .catchError((error) {
+    Expect.isTrue(error is ProcessException);
+    Expect.equals(ENOENT, error.errorCode, error.toString());
+  });
+}
+
+main() {
+  testStartError();
+  testRunError();
+}
diff --git a/tests/standalone/io/process_std_io_script.dart b/tests/standalone/io/process_std_io_script.dart
new file mode 100644
index 0000000..8aee620
--- /dev/null
+++ b/tests/standalone/io/process_std_io_script.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.
+//
+// Utility script to echo stdin to stdout or stderr or both.
+
+import "dart:io";
+
+main(List<String> arguments) {
+  if (arguments.length > 0) {
+    if (arguments[0] == "0") {
+      stdin.pipe(stdout);
+    } else if (arguments[0] == "1") {
+      stdin.pipe(stderr);
+    } else if (arguments[0] == "2") {
+      stdin.listen((data) {
+        stdout.add(data);
+        stderr.add(data);
+      });
+    }
+  }
+}
diff --git a/tests/standalone/io/process_std_io_script2.dart b/tests/standalone/io/process_std_io_script2.dart
new file mode 100644
index 0000000..9dc4674
--- /dev/null
+++ b/tests/standalone/io/process_std_io_script2.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.
+//
+// Utility script to echo strings in various formats to stdout or
+// stderr.
+
+import "dart:convert";
+import "dart:io";
+
+writeData(data, encoding, stream) {
+  if (stream == "stdout") {
+    if (encoding == null) {
+      stdout.add(data);
+    } else {
+      stdout.encoding = encoding;
+      stdout.write(data);
+    }
+  } else if (stream == "stderr") {
+    if (encoding == null) {
+      stderr.add(data);
+    } else {
+      stderr.encoding = encoding;
+      stderr.write(data);
+    }
+  }
+}
+
+main(List<String> arguments) {
+  var asciiString = 'abc';
+  var latin1String = 'æøå';
+  var utf8String = new String.fromCharCodes([955]);
+  var binary = [0, 1, 2];
+  if (arguments.length > 1) {
+    var stream = arguments[1];
+    if (arguments[0] == "ascii") {
+      writeData(asciiString, ascii, stream);
+    } else if (arguments[0] == "latin1") {
+      writeData(latin1String, latin1, stream);
+    } else if (arguments[0] == "utf8") {
+      writeData(utf8String, utf8, stream);
+    } else if (arguments[0] == "binary") {
+      writeData(binary, null, stream);
+    }
+  }
+}
diff --git a/tests/standalone/io/process_stderr_test.dart b/tests/standalone/io/process_stderr_test.dart
new file mode 100644
index 0000000..0492fe2
--- /dev/null
+++ b/tests/standalone/io/process_stderr_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.
+//
+// Process test program to test process communication.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:math';
+
+import "process_test_util.dart";
+
+void test(Future<Process> future, int expectedExitCode) {
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(expectedExitCode, exitCode);
+    });
+
+    List<int> input_data = "ABCDEFGHI\n".codeUnits;
+    final int input_dataSize = input_data.length;
+
+    int received = 0;
+    List<int> buffer = [];
+
+    void readData(List<int> data) {
+      buffer.addAll(data);
+      for (int i = received;
+          i < min(input_data.length, buffer.length) - 1;
+          i++) {
+        Expect.equals(input_data[i], buffer[i]);
+      }
+      received = buffer.length;
+      if (received >= input_dataSize) {
+        // We expect an extra character on windows due to carriage return.
+        if (13 == buffer[input_dataSize - 1] &&
+            input_dataSize + 1 == received) {
+          Expect.equals(13, buffer[input_dataSize - 1]);
+          Expect.equals(10, buffer[input_dataSize]);
+          buffer.removeLast();
+        }
+      }
+    }
+
+    process.stdout.listen((_) {});
+    process.stdin.add(input_data);
+    process.stdin.flush().then((_) => process.stdin.close());
+    process.stderr.listen(readData);
+  });
+}
+
+main() {
+  // Run the test using the process_test binary.
+  test(
+      Process.start(getProcessTestFileName(), const ["1", "1", "99", "0"]), 99);
+
+  // Run the test using the dart binary with an echo script.
+  // The test runner can be run from either the root or from runtime.
+  var scriptFile = new File("tests/standalone_2/io/process_std_io_script.dart");
+  if (!scriptFile.existsSync()) {
+    scriptFile =
+        new File("../tests/standalone_2/io/process_std_io_script.dart");
+  }
+  Expect.isTrue(scriptFile.existsSync());
+  test(
+      Process.start(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..addAll([scriptFile.path, "1"])),
+      0);
+}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart
new file mode 100644
index 0000000..6bb3695
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_script.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.
+//
+// Utility script to echo stdin to stdout or stderr or both.
+
+import "dart:convert";
+import "dart:io";
+
+main() {
+  var subscription;
+  subscription = stdin
+      .transform(utf8.decoder)
+      .transform(new LineSplitter())
+      .listen((String line) {
+    // Unsubscribe after the first line.
+    subscription.cancel();
+  });
+}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
new file mode 100644
index 0000000..fa36a06
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_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.
+//
+// Process test program to test process communication.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:math';
+
+import "process_test_util.dart";
+
+void test(Future<Process> future, int expectedExitCode) {
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(expectedExitCode, exitCode);
+    });
+
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+    process.stdin.writeln("Line1");
+    process.stdin.flush().then((_) {
+      print("flush completed");
+    });
+  });
+}
+
+main() {
+  var scriptName = "process_stdin_transform_unsubscribe_script.dart";
+  var scriptFile = new File("tests/standalone_2/io/$scriptName");
+  if (!scriptFile.existsSync()) {
+    scriptFile = new File("../tests/standalone_2/io/$scriptName");
+  }
+  Expect.isTrue(scriptFile.existsSync());
+  test(
+      Process.start(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(scriptFile.path)),
+      0);
+}
diff --git a/tests/standalone/io/process_stdout_test.dart b/tests/standalone/io/process_stdout_test.dart
new file mode 100644
index 0000000..7d3bc7f
--- /dev/null
+++ b/tests/standalone/io/process_stdout_test.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.
+//
+// Process test program to test process communication.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:math';
+
+import "process_test_util.dart";
+
+void test(Future<Process> future, int expectedExitCode) {
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(expectedExitCode, exitCode);
+    });
+
+    List<int> input_data = "ABCDEFGHI\n".codeUnits;
+    final int input_dataSize = input_data.length;
+
+    int received = 0;
+    List<int> buffer = [];
+
+    void readData(List<int> data) {
+      buffer.addAll(data);
+      for (int i = received; i < min(data.length, buffer.length) - 1; i++) {
+        Expect.equals(data[i], buffer[i]);
+      }
+      received = buffer.length;
+      if (received >= input_dataSize) {
+        // We expect an extra character on windows due to carriage return.
+        if (13 == buffer[input_dataSize - 1] &&
+            input_dataSize + 1 == received) {
+          Expect.equals(13, buffer[input_dataSize - 1]);
+          Expect.equals(10, buffer[input_dataSize]);
+          buffer.removeLast();
+        }
+      }
+    }
+
+    process.stderr.listen((_) {});
+    process.stdin.add(input_data);
+    process.stdin.flush().then((_) => process.stdin.close());
+    process.stdout.listen(readData);
+  });
+}
+
+main() {
+  // Run the test using the process_test binary.
+  test(
+      Process.start(getProcessTestFileName(), const ["0", "1", "99", "0"]), 99);
+
+  // Run the test using the dart binary with an echo script.
+  // The test runner can be run from either the root or from runtime.
+  var scriptFile = new File("tests/standalone_2/io/process_std_io_script.dart");
+  if (!scriptFile.existsSync()) {
+    scriptFile =
+        new File("../tests/standalone_2/io/process_std_io_script.dart");
+  }
+  Expect.isTrue(scriptFile.existsSync());
+  test(
+      Process.start(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..addAll([scriptFile.path, "0"])),
+      0);
+}
diff --git a/tests/standalone/io/process_sync_script.dart b/tests/standalone/io/process_sync_script.dart
new file mode 100644
index 0000000..e89d1a9
--- /dev/null
+++ b/tests/standalone/io/process_sync_script.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.
+//
+// Utility script to generate some output on stdout and stderr.
+
+import "dart:async";
+import "dart:io";
+import "dart:math";
+
+main(List<String> arguments) {
+  var blockCount = int.parse(arguments[0]);
+  var stdoutBlockSize = int.parse(arguments[1]);
+  var stderrBlockSize = int.parse(arguments[2]);
+  var stdoutBlock =
+      new String.fromCharCodes(new List.filled(stdoutBlockSize, 65));
+  var stderrBlock =
+      new String.fromCharCodes(new List.filled(stderrBlockSize, 66));
+  for (int i = 0; i < blockCount; i++) {
+    stdout.write(stdoutBlock);
+    stderr.write(stderrBlock);
+  }
+  Future.wait([stdout.close(), stderr.close()]).then((_) {
+    exit(int.parse(arguments[3]));
+  });
+}
diff --git a/tests/standalone/io/process_sync_test.dart b/tests/standalone/io/process_sync_test.dart
new file mode 100644
index 0000000..02546ce
--- /dev/null
+++ b/tests/standalone/io/process_sync_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// OtherResources=process_sync_script.dart
+
+import "dart:io";
+import "package:expect/expect.dart";
+import 'package:path/path.dart';
+
+test(int blockCount, int stdoutBlockSize, int stderrBlockSize, int exitCode,
+    [int? nonWindowsExitCode]) {
+  // Get the Dart script file that generates output.
+  var scriptFile = new File(
+      Platform.script.resolve("process_sync_script.dart").toFilePath());
+  var args = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..addAll([
+      scriptFile.path,
+      blockCount.toString(),
+      stdoutBlockSize.toString(),
+      stderrBlockSize.toString(),
+      exitCode.toString()
+    ]);
+  ProcessResult syncResult = Process.runSync(Platform.executable, args);
+  Expect.equals(blockCount * stdoutBlockSize, syncResult.stdout.length);
+  Expect.equals(blockCount * stderrBlockSize, syncResult.stderr.length);
+  if (Platform.isWindows) {
+    Expect.equals(exitCode, syncResult.exitCode);
+  } else {
+    if (nonWindowsExitCode == null) {
+      Expect.equals(exitCode, syncResult.exitCode);
+    } else {
+      Expect.equals(nonWindowsExitCode, syncResult.exitCode);
+    }
+  }
+  Process.run(Platform.executable, args).then((asyncResult) {
+    Expect.equals(syncResult.stdout, asyncResult.stdout);
+    Expect.equals(syncResult.stderr, asyncResult.stderr);
+    Expect.equals(syncResult.exitCode, asyncResult.exitCode);
+  });
+}
+
+main() {
+  test(10, 10, 10, 0);
+  test(10, 100, 10, 0);
+  test(10, 10, 100, 0);
+  test(100, 1, 10, 0);
+  test(100, 10, 1, 0);
+  test(100, 1, 1, 0);
+  test(1, 100000, 100000, 0);
+
+  // The buffer size used in process.h.
+  var kBufferSize = 16 * 1024;
+  test(1, kBufferSize, kBufferSize, 0);
+  test(1, kBufferSize - 1, kBufferSize - 1, 0);
+  test(1, kBufferSize + 1, kBufferSize + 1, 0);
+
+  test(10, 10, 10, 1);
+  test(10, 10, 10, 255);
+  test(10, 10, 10, -1, 255);
+  test(10, 10, 10, -255, 1);
+}
diff --git a/tests/standalone/io/process_test_util.dart b/tests/standalone/io/process_test_util.dart
new file mode 100644
index 0000000..3def7a2
--- /dev/null
+++ b/tests/standalone/io/process_test_util.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.
+
+library process_test_util;
+
+import "dart:io";
+
+String getPlatformExecutableExtension() {
+  var os = Platform.operatingSystem;
+  if (os == 'windows') return '.exe';
+  return ''; // Linux and Mac OS.
+}
+
+String getProcessTestFileName() {
+  var extension = getPlatformExecutableExtension();
+  var executable = Platform.executable;
+  var dirIndex = executable.lastIndexOf('dart');
+  var buffer = new StringBuffer(executable.substring(0, dirIndex));
+  buffer.write('process_test$extension');
+  return buffer.toString();
+}
diff --git a/tests/standalone/io/process_working_directory_test.dart b/tests/standalone/io/process_working_directory_test.dart
new file mode 100644
index 0000000..9a3b8ee
--- /dev/null
+++ b/tests/standalone/io/process_working_directory_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.
+//
+// Process working directory test.
+
+library ProcessWorkingDirectoryTest;
+
+import "dart:io";
+import "package:expect/expect.dart";
+import "process_test_util.dart";
+
+class ProcessWorkingDirectoryTest {
+  static String get fullTestFilePath {
+    // Extract full path, since we run processes from another directory.
+    File path = new File(getProcessTestFileName());
+    Expect.isTrue(path.existsSync());
+    return path.resolveSymbolicLinksSync();
+  }
+
+  static void testValidDirectory() {
+    Directory directory =
+        Directory.systemTemp.createTempSync('dart_process_working_directory');
+    Expect.isTrue(directory.existsSync());
+
+    Process.start(fullTestFilePath, const ["0", "0", "99", "0"],
+            workingDirectory: directory.path)
+        .then((process) {
+      process.exitCode.then((int exitCode) {
+        Expect.equals(exitCode, 99);
+        directory.deleteSync();
+      });
+      process.stdout.listen((_) {});
+      process.stderr.listen((_) {});
+    }).catchError((error) {
+      directory.deleteSync();
+      Expect.fail("Couldn't start process");
+    });
+  }
+
+  static void testInvalidDirectory() {
+    Directory directory =
+        Directory.systemTemp.createTempSync('dart_process_working_directory');
+    Expect.isTrue(directory.existsSync());
+
+    Process.start(fullTestFilePath, const ["0", "0", "99", "0"],
+            workingDirectory: directory.path + "/subPath")
+        .then((process) {
+      Expect.fail("bad process completed");
+      directory.deleteSync();
+    }).catchError((e) {
+      Expect.isNotNull(e);
+      directory.deleteSync();
+    });
+  }
+}
+
+main() {
+  ProcessWorkingDirectoryTest.testValidDirectory();
+  ProcessWorkingDirectoryTest.testInvalidDirectory();
+}
diff --git a/tests/standalone/io/raw_datagram_read_all_test.dart b/tests/standalone/io/raw_datagram_read_all_test.dart
new file mode 100644
index 0000000..73d11c4
--- /dev/null
+++ b/tests/standalone/io/raw_datagram_read_all_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var address = InternetAddress.loopbackIPv4;
+  RawDatagramSocket.bind(address, 0).then((producer) {
+    RawDatagramSocket.bind(address, 0).then((receiver) {
+      int sent = 0;
+      new Timer.periodic(const Duration(microseconds: 1), (timer) {
+        producer.send([0], address, receiver.port);
+        sent++;
+        if (sent == 100) {
+          timer.cancel();
+          producer.close();
+        }
+      });
+      var timer;
+      receiver.listen((event) {
+        if (event != RawSocketEvent.read) return;
+        var datagram = receiver.receive()!;
+        Expect.listEquals([0], datagram.data);
+        if (timer != null) timer.cancel();
+        timer = new Timer(const Duration(milliseconds: 200), () {
+          Expect.isNull(receiver.receive());
+          receiver.close();
+          asyncEnd();
+        });
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone/io/raw_datagram_socket_test.dart
new file mode 100644
index 0000000..2585edd
--- /dev/null
+++ b/tests/standalone/io/raw_datagram_socket_test.dart
@@ -0,0 +1,422 @@
+// 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:io";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class FutureExpect {
+  static Future check(Future result, check) =>
+      result.then((value) => check(value));
+  static Future throws(Future result) => result.then((value) {
+        throw new ExpectException(
+            "FutureExpect.throws received $value instead of an exception");
+      }, onError: (_) => null);
+}
+
+testDatagramBroadcastOptions() {
+  test(address) {
+    asyncStart();
+    RawDatagramSocket.bind(address, 0).then((socket) {
+      Expect.isFalse(socket.broadcastEnabled);
+      socket.broadcastEnabled = true;
+      if (!Platform.isMacOS) {
+        Expect.isTrue(socket.broadcastEnabled);
+      }
+      socket.broadcastEnabled = false;
+      Expect.isFalse(socket.broadcastEnabled);
+      asyncEnd();
+    });
+  }
+
+  test(InternetAddress.loopbackIPv4);
+  test(InternetAddress.anyIPv4);
+}
+
+testDatagramMulticastOptions() {
+  test(address) {
+    asyncStart();
+    RawDatagramSocket.bind(address, 0).then((socket) {
+      Expect.isTrue(socket.multicastLoopback);
+      Expect.equals(1, socket.multicastHops);
+      Expect.throws(() => socket.multicastInterface);
+
+      socket.multicastLoopback = false;
+      socket.multicastHops = 4;
+      Expect.isFalse(socket.multicastLoopback);
+      Expect.equals(4, socket.multicastHops);
+      Expect.throws(() => socket.multicastInterface = null);
+
+      socket.multicastLoopback = true;
+      socket.multicastHops = 1;
+      Expect.isTrue(socket.multicastLoopback);
+      Expect.equals(1, socket.multicastHops);
+      Expect.throws(() => socket.multicastInterface);
+
+      asyncEnd();
+    });
+  }
+
+  test(InternetAddress.loopbackIPv4);
+  test(InternetAddress.anyIPv4);
+  test(InternetAddress.loopbackIPv6);
+  test(InternetAddress.anyIPv6);
+}
+
+testDatagramSocketReuseAddress() {
+  test(address, reuseAddress) {
+    asyncStart();
+    RawDatagramSocket.bind(address, 0,
+            reuseAddress: reuseAddress,
+            reusePort: Platform.isMacOS && reuseAddress)
+        .then((socket) {
+      if (reuseAddress) {
+        RawDatagramSocket.bind(address, socket.port,
+                reusePort: Platform.isMacOS)
+            .then((s) => Expect.isTrue(s is RawDatagramSocket))
+            .then(asyncSuccess);
+      } else {
+        FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
+            .then(asyncSuccess);
+      }
+    });
+  }
+
+  test(InternetAddress.loopbackIPv4, true);
+  test(InternetAddress.loopbackIPv4, false);
+  test(InternetAddress.loopbackIPv6, true);
+  test(InternetAddress.loopbackIPv6, false);
+}
+
+testDatagramSocketTtl() {
+  test(address, ttl, shouldSucceed) {
+    asyncStart();
+    if (shouldSucceed) {
+      RawDatagramSocket.bind(address, 0, ttl: ttl).then(asyncSuccess);
+    } else {
+      Expect.throws(() => RawDatagramSocket.bind(address, 0, ttl: ttl));
+      asyncEnd();
+    }
+  }
+
+  test(InternetAddress.loopbackIPv4, 1, true);
+  test(InternetAddress.loopbackIPv4, 255, true);
+  test(InternetAddress.loopbackIPv4, 256, false);
+  test(InternetAddress.loopbackIPv4, 0, false);
+  test(InternetAddress.loopbackIPv4, null, false);
+
+  test(InternetAddress.loopbackIPv6, 1, true);
+  test(InternetAddress.loopbackIPv6, 255, true);
+  test(InternetAddress.loopbackIPv6, 256, false);
+  test(InternetAddress.loopbackIPv6, 0, false);
+  test(InternetAddress.loopbackIPv6, null, false);
+}
+
+testDatagramSocketMulticastIf() {
+  test(address) async {
+    asyncStart();
+    final socket = await RawDatagramSocket.bind(address, 0);
+    RawSocketOption option;
+    late int idx;
+    if (address.type == InternetAddressType.IPv4) {
+      option = RawSocketOption(RawSocketOption.levelIPv4,
+          RawSocketOption.IPv4MulticastInterface, address.rawAddress);
+    } else {
+      if (!NetworkInterface.listSupported) {
+        asyncEnd();
+        return;
+      }
+      var interface = await NetworkInterface.list();
+      if (interface.length == 0) {
+        asyncEnd();
+        return;
+      }
+      idx = interface[0].index;
+      option = RawSocketOption.fromInt(RawSocketOption.levelIPv6,
+          RawSocketOption.IPv6MulticastInterface, idx);
+    }
+
+    socket.setRawOption(option);
+    final getResult = socket.getRawOption(option);
+
+    if (address.type == InternetAddressType.IPv4) {
+      Expect.listEquals(getResult, address.rawAddress);
+    } else {
+      // RawSocketOption.fromInt() will create a Uint8List(4).
+      Expect.equals(
+          getResult.buffer.asByteData().getUint32(0, Endian.host), idx);
+    }
+
+    asyncSuccess(socket);
+  }
+
+  test(InternetAddress.loopbackIPv4);
+  test(InternetAddress.anyIPv4);
+  test(InternetAddress.loopbackIPv6);
+  test(InternetAddress.anyIPv6);
+}
+
+testBroadcast() {
+  test(bindAddress, broadcastAddress, enabled) {
+    asyncStart();
+    Future.wait([
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)
+    ]).then((values) {
+      var broadcastTimer;
+      var sender = values[0];
+      var receiver = values[1];
+      // On Windows at least the receiver needs to have broadcast
+      // enabled whereas on Linux at least the sender needs to.
+      receiver.broadcastEnabled = enabled;
+      sender.broadcastEnabled = enabled;
+      receiver.listen((event) {
+        if (event == RawSocketEvent.read) {
+          Expect.isTrue(enabled);
+          sender.close();
+          receiver.close();
+          broadcastTimer.cancel();
+          asyncEnd();
+        }
+      });
+
+      int sendCount = 0;
+      send(_) {
+        int bytes =
+            sender.send(new Uint8List(1), broadcastAddress, receiver.port);
+        Expect.isTrue(bytes == 0 || bytes == 1);
+        sendCount++;
+        if (!enabled && sendCount == 50) {
+          sender.close();
+          receiver.close();
+          broadcastTimer.cancel();
+          asyncEnd();
+        }
+      }
+
+      broadcastTimer = new Timer.periodic(new Duration(milliseconds: 10), send);
+    });
+  }
+
+  var broadcast = new InternetAddress("255.255.255.255");
+  test(InternetAddress.anyIPv4, broadcast, false);
+  test(InternetAddress.anyIPv4, broadcast, true);
+}
+
+testLoopbackMulticast() {
+  test(bindAddress, multicastAddress, enabled) {
+    asyncStart();
+    Future.wait([
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)
+    ]).then((values) {
+      var senderTimer;
+      var sender = values[0];
+      var receiver = values[1];
+
+      sender.joinMulticast(multicastAddress);
+      receiver.joinMulticast(multicastAddress);
+      // On Windows at least the receiver needs to have multicast
+      // loop enabled whereas on Linux at least the sender needs to.
+      receiver.multicastLoopback = enabled;
+      sender.multicastLoopback = enabled;
+
+      receiver.listen((event) {
+        if (event == RawSocketEvent.read) {
+          if (!enabled) {
+            var data = receiver.receive()!;
+            print(data.port);
+            print(data.address);
+          }
+          Expect.isTrue(enabled);
+          sender.close();
+          receiver.close();
+          senderTimer.cancel();
+          asyncEnd();
+        }
+      });
+
+      int sendCount = 0;
+      send(_) {
+        int bytes =
+            sender.send(new Uint8List(1), multicastAddress, receiver.port);
+        Expect.isTrue(bytes == 0 || bytes == 1);
+        sendCount++;
+        if (!enabled && sendCount == 50) {
+          sender.close();
+          receiver.close();
+          senderTimer.cancel();
+          asyncEnd();
+        }
+      }
+
+      senderTimer = new Timer.periodic(new Duration(milliseconds: 10), send);
+    });
+  }
+
+  test(InternetAddress.anyIPv4, new InternetAddress("228.0.0.4"), true);
+  test(InternetAddress.anyIPv4, new InternetAddress("224.0.0.0"), false);
+  // TODO(30306): Reenable for Linux
+  if (!Platform.isMacOS && !Platform.isLinux) {
+    test(InternetAddress.anyIPv6, new InternetAddress("ff11::0"), true);
+    test(InternetAddress.anyIPv6, new InternetAddress("ff11::0"), false);
+  }
+}
+
+testLoopbackMulticastError() {
+  var bindAddress = InternetAddress.anyIPv4;
+  var multicastAddress = new InternetAddress("228.0.0.4");
+  asyncStart();
+  Future.wait([
+    RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+    RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)
+  ]).then((values) {
+    var sender = values[0];
+    var receiver = values[1];
+    Expect.throws(() {
+      sender.joinMulticast(new InternetAddress("127.0.0.1"));
+    }, (e) => e is! TypeError);
+    sender.close();
+    receiver.close();
+    asyncEnd();
+  });
+}
+
+testSendReceive(InternetAddress bindAddress, int dataSize) {
+  asyncStart();
+
+  var total = 1000;
+
+  int receivedSeq = 0;
+
+  var ackSeq = 0;
+  Timer? ackTimer;
+
+  Future.wait([
+    RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+    RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)
+  ]).then((values) {
+    var sender = values[0];
+    var receiver = values[1];
+    if (bindAddress.isMulticast) {
+      sender.multicastLoopback = true;
+      receiver.multicastLoopback = true;
+      sender.joinMulticast(bindAddress);
+      receiver.joinMulticast(bindAddress);
+    }
+
+    Uint8List createDataPackage(int seq) {
+      var data = new Uint8List(dataSize);
+      (new ByteData.view(data.buffer, 0, 4)).setUint32(0, seq);
+      return data;
+    }
+
+    Uint8List createAckPackage(int seq) {
+      var data = new Uint8List(4);
+      new ByteData.view(data.buffer, 0, 4).setUint32(0, seq);
+      return data;
+    }
+
+    int packageSeq(Datagram datagram) =>
+        new ByteData.view((datagram.data as Uint8List).buffer).getUint32(0);
+
+    void sendData(int seq) {
+      // Send a datagram acknowledging the received sequence.
+      int bytes =
+          sender.send(createDataPackage(seq), bindAddress, receiver.port);
+      Expect.isTrue(bytes == 0 || bytes == dataSize);
+    }
+
+    void sendAck(address, port) {
+      // Send a datagram acknowledging the received sequence.
+      int bytes = receiver.send(createAckPackage(receivedSeq), address, port);
+      Expect.isTrue(bytes == 0 || bytes == 4);
+      // Start a "long" timer for more data.
+      ackTimer?.cancel();
+      ackTimer = new Timer.periodic(
+          new Duration(milliseconds: 100), (_) => sendAck(address, port));
+    }
+
+    sender.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          var datagram = sender.receive();
+          if (datagram != null) {
+            Expect.equals(datagram.port, receiver.port);
+            if (!bindAddress.isMulticast) {
+              Expect.equals(receiver.address, datagram.address);
+            }
+            ackSeq = packageSeq(datagram);
+            if (ackSeq < total) {
+              sender.writeEventsEnabled = true;
+            } else {
+              sender.close();
+              receiver.close();
+              ackTimer?.cancel();
+              asyncEnd();
+            }
+          }
+          break;
+        case RawSocketEvent.write:
+          // Send the next package.
+          sendData(ackSeq + 1);
+          break;
+        case RawSocketEvent.closed:
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+
+    receiver.writeEventsEnabled = false;
+    receiver.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          var datagram = receiver.receive();
+          if (datagram != null) {
+            Expect.equals(datagram.port, sender.port);
+            Expect.equals(dataSize, datagram.data.length);
+            if (!bindAddress.isMulticast) {
+              Expect.equals(receiver.address, datagram.address);
+            }
+            var seq = packageSeq(datagram);
+            if (seq == receivedSeq + 1) {
+              receivedSeq = seq;
+              sendAck(bindAddress, sender.port);
+            }
+          }
+          break;
+        case RawSocketEvent.write:
+          throw "Unexpected.write";
+          break;
+        case RawSocketEvent.closed:
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+  });
+}
+
+main() {
+  testDatagramBroadcastOptions();
+  testDatagramMulticastOptions();
+  testDatagramSocketReuseAddress();
+  testDatagramSocketTtl();
+  testDatagramSocketMulticastIf();
+  testBroadcast();
+  testLoopbackMulticast();
+  testLoopbackMulticastError();
+  testSendReceive(InternetAddress.loopbackIPv4, 1000);
+  testSendReceive(InternetAddress.loopbackIPv6, 1000);
+  if (!Platform.isMacOS) {
+    testSendReceive(InternetAddress.loopbackIPv4, 32 * 1024);
+    testSendReceive(InternetAddress.loopbackIPv6, 32 * 1024);
+    testSendReceive(InternetAddress.loopbackIPv4, 64 * 1024 - 32);
+    testSendReceive(InternetAddress.loopbackIPv6, 64 * 1024 - 32);
+  }
+}
diff --git a/tests/standalone/io/raw_secure_server_closing_test.dart b/tests/standalone/io/raw_secure_server_closing_test.dart
new file mode 100644
index 0000000..46ae0ba
--- /dev/null
+++ b/tests/standalone/io/raw_secure_server_closing_test.dart
@@ -0,0 +1,173 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testCloseOneEnd(String toClose) {
+  asyncStart();
+  Completer serverDone = new Completer();
+  Completer serverEndDone = new Completer();
+  Completer clientEndDone = new Completer();
+  Future.wait([serverDone.future, serverEndDone.future, clientEndDone.future])
+      .then((_) {
+    asyncEnd();
+  });
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((serverConnection) {
+      serverConnection.listen((event) {
+        if (toClose == "server" || event == RawSocketEvent.readClosed) {
+          serverConnection.shutdown(SocketDirection.send);
+        }
+      }, onDone: () {
+        serverEndDone.complete(null);
+      });
+    }, onDone: () {
+      serverDone.complete(null);
+    });
+    RawSecureSocket.connect(HOST, server.port, context: clientContext)
+        .then((clientConnection) {
+      clientConnection.listen((event) {
+        if (toClose == "client" || event == RawSocketEvent.readClosed) {
+          clientConnection.shutdown(SocketDirection.send);
+        }
+      }, onDone: () {
+        clientEndDone.complete(null);
+        server.close();
+      });
+    });
+  });
+}
+
+void testCloseBothEnds() {
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext);
+    server.listen((serverEnd) {
+      clientEndFuture.then((clientEnd) {
+        clientEnd.close();
+        serverEnd.close();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+testPauseServerSocket() {
+  const int socketCount = 10;
+  var acceptCount = 0;
+  var resumed = false;
+
+  asyncStart();
+
+  RawSecureServerSocket.bind(HOST, 0, serverContext, backlog: 2 * socketCount)
+      .then((server) {
+    Expect.isTrue(server.port > 0);
+    var subscription;
+    subscription = server.listen((connection) {
+      Expect.isTrue(resumed);
+      connection.shutdown(SocketDirection.send);
+      if (++acceptCount == 2 * socketCount) {
+        server.close();
+        asyncEnd();
+      }
+    });
+
+    // Pause the server socket subscription and resume it after having
+    // connected a number client sockets. Then connect more client
+    // sockets.
+    subscription.pause();
+    var connectCount = 0;
+    for (int i = 0; i < socketCount; i++) {
+      RawSecureSocket.connect(HOST, server.port, context: clientContext)
+          .then((connection) {
+        connection.shutdown(SocketDirection.send);
+      });
+    }
+    new Timer(const Duration(milliseconds: 500), () {
+      subscription.resume();
+      resumed = true;
+      for (int i = 0; i < socketCount; i++) {
+        RawSecureSocket.connect(HOST, server.port, context: clientContext)
+            .then((connection) {
+          connection.shutdown(SocketDirection.send);
+        });
+      }
+    });
+  });
+}
+
+testCloseServer() {
+  const int socketCount = 3;
+  asyncStart();
+  List ends = [];
+
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Expect.isTrue(server.port > 0);
+    void checkDone() {
+      if (ends.length < 2 * socketCount) return;
+      for (var end in ends) {
+        end.close();
+      }
+      server.close();
+      asyncEnd();
+    }
+
+    server.listen((connection) {
+      ends.add(connection);
+      checkDone();
+    });
+
+    for (int i = 0; i < socketCount; i++) {
+      RawSecureSocket.connect(HOST, server.port, context: clientContext)
+          .then((connection) {
+        ends.add(connection);
+        checkDone();
+      });
+    }
+  });
+}
+
+main() {
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests();
+    asyncEnd();
+  });
+}
+
+runTests() {
+  testCloseOneEnd("client");
+  testCloseOneEnd("server");
+  testCloseBothEnds();
+  testCloseServer();
+  testPauseServerSocket();
+  // TODO(whesse): Add testPauseSocket from raw_socket_test.dart.
+  // TODO(whesse): Add testCancelResubscribeSocket from raw_socket_test.dart.
+}
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
new file mode 100644
index 0000000..87dda6a
--- /dev/null
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -0,0 +1,668 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=certificates/untrusted_server_chain.pem
+// OtherResources=certificates/untrusted_server_key.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testSimpleBind() {
+  print("asyncStart testSimpleBind");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    Expect.isTrue(s.port > 0);
+    s.close();
+    print("asyncEnd testSimpleBind");
+    asyncEnd();
+  });
+}
+
+void testInvalidBind() {
+  int count = 0;
+
+  // Bind to a unknown DNS name.
+  asyncStart();
+  print("asyncStart testInvalidBind");
+  RawSecureServerSocket.bind("ko.faar.__hest__", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    print("asyncEnd testInvalidBind");
+    asyncEnd();
+  });
+
+  // Bind to an unavaliable IP-address.
+  asyncStart();
+  print("asyncStart testInvalidBind 2");
+  RawSecureServerSocket.bind("8.8.8.8", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    print("asyncEnd testInvalidBind 2");
+    asyncEnd();
+  });
+
+  // Bind to a port already in use.
+  asyncStart();
+  print("asyncStart testInvalidBind 3");
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    RawSecureServerSocket.bind(HOST, s.port, serverContext).then((t) {
+      s.close();
+      t.close();
+      Expect.fail("Multiple listens on same port");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException);
+      s.close();
+      print("asyncEnd testInvalidBind 3");
+      asyncEnd();
+    });
+  });
+}
+
+void testSimpleConnect() {
+  print("asyncStart testSimpleConnect");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext);
+    server.listen((serverEnd) {
+      clientEndFuture.then((clientEnd) {
+        // TODO(whesse): Shutdown(SEND) not supported on secure sockets.
+        clientEnd.shutdown(SocketDirection.send);
+        serverEnd.shutdown(SocketDirection.send);
+        server.close();
+        print("asyncEnd testSimpleConnect");
+        asyncEnd();
+      });
+    });
+  });
+}
+
+int debugTestSimpleConnectFailCounter = 0;
+void testSimpleConnectFail(SecurityContext context, bool cancelOnError) {
+  var counter = debugTestSimpleConnectFailCounter++;
+  print("asyncStart testSimpleConnectFail $counter");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, context).then((server) {
+    Future<void> clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext)
+            .then((clientEnd) {
+      Expect.fail("No client connection expected.");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException || error is HandshakeException);
+    });
+    server.listen((serverEnd) {
+      Expect.fail("No server connection expected.");
+    }, onError: (error) {
+      Expect.isTrue(error is SocketException || error is HandshakeException);
+      clientEndFuture.then((_) {
+        if (!cancelOnError) server.close();
+        print("asyncEnd testSimpleConnectFail $counter");
+        asyncEnd();
+      });
+    }, cancelOnError: cancelOnError);
+  });
+}
+
+void testServerListenAfterConnect() {
+  print("asyncStart testServerListenAfterConnect");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Expect.isTrue(server.port > 0);
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext);
+    new Timer(const Duration(milliseconds: 500), () {
+      server.listen((serverEnd) {
+        clientEndFuture.then((clientEnd) {
+          clientEnd.shutdown(SocketDirection.send);
+          serverEnd.shutdown(SocketDirection.send);
+          server.close();
+          print("asyncEnd testServerListenAfterConnect");
+          asyncEnd();
+        });
+      });
+    });
+  });
+}
+
+// This test creates a server and a client connects. The client then
+// writes and the server echos. When the server has finished its echo
+// it half-closes. When the client gets the close event is closes
+// fully.
+//
+// The test can be run in different configurations based on
+// the boolean arguments:
+//
+// listenSecure
+// When this argument is true a secure server is used. When this is false
+// a non-secure server is used and the connections are secured after being
+// connected.
+//
+// connectSecure
+// When this argument is true a secure client connection is used. When this
+// is false a non-secure client connection is used and the connection is
+// secured after being connected.
+//
+// handshakeBeforeSecure
+// When this argument is true some initial clear text handshake is done
+// between client and server before the connection is secured. This argument
+// only makes sense when both listenSecure and connectSecure are false.
+//
+// postponeSecure
+// When this argument is false the securing of the server end will
+// happen as soon as the last byte of the handshake before securing
+// has been written. When this argument is true the securing of the
+// server will not happen until the first TLS handshake data has been
+// received from the client. This argument only takes effect when
+// handshakeBeforeSecure is true.
+void testSimpleReadWrite(
+    {required bool listenSecure,
+    required bool connectSecure,
+    required bool handshakeBeforeSecure,
+    required bool postponeSecure,
+    required bool dropReads}) {
+  int clientReads = 0;
+  int serverReads = 0;
+  if (handshakeBeforeSecure == true &&
+      (listenSecure == true || connectSecure == true)) {
+    Expect.fail("Invalid arguments to testSimpleReadWrite");
+  }
+
+  print("asyncStart testSimpleReadWrite($listenSecure, $connectSecure, "
+      "$handshakeBeforeSecure, $postponeSecure, $dropReads");
+  asyncStart();
+
+  const messageSize = 1000;
+  const handshakeMessageSize = 100;
+
+  List<int> createTestData() {
+    List<int> data = new List<int>.filled(messageSize, 0);
+    for (int i = 0; i < messageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  List<int> createHandshakeTestData() {
+    List<int> data = new List<int>.filled(handshakeMessageSize, 0);
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  void verifyTestData(List<int> data) {
+    Expect.equals(messageSize, data.length);
+    List<int> expected = createTestData();
+    for (int i = 0; i < messageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  void verifyHandshakeTestData(List<int> data) {
+    Expect.equals(handshakeMessageSize, data.length);
+    List<int> expected = createHandshakeTestData();
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  Future runServer(RawSocket client) {
+    var completer = new Completer();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> data = new List<int>.filled(messageSize, 0);
+    client.writeEventsEnabled = false;
+    var subscription;
+    subscription = client.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (dropReads) {
+            if (serverReads != 10) {
+              ++serverReads;
+              break;
+            } else {
+              serverReads = 0;
+            }
+          }
+          Expect.isTrue(bytesWritten == 0);
+          Expect.isTrue(client.available() > 0);
+          var buffer = client.read();
+          if (buffer != null) {
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            for (var value in buffer) {
+              Expect.isTrue(value is int);
+              Expect.isTrue(value < 256 && value >= 0);
+            }
+          }
+          if (bytesRead == data.length) {
+            verifyTestData(data);
+            client.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isFalse(client.writeEventsEnabled);
+          Expect.equals(bytesRead, data.length);
+          for (int i = bytesWritten; i < data.length; ++i) {
+            Expect.isTrue(data[i] is int);
+            Expect.isTrue(data[i] < 256 && data[i] >= 0);
+          }
+          bytesWritten +=
+              client.write(data, bytesWritten, data.length - bytesWritten);
+          if (bytesWritten < data.length) {
+            client.writeEventsEnabled = true;
+          }
+          if (bytesWritten == data.length) {
+            client.shutdown(SocketDirection.send);
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          completer.complete(null);
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<RawSocket> runClient(RawSocket socket) {
+    var completer = new Completer<RawSocket>();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> dataSent = createTestData();
+    List<int> dataReceived = new List<int>.filled(dataSent.length, 0);
+    socket.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          Expect.isTrue(socket.available() > 0);
+          if (dropReads) {
+            if (clientReads != 10) {
+              ++clientReads;
+              break;
+            } else {
+              clientReads = 0;
+            }
+          }
+          var buffer = socket.read();
+          if (buffer != null) {
+            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isTrue(bytesRead == 0);
+          Expect.isFalse(socket.writeEventsEnabled);
+          bytesWritten += socket.write(
+              dataSent, bytesWritten, dataSent.length - bytesWritten);
+          if (bytesWritten < dataSent.length) {
+            socket.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          verifyTestData(dataReceived);
+          completer.complete(socket);
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future runServerHandshake(RawSocket client) {
+    var completer = new Completer();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> data = new List<int>.filled(handshakeMessageSize, 0);
+    client.writeEventsEnabled = false;
+    var subscription;
+    subscription = client.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (bytesRead < data.length) {
+            Expect.isTrue(bytesWritten == 0);
+          }
+          Expect.isTrue(client.available() > 0);
+          if (dropReads) {
+            if (serverReads != 10) {
+              ++serverReads;
+              break;
+            } else {
+              serverReads = 0;
+            }
+          }
+          var buffer = client.read();
+          if (buffer != null) {
+            if (bytesRead == data.length) {
+              // Read first part of TLS handshake from client.
+              Expect.isTrue(postponeSecure);
+              completer.complete([subscription, buffer]);
+              client.readEventsEnabled = false;
+              return;
+            }
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            for (var value in buffer) {
+              Expect.isTrue(value is int);
+              Expect.isTrue(value < 256 && value >= 0);
+            }
+          }
+          if (bytesRead == data.length) {
+            verifyHandshakeTestData(data);
+            client.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isFalse(client.writeEventsEnabled);
+          Expect.equals(bytesRead, data.length);
+          for (int i = bytesWritten; i < data.length; ++i) {
+            Expect.isTrue(data[i] is int);
+            Expect.isTrue(data[i] < 256 && data[i] >= 0);
+          }
+          bytesWritten +=
+              client.write(data, bytesWritten, data.length - bytesWritten);
+          if (bytesWritten < data.length) {
+            client.writeEventsEnabled = true;
+          }
+          if (bytesWritten == data.length) {
+            if (!postponeSecure) {
+              completer.complete([subscription, null]);
+            }
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          Expect.fail("Unexpected close");
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<StreamSubscription<RawSocketEvent>> runClientHandshake(
+      RawSocket socket) {
+    var completer = new Completer<StreamSubscription<RawSocketEvent>>();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> dataSent = createHandshakeTestData();
+    List<int> dataReceived = new List<int>.filled(dataSent.length, 0);
+    var subscription;
+    subscription = socket.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (dropReads) {
+            if (clientReads != 10) {
+              ++clientReads;
+              break;
+            } else {
+              clientReads = 0;
+            }
+          }
+          Expect.isTrue(socket.available() > 0);
+          var buffer = socket.read();
+          if (buffer != null) {
+            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            if (bytesRead == dataSent.length) {
+              verifyHandshakeTestData(dataReceived);
+              completer.complete(subscription);
+            }
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isTrue(bytesRead == 0);
+          Expect.isFalse(socket.writeEventsEnabled);
+          bytesWritten += socket.write(
+              dataSent, bytesWritten, dataSent.length - bytesWritten);
+          if (bytesWritten < dataSent.length) {
+            socket.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          Expect.fail("Unexpected close");
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<RawSecureSocket> connectClient(int port) {
+    if (connectSecure) {
+      return RawSecureSocket.connect(HOST, port, context: clientContext);
+    } else if (!handshakeBeforeSecure) {
+      return RawSocket.connect(HOST, port).then((socket) {
+        return RawSecureSocket.secure(socket, context: clientContext);
+      });
+    } else {
+      return RawSocket.connect(HOST, port).then((socket) {
+        return runClientHandshake(socket).then((subscription) {
+          return RawSecureSocket.secure(socket,
+              context: clientContext, subscription: subscription);
+        });
+      });
+    }
+  }
+
+  serverReady(server) {
+    server.listen((client) {
+      if (listenSecure) {
+        runServer(client).then((_) => server.close());
+      } else if (!handshakeBeforeSecure) {
+        RawSecureSocket.secureServer(client, serverContext).then((client) {
+          runServer(client).then((_) => server.close());
+        });
+      } else {
+        runServerHandshake(client).then((secure) {
+          RawSecureSocket.secureServer(client, serverContext,
+                  subscription: secure[0], bufferedData: secure[1])
+              .then((client) {
+            runServer(client).then((_) => server.close());
+          });
+        });
+      }
+    });
+
+    connectClient(server.port).then(runClient).then((socket) {
+      socket.close();
+      print("asyncEnd testSimpleReadWrite($listenSecure, $connectSecure, "
+          "$handshakeBeforeSecure, $postponeSecure, $dropReads");
+      asyncEnd();
+    });
+  }
+
+  if (listenSecure) {
+    RawSecureServerSocket.bind(HOST, 0, serverContext).then(serverReady);
+  } else {
+    RawServerSocket.bind(HOST, 0).then(serverReady);
+  }
+}
+
+testPausedSecuringSubscription(bool pausedServer, bool pausedClient) {
+  print(
+      "asyncStart testPausedSecuringSubscription $pausedServer $pausedClient");
+  asyncStart();
+  var clientComplete = new Completer();
+  RawServerSocket.bind(HOST, 0).then((server) {
+    server.listen((client) {
+      var subscription;
+      subscription = client.listen((_) {
+        if (pausedServer) {
+          subscription.pause();
+        }
+        void done() {
+          server.close();
+          clientComplete.future.then((_) {
+            client.close();
+            print("asyncEnd testPausedSecuringSubscription "
+                "$pausedServer $pausedClient");
+            asyncEnd();
+          });
+        }
+
+        try {
+          RawSecureSocket.secureServer(client, serverContext,
+                  subscription: subscription)
+              .catchError((_) {})
+              .whenComplete(() {
+            if (pausedServer) {
+              Expect.fail("secureServer succeeded with paused subscription");
+            }
+            done();
+          });
+        } catch (e) {
+          if (!pausedServer) {
+            Expect.fail("secureServer failed with non-paused subscriptions");
+          }
+          if (pausedServer) {
+            Expect.isTrue(e is ArgumentError);
+          }
+          done();
+        }
+      });
+    });
+
+    RawSocket.connect(HOST, server.port).then((socket) {
+      var subscription;
+      subscription = socket.listen((_) {
+        if (pausedClient) {
+          subscription.pause();
+        }
+        try {
+          RawSecureSocket.secure(socket, subscription: subscription)
+              .catchError((_) {})
+              .whenComplete(() {
+            if (pausedClient) {
+              Expect.fail("secure succeeded with paused subscription");
+            }
+            socket.close();
+            clientComplete.complete(null);
+          });
+        } catch (e) {
+          if (!pausedClient) {
+            Expect.fail("secure failed with non-paused subscriptions ($e)");
+          }
+          if (pausedClient) {
+            Expect.isTrue(e is ArgumentError);
+          }
+          clientComplete.complete(null);
+        }
+      });
+    });
+  });
+}
+
+main() {
+  print("asyncStart main");
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests();
+    print("asyncEnd main");
+    asyncEnd();
+  });
+}
+
+runTests() {
+  testSimpleBind();
+  testInvalidBind();
+  testSimpleConnect();
+  SecurityContext context = new SecurityContext();
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  var chain = Platform.script
+      .resolve('certificates/untrusted_server_chain.pem')
+      .toFilePath();
+  context.useCertificateChain(chain);
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  var key = Platform.script
+      .resolve('certificates/untrusted_server_key.pem')
+      .toFilePath();
+  context.usePrivateKey(key, password: 'dartdart');
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  testServerListenAfterConnect();
+
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: false,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: true,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: true);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: true,
+      dropReads: true);
+  testPausedSecuringSubscription(false, false);
+  testPausedSecuringSubscription(true, false);
+  testPausedSecuringSubscription(false, true);
+  testPausedSecuringSubscription(true, true);
+}
diff --git a/tests/standalone/io/raw_secure_socket_pause_test.dart b/tests/standalone/io/raw_secure_socket_pause_test.dart
new file mode 100644
index 0000000..af43758
--- /dev/null
+++ b/tests/standalone/io/raw_secure_socket_pause_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+Future<HttpServer> startServer() {
+  return HttpServer.bindSecure("localhost", 0, serverContext, backlog: 5)
+      .then((server) {
+    server.listen((HttpRequest request) {
+      request.listen((_) {}, onDone: () {
+        request.response.contentLength = 100;
+        for (int i = 0; i < 10; i++) {
+          request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+        }
+        request.response.close();
+      });
+    });
+    return server;
+  });
+}
+
+main() async {
+  List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
+  int written = 0;
+  List<int> body = <int>[];
+  var server = await startServer();
+  var socket = await RawSecureSocket.connect("localhost", server.port,
+      context: clientContext);
+  late StreamSubscription subscription;
+  bool paused = false;
+  bool readEventsTested = false;
+  bool readEventsPaused = false;
+
+  void runPauseTest() {
+    subscription.pause();
+    paused = true;
+    new Timer(const Duration(milliseconds: 500), () {
+      paused = false;
+      subscription.resume();
+    });
+  }
+
+  void runReadEventTest() {
+    if (readEventsTested) return;
+    readEventsTested = true;
+    socket.readEventsEnabled = false;
+    readEventsPaused = true;
+    new Timer(const Duration(milliseconds: 500), () {
+      readEventsPaused = false;
+      socket.readEventsEnabled = true;
+    });
+  }
+
+  void handleRawEvent(RawSocketEvent event) {
+    Expect.isFalse(paused);
+    switch (event) {
+      case RawSocketEvent.read:
+        Expect.isFalse(readEventsPaused);
+        runReadEventTest();
+        body.addAll(socket.read()!);
+        break;
+      case RawSocketEvent.write:
+        written += socket.write(message, written, message.length - written);
+        if (written < message.length) {
+          socket.writeEventsEnabled = true;
+        } else {
+          socket.shutdown(SocketDirection.send);
+          runPauseTest();
+        }
+        break;
+      case RawSocketEvent.readClosed:
+        Expect.isTrue(body.length > 100);
+        Expect.equals(72, body.first);
+        Expect.equals(9, body.last);
+        server.close();
+        break;
+      default:
+        throw "Unexpected event $event";
+    }
+  }
+
+  subscription = socket.listen(handleRawEvent, onError: (e, trace) {
+    String msg = "onError handler of RawSecureSocket stream hit: $e";
+    if (trace != null) msg += "\nStackTrace: $trace";
+    Expect.fail(msg);
+  });
+}
diff --git a/tests/standalone/io/raw_secure_socket_test.dart b/tests/standalone/io/raw_secure_socket_test.dart
new file mode 100644
index 0000000..59ac869
--- /dev/null
+++ b/tests/standalone/io/raw_secure_socket_test.dart
@@ -0,0 +1,72 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+final SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+final SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+main() async {
+  List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
+  int written = 0;
+  List<int> body = <int>[];
+  var server =
+      await HttpServer.bindSecure("localhost", 0, serverContext, backlog: 5);
+  server.listen((HttpRequest request) async {
+    await request.drain();
+    request.response.contentLength = 100;
+    for (int i = 0; i < 10; i++) {
+      request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+    }
+    request.response.close();
+  });
+  var socket = await RawSecureSocket.connect("localhost", server.port,
+      context: clientContext);
+  socket.listen((RawSocketEvent event) {
+    switch (event) {
+      case RawSocketEvent.read:
+        body.addAll(socket.read()!);
+        break;
+      case RawSocketEvent.write:
+        written += socket.write(message, written, message.length - written);
+        if (written < message.length) {
+          socket.writeEventsEnabled = true;
+        } else {
+          socket.shutdown(SocketDirection.send);
+        }
+        break;
+      case RawSocketEvent.readClosed:
+        Expect.isTrue(body.length > 100, "$body\n${body.length}");
+        Expect.equals(72, body[0]);
+        Expect.equals(9, body[body.length - 1]);
+        server.close();
+        break;
+      default:
+        throw "Unexpected event $event";
+    }
+  }, onError: (e, trace) {
+    String msg = "onError handler of RawSecureSocket stream hit $e";
+    if (trace != null) msg += "\nStackTrace: $trace";
+    Expect.fail(msg);
+  });
+}
diff --git a/tests/standalone/io/raw_server_socket_cancel_test.dart b/tests/standalone/io/raw_server_socket_cancel_test.dart
new file mode 100644
index 0000000..ccdb93b
--- /dev/null
+++ b/tests/standalone/io/raw_server_socket_cancel_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testCancelResubscribeServerSocket(int socketCount, int backlog) {
+  var acceptCount = 0;
+  var doneCount = 0;
+  var errorCount = 0;
+  var earlyErrorCount = 0;
+
+  asyncStart();
+
+  RawServerSocket.bind("127.0.0.1", 0, backlog: backlog).then((server) {
+    Expect.isTrue(server.port > 0);
+
+    void checkDone() {
+      if (doneCount + errorCount + earlyErrorCount == socketCount) {
+        asyncEnd();
+        // Be sure to close as subscription.cancel may not be called, if
+        // backlog prevents acceptCount to grow to socketCount / 2.
+        server.close();
+      }
+    }
+
+    var subscription;
+    subscription = server.listen((client) {
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            client.read();
+            break;
+          case RawSocketEvent.readClosed:
+            client.shutdown(SocketDirection.send);
+            break;
+          case RawSocketEvent.write:
+            Expect.fail("No write event expected");
+            break;
+        }
+      });
+
+      if (++acceptCount == socketCount / 2) {
+        // Cancel subscription and then attempt to resubscribe.
+        subscription.cancel();
+        Timer.run(() {
+          Expect.throws(() {
+            server.listen((_) {
+              // Server socket is closed on cancel, so no more events.
+              Expect.fail("Event after closed through cancel");
+            });
+          });
+        });
+      }
+    });
+
+    // Connect a number of sockets.
+    for (int i = 0; i < socketCount; i++) {
+      RawSocket.connect("127.0.0.1", server.port).then((socket) {
+        bool done = false;
+        var subscription;
+        subscription = socket.listen((event) {
+          switch (event) {
+            case RawSocketEvent.read:
+              Expect.fail("No read event expected");
+              break;
+            case RawSocketEvent.readClosed:
+              done = true;
+              doneCount++;
+              checkDone();
+              break;
+            case RawSocketEvent.write:
+              // We don't care if this write succeeds, so we don't check
+              // the return value (number of bytes written).
+              socket.write([1, 2, 3]);
+              socket.shutdown(SocketDirection.send);
+              break;
+          }
+        }, onDone: () {
+          if (!done) {
+            doneCount++;
+            checkDone();
+          }
+        }, onError: (e) {
+          // "Connection reset by peer" errors are handled here.
+          errorCount++;
+          checkDone();
+        }, cancelOnError: true);
+      }).catchError((e) {
+        // "Connection actively refused by host" errors are handled here.
+        earlyErrorCount++;
+        checkDone();
+      });
+    }
+  });
+}
+
+void main() {
+  testCancelResubscribeServerSocket(10, 20);
+  testCancelResubscribeServerSocket(20, 5);
+}
diff --git a/tests/standalone/io/raw_socket_cross_process_test.dart b/tests/standalone/io/raw_socket_cross_process_test.dart
new file mode 100644
index 0000000..42ef338
--- /dev/null
+++ b/tests/standalone/io/raw_socket_cross_process_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:async';
+import 'dart:io';
+import "package:expect/expect.dart";
+
+const int serversCount = 10;
+
+void main(List<String> args) {
+  if (args.isEmpty) {
+    for (int i = 0; i < serversCount; ++i) {
+      makeServer().then((server) {
+        runClientProcess(server.port).then((_) => server.close());
+      });
+    }
+  } else if (args[0] == '--client') {
+    int port = int.parse(args[1]);
+    runClient(port);
+  } else {
+    Expect.fail('Unknown arguments to raw_socket_cross_process_test.dart');
+  }
+}
+
+Future makeServer() {
+  return RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((connection) {
+      connection.writeEventsEnabled = false;
+      connection.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.fail("No read event expected");
+            break;
+          case RawSocketEvent.readClosed:
+            connection.shutdown(SocketDirection.send);
+            break;
+          case RawSocketEvent.write:
+            Expect.fail("No write event expected");
+            break;
+        }
+      });
+    });
+    return server;
+  });
+}
+
+Future runClientProcess(int port) {
+  return Process.run(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(Platform.script.toFilePath())
+            ..add('--client')
+            ..add(port.toString()))
+      .then((ProcessResult result) {
+    if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
+      print("Client failed, exit code ${result.exitCode}");
+      print("  stdout:");
+      print(result.stdout);
+      print("  stderr:");
+      print(result.stderr);
+      Expect.fail('Client subprocess exit code: ${result.exitCode}');
+    }
+  });
+}
+
+runClient(int port) {
+  RawSocket.connect(InternetAddress.loopbackIPv4, port).then((connection) {
+    connection.listen((_) {}, onDone: () => print('SUCCESS'));
+    connection.shutdown(SocketDirection.send);
+  });
+}
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
new file mode 100644
index 0000000..8280094
--- /dev/null
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -0,0 +1,509 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testArguments() {
+  Expect.throws(() => RawServerSocket.bind("127.0.0.1", 65536));
+  Expect.throws(() => RawServerSocket.bind("127.0.0.1", -1));
+  Expect.throws(() => RawServerSocket.bind("127.0.0.1", 0, backlog: -1));
+}
+
+void testSimpleBind() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((s) {
+    Expect.isTrue(s.port > 0);
+    s.close();
+    asyncEnd();
+  });
+}
+
+void testInvalidBind() {
+  // Bind to a unknown DNS name.
+  asyncStart();
+  RawServerSocket.bind("ko.faar.__hest__", 0).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to an unavaliable IP-address.
+  asyncStart();
+  RawServerSocket.bind("8.8.8.8", 0).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to a port already in use.
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((s) {
+    RawServerSocket.bind(InternetAddress.loopbackIPv4, s.port).then((t) {
+      Expect.fail("Multiple listens on same port");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException);
+      s.close();
+      asyncEnd();
+    });
+  });
+}
+
+void testSimpleConnect() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((socket) {
+      socket.close();
+    });
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      server.close();
+      socket.close();
+      asyncEnd();
+    });
+  });
+}
+
+void testCancelConnect() {
+  asyncStart();
+  RawSocket.startConnect(InternetAddress.loopbackIPv4, 0).then(
+      (ConnectionTask<RawSocket> task) {
+    task.cancel();
+    task.socket.then((s) {
+      Expect.fail("Unreachable");
+    }, onError: (e) {
+      Expect.isTrue(e is SocketException);
+      asyncEnd();
+    });
+  }, onError: (e) {
+    Expect.fail("Unreachable");
+  });
+}
+
+void testCloseOneEnd(String toClose) {
+  asyncStart();
+  Completer serverDone = new Completer();
+  Completer serverEndDone = new Completer();
+  Completer clientEndDone = new Completer();
+  Future.wait([serverDone.future, serverEndDone.future, clientEndDone.future])
+      .then((_) {
+    asyncEnd();
+  });
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((serverConnection) {
+      serverConnection.listen((event) {
+        if (toClose == "server" || event == RawSocketEvent.readClosed) {
+          serverConnection.shutdown(SocketDirection.send);
+        }
+      }, onDone: () {
+        serverEndDone.complete(null);
+      });
+    }, onDone: () {
+      serverDone.complete(null);
+    });
+    RawSocket.connect("127.0.0.1", server.port).then((clientConnection) {
+      clientConnection.listen((event) {
+        if (toClose == "client" || event == RawSocketEvent.readClosed) {
+          clientConnection.shutdown(SocketDirection.send);
+        }
+      }, onDone: () {
+        clientEndDone.complete(null);
+        server.close();
+      });
+    });
+  });
+}
+
+void testServerListenAfterConnect() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    Expect.isTrue(server.port > 0);
+    RawSocket.connect("127.0.0.1", server.port).then((client) {
+      server.listen((socket) {
+        client.close();
+        server.close();
+        socket.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+void testSimpleReadWrite({required bool dropReads}) {
+  // This test creates a server and a client connects. The client then
+  // writes and the server echos. When the server has finished its
+  // echo it half-closes. When the client gets the close event is
+  // closes fully.
+  asyncStart();
+
+  const messageSize = 1000;
+  int serverReadCount = 0;
+  int clientReadCount = 0;
+
+  List<int> createTestData() {
+    return new List<int>.generate(messageSize, (index) => index & 0xff);
+  }
+
+  void verifyTestData(List<int> data) {
+    Expect.equals(messageSize, data.length);
+    List<int> expected = createTestData();
+    for (int i = 0; i < messageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      bool closedEventReceived = false;
+      List<int> data = new List<int>.filled(messageSize, 0);
+
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            if (dropReads) {
+              if (serverReadCount != 10) {
+                serverReadCount++;
+                break;
+              } else {
+                serverReadCount = 0;
+              }
+            }
+            Expect.isTrue(bytesWritten == 0);
+            Expect.isTrue(client.available() > 0);
+            var buffer = client.read(200)!;
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            if (bytesRead == data.length) {
+              verifyTestData(data);
+              client.writeEventsEnabled = true;
+            }
+            break;
+          case RawSocketEvent.write:
+            Expect.isFalse(client.writeEventsEnabled);
+            bytesWritten +=
+                client.write(data, bytesWritten, data.length - bytesWritten);
+            if (bytesWritten < data.length) {
+              client.writeEventsEnabled = true;
+            }
+            if (bytesWritten == data.length) {
+              client.shutdown(SocketDirection.send);
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            server.close();
+            break;
+          case RawSocketEvent.closed:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: () => Expect.isTrue(closedEventReceived));
+    });
+
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      bool closedEventReceived = false;
+      List<int> data = createTestData();
+
+      socket.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.isTrue(socket.available() > 0);
+            if (dropReads) {
+              if (clientReadCount != 10) {
+                clientReadCount++;
+                break;
+              } else {
+                clientReadCount = 0;
+              }
+            }
+            var buffer = socket.read()!;
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            break;
+          case RawSocketEvent.write:
+            Expect.isTrue(bytesRead == 0);
+            Expect.isFalse(socket.writeEventsEnabled);
+            bytesWritten +=
+                socket.write(data, bytesWritten, data.length - bytesWritten);
+            if (bytesWritten < data.length) {
+              socket.writeEventsEnabled = true;
+            } else {
+              data = new List<int>.filled(messageSize, 0);
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            verifyTestData(data);
+            socket.close();
+            break;
+          case RawSocketEvent.closed:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: () {
+        Expect.isTrue(closedEventReceived);
+        asyncEnd();
+      });
+    });
+  });
+}
+
+testPauseServerSocket() {
+  const int socketCount = 10;
+  var acceptCount = 0;
+  var resumed = false;
+
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    Expect.isTrue(server.port > 0);
+    var subscription = server.listen((socket) {
+      socket.close();
+      Expect.isTrue(resumed);
+      if (++acceptCount == socketCount) {
+        server.close();
+        asyncEnd();
+      }
+    });
+
+    // Pause the server socket subscription and resume it after having
+    // connected a number client sockets. Then connect more client
+    // sockets.
+    subscription.pause();
+    var connectCount = 0;
+    for (int i = 0; i < socketCount / 2; i++) {
+      RawSocket.connect("127.0.0.1", server.port).then((socket) {
+        if (++connectCount == socketCount / 2) {
+          subscription.resume();
+          resumed = true;
+          for (int i = connectCount; i < socketCount; i++) {
+            RawSocket.connect("127.0.0.1", server.port).then((socket) {
+              socket.close();
+            });
+          }
+        }
+        socket.close();
+      });
+    }
+  });
+}
+
+void testPauseSocket() {
+  const messageSize = 1000;
+  const loopCount = 10;
+  Completer connected = new Completer();
+  int pauseResumeCount = 0;
+  int bytesWritten = 0;
+  int bytesRead = 0;
+  var writeSubscription;
+  var readSubscription;
+
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    Expect.isTrue(server.port > 0);
+    server.listen((client) {
+      bool closedEventReceived = false;
+      List<int> data = new List<int>.filled(messageSize, 0);
+      writeSubscription = client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            throw "Unexpected read event";
+          case RawSocketEvent.write:
+            if (pauseResumeCount == loopCount) return;
+            Expect.isFalse(client.writeEventsEnabled);
+            Expect.equals(0, bytesRead); // Checks that reader is paused.
+            bytesWritten +=
+                client.write(data, bytesWritten, data.length - bytesWritten);
+            // Ensure all data is written. When done disable the write
+            // event and resume the receiver.
+            if (bytesWritten == data.length) {
+              writeSubscription.pause();
+              bytesWritten = 0;
+              connected.future.then((_) {
+                readSubscription.resume();
+              });
+            }
+            client.writeEventsEnabled = true;
+            break;
+          case RawSocketEvent.readClosed:
+            client.close();
+            server.close();
+            break;
+          case RawSocketEvent.closed:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: () => Expect.isTrue(closedEventReceived));
+    });
+
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      bool closedEventReceived = false;
+      socket.writeEventsEnabled = false;
+      readSubscription = socket.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.equals(0, bytesWritten); // Checks that writer is paused.
+            Expect.isTrue(socket.available() > 0);
+            var buffer = socket.read()!;
+            bytesRead += buffer.length;
+            // Ensure all data is read. When done pause and resume the sender
+            if (bytesRead == messageSize) {
+              if (++pauseResumeCount == loopCount) {
+                socket.close();
+                asyncEnd();
+              } else {
+                readSubscription.pause();
+              }
+              // Always resume writer as it needs the read closed
+              // event when done.
+              bytesRead = 0;
+              writeSubscription.resume();
+            }
+            break;
+          case RawSocketEvent.write:
+            throw "Unexpected write event";
+          case RawSocketEvent.readClosed:
+            throw "Unexpected read closed event";
+          case RawSocketEvent.closed:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: () => Expect.isTrue(closedEventReceived));
+      readSubscription.pause();
+      connected.complete(true);
+    });
+  });
+}
+
+void testSocketZone() {
+  asyncStart();
+  Expect.equals(Zone.root, Zone.current);
+  runZoned(() {
+    Expect.notEquals(Zone.root, Zone.current);
+    RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+      Expect.notEquals(Zone.root, Zone.current);
+      server.listen((socket) {
+        Expect.notEquals(Zone.root, Zone.current);
+        socket.close();
+        server.close();
+      });
+      RawSocket.connect("127.0.0.1", server.port).then((socket) {
+        socket.listen((event) {
+          if (event == RawSocketEvent.readClosed) {
+            socket.close();
+            asyncEnd();
+          }
+        });
+      });
+    });
+  });
+}
+
+void testSocketZoneError() {
+  asyncStart();
+  Expect.equals(Zone.root, Zone.current);
+  runZoned(() {
+    Expect.notEquals(Zone.root, Zone.current);
+    RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+      Expect.notEquals(Zone.root, Zone.current);
+      server.listen((socket) {
+        Expect.notEquals(Zone.root, Zone.current);
+        var timer;
+        void write() {
+          socket.write(const [0]);
+          timer = new Timer(const Duration(milliseconds: 5), write);
+        }
+
+        write();
+        socket.listen((_) {}, onError: (error) {
+          timer.cancel();
+          Expect.notEquals(Zone.root, Zone.current);
+          socket.close();
+          server.close();
+          throw error;
+        });
+      });
+      RawSocket.connect("127.0.0.1", server.port).then((socket) {
+        socket.close();
+      });
+    });
+  }, onError: (e) {
+    asyncEnd();
+  });
+}
+
+void testClosedError() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((socket) {
+      socket.close();
+    });
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      server.close();
+      socket.close();
+      Expect.throws(() => socket.remotePort, (e) => e is SocketException);
+      Expect.throws(() => socket.remoteAddress, (e) => e is SocketException);
+      asyncEnd();
+    });
+  });
+}
+
+void testClosedServer() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    int port = server.port;
+    server.close().then((_) {
+      RawSocket.connect(InternetAddress.loopbackIPv4, server.port).then((_) {
+        Expect.fail('Connecting to the closed server socket should fail');
+      }, onError: (e) {
+        Expect.isTrue(e is SocketException);
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  testArguments();
+  testSimpleBind();
+  testCloseOneEnd("client");
+  testCloseOneEnd("server");
+  testInvalidBind();
+  testSimpleConnect();
+  testCancelConnect();
+  testServerListenAfterConnect();
+  testSimpleReadWrite(dropReads: false);
+  testSimpleReadWrite(dropReads: true);
+  testPauseServerSocket();
+  testPauseSocket();
+  testSocketZone();
+  testSocketZoneError();
+  testClosedError();
+  testClosedServer();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/raw_socket_typed_data_test.dart b/tests/standalone/io/raw_socket_typed_data_test.dart
new file mode 100644
index 0000000..2321b75
--- /dev/null
+++ b/tests/standalone/io/raw_socket_typed_data_test.dart
@@ -0,0 +1,220 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+testOutOfRange() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.fail("No data expected");
+            break;
+          case RawSocketEvent.write:
+            break;
+          case RawSocketEvent.readClosed:
+            client.close();
+            server.close();
+            break;
+          case RawSocketEvent.closed:
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      });
+    });
+
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      socket.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            break;
+          case RawSocketEvent.write:
+            Expect.isFalse(socket.writeEventsEnabled);
+            var data;
+            data = new Uint16List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data = new Uint32List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data = new Uint64List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data = new Int16List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data[0] = -1;
+            Expect.throws(() => socket.write(data));
+            data = new Int32List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data[0] = -1;
+            Expect.throws(() => socket.write(data));
+            data = new Int64List(1);
+            data[0] = 256;
+            Expect.throws(() => socket.write(data));
+            data[0] = -1;
+            Expect.throws(() => socket.write(data));
+            Expect.throws(() => socket.write([-1]));
+            Expect.throws(() => socket.write([256]));
+            socket.close();
+            break;
+          case RawSocketEvent.readClosed:
+            break;
+          case RawSocketEvent.closed:
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: asyncEnd);
+    });
+  });
+}
+
+void testSimpleReadWrite() {
+  // This test creates a server and a client connects. The client then
+  // writes and the server echos. When the server has finished its
+  // echo it half-closes. When the client gets the close event is
+  // closes fully.
+  asyncStart();
+
+  // The test data to send is 5 times 256 bytes and 4 times 128
+  // bytes. This is all the legal byte values from the integer typed
+  // data.
+  const messageSize = 256 * 5 + 128 * 4;
+  var fillData128 = new List.generate(128, (index) => index);
+  var fillData256 = new List.generate(256, (index) => index);
+  List<List<int>> createTestData() {
+    return [
+      new Uint8List(256)..setAll(0, fillData256),
+      new Uint8ClampedList(256)..setAll(0, fillData256),
+      new Uint16List(256)..setAll(0, fillData256),
+      new Uint32List(256)..setAll(0, fillData256),
+      new Uint64List(256)..setAll(0, fillData256),
+      new Int8List(128)..setAll(0, fillData128),
+      new Int16List(128)..setAll(0, fillData128),
+      new Int32List(128)..setAll(0, fillData128),
+      new Int64List(128)..setAll(0, fillData128),
+    ];
+  }
+
+  void verifyTestData(List<int> data) {
+    var testData = createTestData();
+    var expected = [];
+    testData.forEach((list) => expected.addAll(list));
+    Expect.listEquals(expected, data);
+  }
+
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      int index = 0;
+      List<List<int>> data = createTestData();
+      List<int> received = new List<int>.filled(messageSize, 0);
+
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.isTrue(bytesWritten == 0);
+            Expect.isTrue(client.available() > 0);
+            var buffer = client.read()!;
+            received.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            if (bytesRead == messageSize) {
+              verifyTestData(received);
+              client.writeEventsEnabled = true;
+            }
+            break;
+          case RawSocketEvent.write:
+            Expect.isTrue(bytesRead == messageSize);
+            Expect.isFalse(client.writeEventsEnabled);
+            bytesWritten += client.write(
+                data[index], bytesWritten, data[index].length - bytesWritten);
+            if (bytesWritten < data[index].length) {
+              client.writeEventsEnabled = true;
+            } else {
+              index++;
+              bytesWritten = 0;
+              if (index < data.length) {
+                client.writeEventsEnabled = true;
+              } else {
+                client.shutdown(SocketDirection.send);
+              }
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            server.close();
+            break;
+          case RawSocketEvent.closed:
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      });
+    });
+
+    RawSocket.connect("127.0.0.1", server.port).then((socket) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      int index = 0;
+      List<List<int>> data = createTestData();
+      List<int> received = new List<int>.filled(messageSize, 0);
+
+      socket.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.isTrue(socket.available() > 0);
+            var buffer = socket.read()!;
+            received.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            break;
+          case RawSocketEvent.write:
+            Expect.isTrue(bytesRead == 0);
+            Expect.isFalse(socket.writeEventsEnabled);
+            bytesWritten += socket.write(
+                data[index], bytesWritten, data[index].length - bytesWritten);
+            if (bytesWritten < data[index].length) {
+              socket.writeEventsEnabled = true;
+            } else {
+              index++;
+              bytesWritten = 0;
+              if (index < data.length) {
+                socket.writeEventsEnabled = true;
+              }
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            verifyTestData(received);
+            socket.close();
+            break;
+          case RawSocketEvent.closed:
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: asyncEnd);
+    });
+  });
+}
+
+main() {
+  // testOutOfRange();
+  testSimpleReadWrite();
+}
diff --git a/tests/standalone/io/raw_socket_write_destroy_test.dart b/tests/standalone/io/raw_socket_write_destroy_test.dart
new file mode 100644
index 0000000..f257303
--- /dev/null
+++ b/tests/standalone/io/raw_socket_write_destroy_test.dart
@@ -0,0 +1,100 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "package:expect/expect.dart";
+
+const SERVER_ADDRESS = "127.0.0.1";
+
+void testWriteDestroyServer() {
+  int WROTE = 100000;
+  RawServerSocket.bind(SERVER_ADDRESS, 0).then((server) {
+    server.listen((socket) {
+      socket.writeEventsEnabled = false;
+
+      var buffer = new List.filled(WROTE, 0);
+      int offset = 0;
+      void write() {
+        int n = socket.write(buffer, offset, buffer.length - offset);
+        offset += n;
+        socket.writeEventsEnabled = true;
+      }
+
+      socket.listen((e) {
+        if (e == RawSocketEvent.write) {
+          if (offset == buffer.length) {
+            socket.close();
+          } else {
+            write();
+          }
+        }
+      });
+      write();
+    });
+    RawSocket.connect(SERVER_ADDRESS, server.port).then((socket) {
+      var bytes = 0;
+      socket.listen((e) {
+        if (e == RawSocketEvent.read) {
+          bytes += socket.read()!.length;
+        } else if (e == RawSocketEvent.readClosed) {
+          Expect.equals(WROTE, bytes);
+          socket.close();
+          server.close();
+        }
+      });
+    });
+  });
+}
+
+void testWriteDestroyClient() {
+  int WROTE = 100000;
+  RawServerSocket.bind(SERVER_ADDRESS, 0).then((server) {
+    server.listen((socket) {
+      var bytes = 0;
+      socket.listen((e) {
+        if (e == RawSocketEvent.read) {
+          bytes += socket.read()!.length;
+        } else if (e == RawSocketEvent.readClosed) {
+          Expect.equals(WROTE, bytes);
+          socket.close();
+          server.close();
+        }
+      });
+    });
+    RawSocket.connect(SERVER_ADDRESS, server.port).then((socket) {
+      socket.writeEventsEnabled = false;
+
+      var buffer = new List.filled(WROTE, 0);
+      int offset = 0;
+      void write() {
+        int n = socket.write(buffer, offset, buffer.length - offset);
+        offset += n;
+        socket.writeEventsEnabled = true;
+      }
+
+      socket.listen((e) {
+        if (e == RawSocketEvent.write) {
+          if (offset == buffer.length) {
+            socket.close();
+          } else {
+            write();
+          }
+        }
+      });
+      write();
+    });
+  });
+}
+
+void main() {
+  testWriteDestroyServer();
+  testWriteDestroyClient();
+}
diff --git a/tests/standalone/io/raw_synchronous_socket_test.dart b/tests/standalone/io/raw_synchronous_socket_test.dart
new file mode 100644
index 0000000..74a82f2
--- /dev/null
+++ b/tests/standalone/io/raw_synchronous_socket_test.dart
@@ -0,0 +1,482 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "dart:math";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+const String loopbackIPv4String = "127.0.0.1";
+
+void testArguments() {
+  Expect.throws(() => RawSynchronousSocket.connectSync(null, 0));
+  Expect.throws(
+      () => RawSynchronousSocket.connectSync(loopbackIPv4String, 65536));
+  Expect.throws(() => RawSynchronousSocket.connectSync(loopbackIPv4String, -1));
+}
+
+// The connection attempt happens on the main Dart thread and the OS timeout can
+// be arbitrarily long, causing timeout issues on the build bots. This isn't an
+// issue with the async sockets since the lookup for a connect call happens on
+// the IO service thread.
+/*
+void testInvalidConnect() {
+  // Connect to an unknown DNS name.
+  try {
+    var socket = RawSynchronousSocket.connectSync("ko.faar.__hest__", 0);
+    Expect.fail("Failure expected");
+  } catch (e) {
+    Expect.isTrue(e is SocketException);
+  }
+
+  // Connect to an unavaliable IP-address.
+  try {
+    var socket = RawSynchronousSocket.connectSync("1.2.3.4", 0);
+    Expect.fail("Failure expected");
+  } catch (e) {
+    Expect.isTrue(e is SocketException);
+  }
+}
+*/
+
+void testSimpleConnect() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    var socket =
+        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
+    server.listen((serverSocket) {
+      Expect.equals(socket.address, serverSocket.remoteAddress);
+      Expect.equals(socket.port, serverSocket.remotePort);
+      Expect.equals(socket.remoteAddress, server.address);
+      Expect.equals(socket.remotePort, server.port);
+      socket.closeSync();
+      server.close();
+      asyncEnd();
+    });
+  });
+}
+
+void testServerListenAfterConnect() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    Expect.isTrue(server.port > 0);
+    var client =
+        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
+    server.listen((socket) {
+      client.closeSync();
+      server.close();
+      socket.close();
+      asyncEnd();
+    });
+  });
+}
+
+const messageSize = 1000;
+// Configuration fields for the EchoServer.
+enum EchoServerTypes {
+  // Max accumulated connections to server before close. Defaults to 1.
+  CONNECTION_COUNT,
+  // Sets the range of the fields to check in the list generated by
+  // createTestData().
+  OFFSET_END,
+  OFFSET_START,
+  // The port used to communicate with an isolate.
+  ISOLATE_SEND_PORT,
+  // The port of the newly created echo server.
+  SERVER_PORT
+}
+
+List<int> createTestData() {
+  return new List<int>.generate(messageSize, (index) => index & 0xff);
+}
+
+// Consumes data generated by a test and compares it against the original test
+// data. The optional fields, start and end, are used to compare against
+// segments of the original test data list. In other words, data.length == (end
+// - start).
+void verifyTestData(List<int> data, [int start = 0, int? end]) {
+  assert(data != null);
+  List<int> expected = createTestData();
+  if (end == null) {
+    end = data.length;
+  }
+  end = min(messageSize, end);
+  Expect.equals(end - start, data.length);
+  for (int i = 0; i < (end - start); i++) {
+    Expect.equals(expected[start + i], data[i]);
+  }
+}
+
+// The echo server is spawned in a new isolate and is used to test various
+// synchronous read/write operations by echoing any data received back to the
+// sender. The server should shutdown automatically after a specified number of
+// socket disconnections (default: 1).
+Future echoServer(var sendPort) async {
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) async {
+    ReceivePort receivePort = new ReceivePort();
+    Map response = {
+      EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
+      EchoServerTypes.SERVER_PORT: server.port
+    };
+    sendPort.send(response);
+    Map limits = await receivePort.first;
+    int start = limits[EchoServerTypes.OFFSET_START];
+    int end = limits[EchoServerTypes.OFFSET_END];
+    int length = end - start;
+    int connection_count = limits[EchoServerTypes.CONNECTION_COUNT] ?? 1;
+    int connections = 0;
+    sendPort = limits[EchoServerTypes.ISOLATE_SEND_PORT];
+    server.listen((client) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      bool closedEventReceived = false;
+      List<int> data = new List<int>.filled(length, 0);
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.isTrue(bytesWritten == 0);
+            Expect.isTrue(client.available() > 0);
+            var buffer = client.read(client.available())!;
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            // Once we've read all the data, we can echo it back. Otherwise,
+            // keep waiting for more bytes.
+            if (bytesRead >= length) {
+              verifyTestData(data, start, end);
+              client.writeEventsEnabled = true;
+            }
+            break;
+          case RawSocketEvent.write:
+            Expect.isFalse(client.writeEventsEnabled);
+            bytesWritten +=
+                client.write(data, bytesWritten, data.length - bytesWritten);
+            if (bytesWritten < length) {
+              client.writeEventsEnabled = true;
+            } else if (bytesWritten == length) {
+              // Close the socket for writing from the server since we're done
+              // writing to this socket. The connection is closed completely
+              // after the client closes the socket for reading from the server.
+              client.shutdown(SocketDirection.send);
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            client.close();
+            break;
+          case RawSocketEvent.closed:
+            Expect.isFalse(closedEventReceived);
+            closedEventReceived = true;
+            break;
+          default:
+            throw "Unexpected event $event";
+        }
+      }, onDone: () {
+        Expect.isTrue(closedEventReceived);
+        connections++;
+        if (connections >= connection_count) {
+          server.close();
+        }
+      });
+    }, onDone: () {
+      // Let the client know we're shutting down then kill the isolate.
+      sendPort.send(null);
+      Isolate.current.kill();
+    });
+  });
+}
+
+Future testSimpleReadWrite({bool? dropReads}) async {
+  asyncStart();
+  // This test creates a server and a client connects. The client writes data
+  // to the socket and the server echos it back. The client confirms the data it
+  // reads is the same as the data sent, then closes the socket, resulting in
+  // the closing of the server, which responds on receivePort with null to
+  // specify the echo server isolate is about to be killed. If an error occurs
+  // in the echo server, the exception and stack trace are sent to receivePort,
+  // which prints the exception and stack trace before eventually throwing an
+  // error.
+  ReceivePort receivePort = new ReceivePort();
+  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
+
+  Map response = await receivePort.first;
+  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
+  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
+
+  receivePort = new ReceivePort();
+  echo.addErrorListener(receivePort.sendPort);
+
+  Map limits = {
+    EchoServerTypes.OFFSET_START: 0,
+    EchoServerTypes.OFFSET_END: messageSize,
+    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
+  };
+  sendPort.send(limits);
+
+  try {
+    var socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+    List<int> data = createTestData();
+    socket.writeFromSync(data);
+    List<int> result = socket.readSync(data.length)!;
+    verifyTestData(result);
+    socket.shutdown(SocketDirection.send);
+    socket.closeSync();
+  } catch (e, stack) {
+    print("Echo test failed in the client");
+    rethrow;
+  }
+  // Wait for the server to shutdown before finishing the test.
+  var result = await receivePort.first;
+  if (result != null) {
+    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
+        " ${result[1]}";
+  }
+  asyncEnd();
+}
+
+Future testPartialRead() async {
+  asyncStart();
+  // This test is based on testSimpleReadWrite, but instead of reading the
+  // entire echoed message at once, it reads it in two calls to readIntoSync.
+  ReceivePort receivePort = new ReceivePort();
+  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
+
+  Map response = await receivePort.first;
+  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
+  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
+  List<int> data = createTestData();
+
+  receivePort = new ReceivePort();
+  echo.addErrorListener(receivePort.sendPort);
+
+  Map limits = {
+    EchoServerTypes.OFFSET_START: 0,
+    EchoServerTypes.OFFSET_END: 1000,
+    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
+  };
+  sendPort.send(limits);
+
+  try {
+    var socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+    int half_length = (data.length / 2).toInt();
+
+    // Send the full data list to the server.
+    socket.writeFromSync(data);
+    List<int> result = new List<int>.filled(data.length, 0);
+
+    // Read half at a time and check that there's still more bytes available.
+    socket.readIntoSync(result, 0, half_length);
+    verifyTestData(result.sublist(0, half_length), 0, half_length);
+    Expect.isTrue(socket.available() == (data.length - half_length));
+
+    // Read the second half and verify again.
+    socket.readIntoSync(result, half_length);
+    verifyTestData(result);
+    Expect.isTrue(socket.available() == 0);
+
+    socket.closeSync();
+  } catch (e, stack) {
+    print("Echo test failed in the client.");
+    rethrow;
+  }
+  // Wait for the server to shutdown before finishing the test.
+  var result = await receivePort.first;
+  if (result != null) {
+    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
+        " ${result[1]}";
+  }
+  asyncEnd();
+}
+
+Future testPartialWrite() async {
+  asyncStart();
+  // This test is based on testSimpleReadWrite, but instead of writing the
+  // entire data buffer at once, it writes different parts of the buffer over
+  // multiple calls to writeFromSync.
+  ReceivePort receivePort = new ReceivePort();
+  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
+
+  Map response = await receivePort.first;
+  List<int> data = createTestData();
+  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
+  int startOffset = 32;
+  int endOffset = (data.length / 2).toInt();
+  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
+
+  receivePort = new ReceivePort();
+  echo.addErrorListener(receivePort.sendPort);
+
+  Map limits = {
+    EchoServerTypes.OFFSET_START: startOffset,
+    EchoServerTypes.OFFSET_END: endOffset,
+    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
+  };
+  sendPort.send(limits);
+  try {
+    var socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+    List<int> data = createTestData();
+
+    // Write a subset of data to the server.
+    socket.writeFromSync(data, startOffset, endOffset);
+
+    // Grab the response and verify it's correct.
+    List<int> result = new List<int>.filled(endOffset - startOffset, 0);
+    socket.readIntoSync(result);
+
+    Expect.equals(result.length, endOffset - startOffset);
+    verifyTestData(result, startOffset, endOffset);
+    socket.closeSync();
+  } catch (e, stack) {
+    print("Echo test failed in the client.");
+    rethrow;
+  }
+
+  // Wait for the server to shutdown before finishing the test.
+  var result = await receivePort.first;
+  if (result != null) {
+    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
+        " ${result[1]}";
+  }
+  asyncEnd();
+}
+
+Future testShutdown() async {
+  asyncStart();
+  // This test creates a server and a client connects. The client then tries to
+  // perform various operations after being shutdown in a specific direction, to
+  // ensure reads or writes cannot be performed if the socket has been shutdown
+  // for reading or writing.
+  ReceivePort receivePort = new ReceivePort();
+  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);
+
+  Map response = await receivePort.first;
+  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
+  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
+  List<int> data = createTestData();
+
+  receivePort = new ReceivePort();
+  echo.addErrorListener(receivePort.sendPort);
+
+  Map limits = {
+    EchoServerTypes.OFFSET_START: 0,
+    EchoServerTypes.OFFSET_END: data.length,
+    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
+    // Tell the server to shutdown after 3 sockets disconnect.
+    EchoServerTypes.CONNECTION_COUNT: 3
+  };
+  sendPort.send(limits);
+
+  try {
+    var socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+
+    // Close from both directions. Shouldn't be able to read/write to the
+    // socket.
+    socket.shutdown(SocketDirection.both);
+    Expect.throws(
+        () => socket.writeFromSync(data), (e) => e is SocketException);
+    Expect.throws(
+        () => socket.readSync(data.length), (e) => e is SocketException);
+    socket.closeSync();
+
+    // Close the socket for reading then try and perform a read. This should
+    // cause a SocketException.
+    socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+    socket.shutdown(SocketDirection.receive);
+    // Throws exception when the socket is closed for RECEIVE.
+    Expect.throws(
+        () => socket.readSync(data.length), (e) => e is SocketException);
+    socket.closeSync();
+
+    // Close the socket for writing and try to do a write. This should cause an
+    // OSError to be throw as the pipe is closed for writing.
+    socket = RawSynchronousSocket.connectSync(
+        loopbackIPv4String, serverInternetPort);
+    socket.shutdown(SocketDirection.send);
+    Expect.throws(
+        () => socket.writeFromSync(data), (e) => e is SocketException);
+    socket.closeSync();
+  } catch (e, stack) {
+    print("Echo test failed in client.");
+    rethrow;
+  }
+  // Wait for the server to shutdown before finishing the test.
+  var result = await receivePort.first;
+  if (result != null) {
+    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
+        " ${result[1]}";
+  }
+  asyncEnd();
+}
+
+Future testInvalidReadWriteOperations() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((socket) {});
+    List<int> data = createTestData();
+    var socket =
+        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
+
+    // Invalid writeFromSync invocations
+    Expect.throwsRangeError(() => socket.writeFromSync(data, data.length + 1));
+    Expect.throwsRangeError(
+        () => socket.writeFromSync(data, 0, data.length + 1));
+    Expect.throwsRangeError(() => socket.writeFromSync(data, 1, 0));
+
+    // Invalid readIntoSync invocations
+    List<int> buffer = new List<int>.filled(10, 0);
+    Expect.throwsRangeError(
+        () => socket.readIntoSync(buffer, buffer.length + 1));
+    Expect.throwsRangeError(
+        () => socket.readIntoSync(buffer, 0, buffer.length + 1));
+    Expect.throwsRangeError(() => socket.readIntoSync(buffer, 1, 0));
+
+    // Invalid readSync invocation
+    Expect.throwsArgumentError(() => socket.readSync(-1));
+
+    server.close();
+    socket.closeSync();
+    asyncEnd();
+  });
+}
+
+void testClosedError() {
+  asyncStart();
+  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((socket) {
+      socket.close();
+    });
+    var socket =
+        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
+    server.close();
+    socket.closeSync();
+    Expect.throws(() => socket.remotePort, (e) => e is SocketException);
+    Expect.throws(() => socket.remoteAddress, (e) => e is SocketException);
+    asyncEnd();
+  });
+}
+
+main() async {
+  asyncStart();
+  testArguments();
+  // testInvalidConnect(); Long timeout for bad lookups, so disable for bots.
+  await testShutdown();
+  testSimpleConnect();
+  testServerListenAfterConnect();
+  await testSimpleReadWrite();
+  await testPartialRead();
+  await testPartialWrite();
+  testInvalidReadWriteOperations();
+  testClosedError();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/read_as_text.dat b/tests/standalone/io/read_as_text.dat
new file mode 100644
index 0000000..db2cce6
--- /dev/null
+++ b/tests/standalone/io/read_as_text.dat
@@ -0,0 +1 @@
+λx. x
diff --git a/tests/standalone/io/read_into_const_list_test.dart b/tests/standalone/io/read_into_const_list_test.dart
new file mode 100644
index 0000000..14f1d8f
--- /dev/null
+++ b/tests/standalone/io/read_into_const_list_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.
+//
+// OtherResources=readline_test1.dat
+
+// Regression test for missing immutability check in the ListSet
+// methods in the API. This allowed overwriting const Lists.
+
+import "package:expect/expect.dart";
+import "dart:io";
+
+String getFilename(String path) {
+  return Platform.script.resolve(path).toFilePath();
+}
+
+void main() {
+  var a = const [0];
+  var b = const [0];
+  Expect.identical(a, b);
+
+  String filename = getFilename("readline_test1.dat");
+  File file = new File(filename);
+  file.open().then((input) {
+    Expect.throwsUnsupportedError(() => input.readIntoSync(a, 0, 1));
+    Expect.equals(0, a[0]);
+    Expect.equals(0, b[0]);
+    input.closeSync();
+  });
+}
diff --git a/tests/standalone/io/readline_test1.dat b/tests/standalone/io/readline_test1.dat
new file mode 100644
index 0000000..cfbbd08
--- /dev/null
+++ b/tests/standalone/io/readline_test1.dat
@@ -0,0 +1,10 @@
+# Test file with 10 lines and terminating line feed
+#
+Line 3
+Line 4
+Line 5
+Line 6
+Line 7
+Line 8
+Line 9
+Line 10
diff --git a/tests/standalone/io/readline_test2.dat b/tests/standalone/io/readline_test2.dat
new file mode 100644
index 0000000..784dee2
--- /dev/null
+++ b/tests/standalone/io/readline_test2.dat
@@ -0,0 +1,10 @@
+# Test file with 10 lines without terminating line feed
+#
+Line 3
+Line 4
+Line 5
+Line 6
+Line 7
+Line 8
+Line 9
+Line 10
\ No newline at end of file
diff --git a/tests/standalone/io/readuntil_test.dat b/tests/standalone/io/readuntil_test.dat
new file mode 100644
index 0000000..aa117d2
--- /dev/null
+++ b/tests/standalone/io/readuntil_test.dat
@@ -0,0 +1,2 @@
+Hello Dart
+wassup!
diff --git a/tests/standalone/io/regress_10026_test.dart b/tests/standalone/io/regress_10026_test.dart
new file mode 100644
index 0000000..4641327
--- /dev/null
+++ b/tests/standalone/io/regress_10026_test.dart
@@ -0,0 +1,701 @@
+// 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:convert';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testZLibInflate_regress10026() {
+  test(data, expect) {
+    asyncStart();
+    var controller = new StreamController(sync: true);
+    controller.stream
+        .transform(zlib.decoder)
+        .transform(utf8.decoder)
+        .fold<StringBuffer>(new StringBuffer(), (buffer, s) {
+      buffer.write(s);
+      return buffer;
+    }).then((out) {
+      Expect.equals(out.toString(), expect);
+      asyncEnd();
+    });
+    controller.add(data);
+    controller.close();
+  }
+
+  // Generated by using 'gzip -c | od -v -tu1 -An -w12' and adding commas.
+  test([
+    31,
+    139,
+    8,
+    8,
+    238,
+    42,
+    167,
+    81,
+    0,
+    3,
+    116,
+    101,
+    120,
+    116,
+    46,
+    116,
+    120,
+    116,
+    0,
+    125,
+    84,
+    79,
+    175,
+    147,
+    64,
+    16,
+    63,
+    183,
+    159,
+    98,
+    196,
+    139,
+    38,
+    165,
+    244,
+    249,
+    212,
+    52,
+    20,
+    136,
+    70,
+    77,
+    188,
+    168,
+    7,
+    189,
+    120,
+    156,
+    178,
+    67,
+    153,
+    20,
+    118,
+    113,
+    119,
+    161,
+    109,
+    140,
+    223,
+    221,
+    97,
+    105,
+    251,
+    170,
+    47,
+    154,
+    54,
+    41,
+    51,
+    195,
+    254,
+    254,
+    49,
+    52,
+    123,
+    162,
+    76,
+    233,
+    79,
+    29,
+    65,
+    237,
+    219,
+    166,
+    152,
+    103,
+    151,
+    31,
+    66,
+    85,
+    204,
+    103,
+    153,
+    103,
+    223,
+    80,
+    241,
+    225,
+    136,
+    109,
+    215,
+    16,
+    188,
+    55,
+    45,
+    178,
+    206,
+    146,
+    169,
+    59,
+    151,
+    121,
+    75,
+    30,
+    161,
+    172,
+    209,
+    58,
+    242,
+    121,
+    212,
+    251,
+    42,
+    94,
+    71,
+    144,
+    20,
+    151,
+    73,
+    237,
+    125,
+    23,
+    211,
+    143,
+    158,
+    135,
+    60,
+    122,
+    103,
+    180,
+    39,
+    237,
+    227,
+    145,
+    45,
+    130,
+    114,
+    170,
+    242,
+    200,
+    211,
+    209,
+    39,
+    35,
+    235,
+    230,
+    138,
+    243,
+    8,
+    70,
+    99,
+    75,
+    121,
+    52,
+    48,
+    29,
+    58,
+    99,
+    253,
+    205,
+    225,
+    3,
+    43,
+    95,
+    231,
+    138,
+    6,
+    46,
+    41,
+    14,
+    197,
+    2,
+    88,
+    179,
+    103,
+    108,
+    98,
+    87,
+    98,
+    67,
+    249,
+    221,
+    25,
+    199,
+    249,
+    147,
+    24,
+    24,
+    185,
+    207,
+    148,
+    165,
+    115,
+    145,
+    12,
+    182,
+    70,
+    157,
+    224,
+    231,
+    124,
+    54,
+    219,
+    98,
+    185,
+    223,
+    89,
+    211,
+    107,
+    21,
+    151,
+    166,
+    49,
+    54,
+    133,
+    167,
+    213,
+    74,
+    62,
+    47,
+    54,
+    50,
+    108,
+    209,
+    238,
+    88,
+    167,
+    176,
+    26,
+    139,
+    14,
+    149,
+    98,
+    189,
+    59,
+    87,
+    149,
+    104,
+    137,
+    43,
+    108,
+    185,
+    57,
+    165,
+    16,
+    125,
+    233,
+    72,
+    195,
+    87,
+    212,
+    46,
+    90,
+    64,
+    244,
+    145,
+    154,
+    129,
+    60,
+    151,
+    8,
+    159,
+    169,
+    39,
+    233,
+    92,
+    27,
+    11,
+    120,
+    107,
+    69,
+    227,
+    2,
+    156,
+    220,
+    26,
+    59,
+    178,
+    92,
+    109,
+    36,
+    206,
+    95,
+    243,
+    153,
+    226,
+    33,
+    200,
+    9,
+    102,
+    82,
+    120,
+    189,
+    90,
+    117,
+    199,
+    91,
+    5,
+    175,
+    168,
+    5,
+    236,
+    189,
+    249,
+    67,
+    200,
+    61,
+    181,
+    155,
+    127,
+    88,
+    168,
+    170,
+    48,
+    49,
+    86,
+    145,
+    141,
+    45,
+    42,
+    238,
+    93,
+    10,
+    119,
+    225,
+    126,
+    97,
+    195,
+    180,
+    97,
+    189,
+    95,
+    0,
+    166,
+    3,
+    59,
+    246,
+    164,
+    2,
+    247,
+    229,
+    240,
+    253,
+    250,
+    229,
+    122,
+    29,
+    206,
+    143,
+    137,
+    197,
+    138,
+    74,
+    99,
+    209,
+    179,
+    17,
+    25,
+    218,
+    104,
+    154,
+    32,
+    222,
+    180,
+    164,
+    24,
+    225,
+    89,
+    139,
+    199,
+    248,
+    86,
+    244,
+    243,
+    41,
+    213,
+    75,
+    188,
+    255,
+    17,
+    39,
+    32,
+    87,
+    219,
+    23,
+    223,
+    23,
+    139,
+    15,
+    201,
+    63,
+    180,
+    254,
+    50,
+    19,
+    158,
+    194,
+    67,
+    22,
+    147,
+    183,
+    17,
+    84,
+    190,
+    89,
+    18,
+    158,
+    187,
+    44,
+    116,
+    50,
+    109,
+    244,
+    60,
+    27,
+    21,
+    73,
+    45,
+    132,
+    227,
+    90,
+    212,
+    119,
+    143,
+    150,
+    91,
+    90,
+    50,
+    232,
+    138,
+    111,
+    53,
+    59,
+    80,
+    161,
+    9,
+    114,
+    69,
+    206,
+    227,
+    182,
+    97,
+    87,
+    75,
+    72,
+    222,
+    192,
+    150,
+    160,
+    119,
+    114,
+    89,
+    25,
+    11,
+    220,
+    52,
+    189,
+    243,
+    99,
+    52,
+    3,
+    1,
+    77,
+    112,
+    78,
+    246,
+    80,
+    78,
+    151,
+    125,
+    43,
+    139,
+    234,
+    150,
+    240,
+    221,
+    244,
+    82,
+    74,
+    110,
+    30,
+    52,
+    5,
+    136,
+    16,
+    180,
+    88,
+    97,
+    141,
+    158,
+    64,
+    96,
+    208,
+    237,
+    3,
+    92,
+    71,
+    182,
+    101,
+    231,
+    36,
+    231,
+    145,
+    72,
+    88,
+    192,
+    223,
+    74,
+    209,
+    87,
+    10,
+    121,
+    110,
+    90,
+    1,
+    251,
+    81,
+    222,
+    8,
+    140,
+    3,
+    114,
+    35,
+    34,
+    105,
+    132,
+    17,
+    120,
+    75,
+    59,
+    158,
+    116,
+    25,
+    189,
+    204,
+    146,
+    110,
+    242,
+    149,
+    201,
+    107,
+    105,
+    169,
+    202,
+    163,
+    241,
+    229,
+    76,
+    147,
+    228,
+    112,
+    56,
+    44,
+    25,
+    53,
+    46,
+    141,
+    221,
+    37,
+    19,
+    137,
+    75,
+    92,
+    71,
+    165,
+    44,
+    104,
+    84,
+    124,
+    50,
+    150,
+    132,
+    83,
+    0,
+    219,
+    9,
+    103,
+    41,
+    72,
+    88,
+    4,
+    180,
+    44,
+    9,
+    41,
+    102,
+    201,
+    57,
+    211,
+    100,
+    250,
+    243,
+    248,
+    13,
+    215,
+    32,
+    235,
+    247,
+    84,
+    4,
+    0,
+    0
+  ], '''
+<!doctype html>
+<html>
+<head>
+	<title>Example Domain</title>
+
+	<meta charset="utf-8" />
+	<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+	<meta name="viewport" content="width=device-width, initial-scale=1" />
+	<style type="text/css">
+	body {
+		background-color: #f0f0f2;
+		margin: 0;
+		padding: 0;
+		font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+
+	}
+	div {
+		width: 600px;
+		margin: 5em auto;
+		padding: 3em;
+		background-color: #fff;
+		border-radius: 1em;
+	}
+	a:link, a:visited {
+		color: #38488f;
+		text-decoration: none;
+	}
+	@media (max-width: 600px) {
+		body {
+			background-color: #fff;
+		}
+		div {
+			width: auto;
+			margin: 0 auto;
+			border-radius: 0;
+			padding: 1em;
+		}
+	}
+	</style>
+</head>
+
+<body>
+<div>
+	<h1>Example Domain</h1>
+	<p>This domain is established to be used for illustrative examples in documents. You do not need to
+		coordinate or ask for permission to use this domain in examples, and it is not available for
+		registration.</p>
+	<p><a href="http://www.iana.org/domains/special">More information...</a></p>
+</div>
+</body>
+</html>
+''');
+}
+
+void main() {
+  testZLibInflate_regress10026();
+}
diff --git a/tests/standalone/io/regress_21160_test.dart b/tests/standalone/io/regress_21160_test.dart
new file mode 100644
index 0000000..15bf5e4
--- /dev/null
+++ b/tests/standalone/io/regress_21160_test.dart
@@ -0,0 +1,86 @@
+// 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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "package:async_helper/async_helper.dart";
+
+import "dart:async";
+import "dart:io";
+import "dart:typed_data";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+// 10 KiB of i%256 data.
+Uint8List DATA =
+    new Uint8List.fromList(new List.generate(10 * 1024, (i) => i % 256));
+
+Future<SecureServerSocket> startServer() {
+  return SecureServerSocket.bind("localhost", 0, serverContext).then((server) {
+    server.listen((SecureSocket request) async {
+      await request.drain();
+      request
+        ..add(DATA)
+        ..close();
+    });
+    return server;
+  });
+}
+
+main() async {
+  asyncStart();
+  var server = await SecureServerSocket.bind("localhost", 0, serverContext);
+  server.listen((SecureSocket request) async {
+    await request.drain();
+    request
+      ..add(DATA)
+      ..close();
+  });
+
+  var socket = await RawSecureSocket.connect("localhost", server.port,
+      context: clientContext);
+  List<int> body = <int>[];
+  // Close our end, since we're not sending data.
+  socket.shutdown(SocketDirection.send);
+
+  socket.listen((RawSocketEvent event) {
+    switch (event) {
+      case RawSocketEvent.read:
+        // NOTE: We have a very low prime number here. The internal
+        // ring buffers will not have a size of 3. This means that
+        // we'll reach the point where we would like to read 1/2 bytes
+        // at the end and then wrap around and read the next 2/1 bytes.
+        // [This will ensure we trigger the bug.]
+        body.addAll(socket.read(3)!);
+        break;
+      case RawSocketEvent.write:
+        break;
+      case RawSocketEvent.readClosed:
+        break;
+      default:
+        throw "Unexpected event $event";
+    }
+  }, onError: (e, _) {
+    Expect.fail('Unexpected error: $e');
+  }, onDone: () {
+    Expect.equals(body.length, DATA.length);
+    for (int i = 0; i < body.length; i++) {
+      Expect.equals(body[i], DATA[i]);
+    }
+    server.close();
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/regress_21987_test.dart b/tests/standalone/io/regress_21987_test.dart
new file mode 100644
index 0000000..7cc6308f
--- /dev/null
+++ b/tests/standalone/io/regress_21987_test.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 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void main() {
+  if (Platform.isLinux) {
+    asyncStart();
+    var selfExe = new Link('/proc/self/exe');
+    Expect.isTrue(selfExe.targetSync().length > 0);
+    selfExe.target().then((target) {
+      Expect.isTrue(target.length > 0);
+      asyncEnd();
+    });
+  }
+}
diff --git a/tests/standalone/io/regress_7191_script.dart b/tests/standalone/io/regress_7191_script.dart
new file mode 100644
index 0000000..a674feb
--- /dev/null
+++ b/tests/standalone/io/regress_7191_script.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.
+
+import 'dart:io';
+import 'dart:isolate';
+
+main() {
+  // Open a port to make the script hang.
+  var port = new ReceivePort();
+  // Start sub-process when receiving data.
+  var subscription;
+  subscription = stdin.listen((data) {
+    Process.start(Platform.executable, [Platform.script.toFilePath()])
+        .then((p) {
+      p.stdout.listen((_) {});
+      p.stderr.listen((_) {});
+      // When receiving data again, kill sub-process and exit.
+      subscription.onData((data) {
+        // If a SIGTERM is sent before the child-process's main is invoked,
+        // there is a change that the SIGTERM is ignore on Mac OS X. Use
+        // SIGKILL to get around the issue.
+        p.kill(ProcessSignal.sigkill);
+        p.exitCode.then((_) => exit(0));
+      });
+      // Close stdout. If handles are incorrectly inherited this will
+      // not actually close stdout and the test will hang.
+      stdout.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/regress_7191_test.dart b/tests/standalone/io/regress_7191_test.dart
new file mode 100644
index 0000000..8477956
--- /dev/null
+++ b/tests/standalone/io/regress_7191_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.
+
+// OtherResources=regress_7191_script.dart
+
+// Regression test for http://dartbug.com/7191.
+
+// Starts a sub-process which in turn starts another sub-process and then closes
+// its standard output. If handles are incorrectly inherited on Windows, this
+// will lead to a situation where the stdout of the first sub-process is never
+// closed which will make this test hang.
+
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import 'package:path/path.dart';
+
+main() {
+  asyncStart();
+  var executable = Platform.executable;
+  var script = Platform.script.resolve('regress_7191_script.dart').toFilePath();
+  Process.start(
+          executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(script))
+      .then((process) {
+    process.stdin.add([0]);
+    process.stdout.listen((_) {}, onDone: () {
+      process.stdin.add([0]);
+    });
+    process.stderr.listen((_) {});
+    process.exitCode.then((exitCode) {
+      asyncEnd();
+      if (exitCode != 0) throw "Bad exit code";
+    });
+  });
+}
diff --git a/tests/standalone/io/regress_7679_test.dart b/tests/standalone/io/regress_7679_test.dart
new file mode 100644
index 0000000..720e607
--- /dev/null
+++ b/tests/standalone/io/regress_7679_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.
+
+import "package:expect/expect.dart";
+import 'dart:io';
+
+main() {
+  Directory temp = Directory.systemTemp.createTempSync('dart_regress_7679');
+  File script = new File('${temp.path}/script.dart');
+  script.writeAsStringSync("""
+import 'dart:io';
+
+class Expect {
+  static void isTrue(var x) {
+    if (!identical(x, true)) {
+      throw new StateError("Not identical");
+    }
+  }
+}
+
+main() {
+  Directory d = new Directory('a');
+  d.create(recursive: true).then((_) {
+    d.exists().then((result) {
+      Expect.isTrue(result);
+      d = new Directory('b/c/d');
+      d.create(recursive: true).then((_) {
+        d.exists().then((result) {
+          Expect.isTrue(result);
+        });
+      });
+    });
+  });
+}
+""");
+  String executable = new File(Platform.executable).resolveSymbolicLinksSync();
+  // Note: we prevent this child process from using Crashpad handler because
+  // this introduces an issue with deleting the temporary directory.
+  Process.run(
+      executable,
+      []
+        ..addAll(Platform.executableArguments)
+        ..add('script.dart'),
+      workingDirectory: temp.path,
+      environment: {'DART_CRASHPAD_HANDLER': ''}).then((result) {
+    temp.deleteSync(recursive: true);
+    Expect.equals(0, result.exitCode);
+  });
+}
diff --git a/tests/standalone/io/regress_8828_test.dart b/tests/standalone/io/regress_8828_test.dart
new file mode 100644
index 0000000..22225c8
--- /dev/null
+++ b/tests/standalone/io/regress_8828_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.
+
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import 'dart:io';
+
+void main() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      request.response
+        ..writeln("first line")
+        ..write("")
+        ..writeln("second line")
+        ..close();
+    });
+
+    HttpClient client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/").then((HttpClientRequest request) {
+      return request.close();
+    }).then((HttpClientResponse response) {
+      List<int> body = new List();
+      response.listen(body.addAll, onDone: () {
+        Expect.equals(
+            "first line\nsecond line\n", new String.fromCharCodes(body));
+        server.close();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/regress_9194_test.dart b/tests/standalone/io/regress_9194_test.dart
new file mode 100644
index 0000000..c6ca92f
--- /dev/null
+++ b/tests/standalone/io/regress_9194_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";
+import 'dart:io';
+
+void main() {
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+    server.listen((request) {
+      request.response
+        ..reasonPhrase = ''
+        ..close();
+    });
+
+    HttpClient client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/").then((HttpClientRequest request) {
+      return request.close();
+    }).then((HttpClientResponse response) {
+      Expect.equals("", response.reasonPhrase);
+      server.close();
+      client.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/resolve_symbolic_links_test.dart b/tests/standalone/io/resolve_symbolic_links_test.dart
new file mode 100644
index 0000000..57561db
--- /dev/null
+++ b/tests/standalone/io/resolve_symbolic_links_test.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing FileSystemEntity.resolveSymbolicLinks
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "package:async_helper/async_helper.dart";
+import 'dart:async';
+import 'dart:io';
+
+main() {
+  String testsDir = Directory.current.uri.resolve('tests').toFilePath();
+
+  // All of these tests test that resolveSymbolicLinks gives a path
+  // that points to the same place as the original, and that it removes
+  // all links, .., and . segments, and that it produces an absolute path.
+  asyncTest(() => testFile(join(
+      testsDir, 'standalone_2', 'io', 'resolve_symbolic_links_test.dart')));
+  asyncTest(() => testFile(join(testsDir, 'standalone_2', 'io', '..', 'io',
+      'resolve_symbolic_links_test.dart')));
+
+  asyncTest(() => testDir(join(testsDir, 'standalone_2', 'io')));
+  asyncTest(() => testDir(join(testsDir, 'lib_2', '..', 'standalone_2', 'io')));
+  // Test a relative path.
+  if (Platform.isWindows) {
+    asyncTest(() => testFile(join('\\\\?\\$testsDir', 'standalone_2', 'io',
+        'resolve_symbolic_links_test.dart')));
+    asyncTest(() => testDir('\\\\?\\$testsDir'));
+  }
+  asyncTest(() => Directory.systemTemp
+          .createTemp('dart_resolve_symbolic_links')
+          .then((tempDir) {
+        String temp = tempDir.path;
+        return makeEntities(temp)
+            .then((_) => Future.wait([
+                  testFile(join(temp, 'dir1', 'file1')),
+                  testFile(join(temp, 'link1', 'file2')),
+                  testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
+                  testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
+                  testLink(join(temp, 'link1')),
+                  testDir('.')
+                ]))
+            .then((_) {
+          if (Platform.isWindows) {
+            // Windows applies '..' to a link without resolving the link first.
+            return Future.wait([
+              testFile(join(
+                  temp, 'dir1', '..', 'link1', '..', 'dir1', 'dir2', 'file2')),
+              testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir1')),
+              testLink(join(temp, 'link1', '..', 'link1'))
+            ]);
+          } else {
+            // Non-Windows platforms resolve the link before adding the '..'.
+            return Future.wait([
+              testFile(
+                  join(temp, 'dir1', '..', 'link1', '..', 'dir2', 'file2')),
+              testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir2')),
+              testLink(join(temp, 'link1', '..', '..', 'link1'))
+            ]);
+          }
+        }).then((_) {
+          Directory.current = temp;
+          return Future.wait([
+            testFile('dir1/dir2/file2'), // Test forward slashes on Windows too.
+            testFile('link1/file2'),
+            testFile(join('dir1', '..', 'dir1', '.', 'file1')),
+            testDir('.'),
+            testLink('link1')
+          ]);
+        }).then((_) {
+          Directory.current = 'link1';
+          if (Platform.isWindows) {
+            return Future.wait([
+              testFile('file2'),
+              // Windows applies '..' to a link without resolving the link first.
+              testFile('..\\dir1\\file1'),
+              testLink('.'),
+              testDir('..'),
+              testLink('..\\link1')
+            ]);
+          } else {
+            return Future.wait([
+              testFile('file2'),
+              // On non-Windows the link is changed to dir1/dir2 before .. happens.
+              testFile('../dir2/file2'),
+              testDir('.'),
+              testDir('..'),
+              testLink('../../link1')
+            ]);
+          }
+        }).whenComplete(() {
+          Directory.current = testsDir;
+          tempDir.delete(recursive: true);
+        });
+      }));
+}
+
+Future makeEntities(String temp) {
+  return new Directory(join(temp, 'dir1', 'dir2'))
+      .create(recursive: true)
+      .then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
+      .then((_) => new File(join(temp, 'dir1', 'file1')).create())
+      .then((_) =>
+          new Link(join(temp, 'link1')).create(join(temp, 'dir1', 'dir2')));
+}
+
+Future testFile(String name) {
+  // We test that f.resolveSymbolicLinks points to the same place
+  // as f, because the actual resolved path is not easily predictable.
+  // The location of the temp directory varies from system to system,
+  // and its path includes symbolic links on some systems.
+  //Expect.isTrue(FileSystemEntity.identicalSync(name,
+  //   new File(name).resolveSymbolicLinksSync()));
+  return new File(name).resolveSymbolicLinks().then((String resolved) {
+    //Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
+    Expect.isTrue(isAbsolute(resolved));
+    // Test that resolveSymbolicLinks removes all links, .., and . segments.
+    Expect.isFalse(resolved.contains('..'));
+    Expect.isFalse(resolved.contains('./'));
+    Expect.isFalse(resolved.contains('link1'));
+  });
+}
+
+Future testDir(String name) {
+  Expect.isTrue(FileSystemEntity.identicalSync(
+      name, new Directory(name).resolveSymbolicLinksSync()));
+  return new Directory(name).resolveSymbolicLinks().then((String resolved) {
+    Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
+    Expect.isTrue(isAbsolute(resolved));
+    // Test that resolveSymbolicLinks removes all links, .., and . segments.
+    Expect.isFalse(resolved.contains('..'));
+    Expect.isFalse(resolved.contains('./'));
+    Expect.isFalse(resolved.contains('link1'));
+  });
+}
+
+Future testLink(String name) {
+  Expect.isFalse(FileSystemEntity.identicalSync(
+      name, new Link(name).resolveSymbolicLinksSync()));
+  Expect.isTrue(FileSystemEntity.identicalSync(
+      new Link(name).targetSync(), new Link(name).resolveSymbolicLinksSync()));
+  return new Link(name).resolveSymbolicLinks().then((String resolved) {
+    Expect.isFalse(FileSystemEntity.identicalSync(name, resolved));
+    Expect.isTrue(isAbsolute(resolved));
+    // Test that resolveSymbolicLinks removes all links, .., and . segments.
+    Expect.isFalse(resolved.contains('..'));
+    Expect.isFalse(resolved.contains('./'));
+    Expect.isFalse(resolved.contains('link1'));
+    return new Link(name)
+        .target()
+        .then((targetName) => FileSystemEntity.identical(targetName, resolved))
+        .then((identical) => Expect.isTrue(identical));
+  });
+}
diff --git a/tests/standalone/io/sample_certificate_v3_extensions b/tests/standalone/io/sample_certificate_v3_extensions
new file mode 100644
index 0000000..f17764d
--- /dev/null
+++ b/tests/standalone/io/sample_certificate_v3_extensions
@@ -0,0 +1,53 @@
+# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# OpenSSL configuration file giving the v3 extensions for the sample
+# certificates created by create_sample_certificates.sh
+
+default_bits = 2048
+distinguished_name = name_section
+[name_section]
+CN = foo
+
+[localhost]
+subjectAltName = @alt_names
+basicConstraints = critical,CA:false
+subjectKeyIdentifier = hash
+authorityKeyIdentifier=keyid,issuer
+keyUsage=critical, digitalSignature, keyEncipherment, keyAgreement
+extendedKeyUsage=serverAuth
+
+[alt_names]
+DNS.1 = localhost
+DNS.2 = 127.0.0.1
+DNS.3 = ::1
+IP.1 = 127.0.0.1
+IP.2 = ::1
+
+[badlocalhost]
+basicConstraints = critical,CA:false
+subjectKeyIdentifier = hash
+authorityKeyIdentifier=keyid,issuer
+keyUsage=critical, digitalSignature, keyEncipherment, keyAgreement
+extendedKeyUsage=serverAuth
+
+[intermediate_authority]
+basicConstraints = critical, CA:true, pathlen:0
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always, issuer
+keyUsage=critical, keyCertSign
+extendedKeyUsage=serverAuth
+
+[client_authority]
+basicConstraints = critical,CA:true,pathlen:0
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always, issuer
+keyUsage=critical, keyCertSign
+extendedKeyUsage=clientAuth
+
+[client_certificate]
+basicConstraints = CA:false
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always, issuer
+extendedKeyUsage=clientAuth
diff --git a/tests/standalone/io/secure_bad_certificate_test.dart b/tests/standalone/io/secure_bad_certificate_test.dart
new file mode 100644
index 0000000..e002313
--- /dev/null
+++ b/tests/standalone/io/secure_bad_certificate_test.dart
@@ -0,0 +1,105 @@
+// 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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/bad_server_chain.pem
+// OtherResources=certificates/bad_server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+// This test verifies that the bad certificate callback works.
+
+import "dart:async";
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+final HOST_NAME = 'localhost';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext badServerContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/bad_server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/bad_server_key.pem'),
+      password: 'dartdart');
+
+class CustomException {}
+
+main() async {
+  var HOST = (await InternetAddress.lookup(HOST_NAME)).first;
+  var server = await SecureServerSocket.bind(HOST_NAME, 0, serverContext);
+  server.listen((SecureSocket socket) {
+    socket.listen((_) {}, onDone: () {
+      socket.close();
+    });
+  }, onError: (e) {
+    if (e is! HandshakeException) throw e;
+  });
+
+  var badServer = await SecureServerSocket.bind(HOST_NAME, 0, badServerContext);
+  badServer.listen((SecureSocket socket) {
+    socket.listen((_) {}, onDone: () {
+      socket.close();
+    });
+  }, onError: (e) {
+    if (e is! HandshakeException) throw e;
+  });
+
+  SecurityContext goodContext = new SecurityContext()
+    ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+  SecurityContext badContext = new SecurityContext();
+  SecurityContext defaultContext = SecurityContext.defaultContext;
+
+  await runClient(server.port, goodContext, true, 'pass');
+  await runClient(server.port, goodContext, false, 'pass');
+  await runClient(server.port, goodContext, 'fisk', 'pass');
+  await runClient(server.port, goodContext, 'exception', 'pass');
+  await runClient(server.port, badContext, true, 'pass');
+  await runClient(server.port, badContext, false, 'fail');
+  await runClient(server.port, badContext, 'fisk', 'fail');
+  await runClient(server.port, badContext, 'exception', 'throw');
+  await runClient(server.port, defaultContext, true, 'pass');
+  await runClient(server.port, defaultContext, false, 'fail');
+  await runClient(server.port, defaultContext, 'fisk', 'fail');
+  await runClient(server.port, defaultContext, 'exception', 'throw');
+
+  await runClient(badServer.port, goodContext, false, 'fail');
+
+  server.close();
+  badServer.close();
+}
+
+Future runClient(
+    int port, SecurityContext context, callbackReturns, result) async {
+  bool badCertificateCallback(X509Certificate certificate) {
+    Expect.isNotNull(certificate.subject);
+    Expect.isNotNull(certificate.issuer);
+    // Throw exception if one is requested.
+    if (callbackReturns == 'exception') throw new CustomException();
+    if (callbackReturns is bool) return callbackReturns;
+    return false;
+  }
+
+  try {
+    var socket = await SecureSocket.connect(HOST_NAME, port,
+        context: context, onBadCertificate: badCertificateCallback);
+    Expect.equals('pass', result); // Is rethrown below
+    await socket.close();
+  } catch (error) {
+    if (error is ExpectException) rethrow;
+    Expect.notEquals(result, 'pass');
+    if (result == 'fail') {
+      Expect.isTrue(error is HandshakeException || error is ArgumentError);
+    } else if (result == 'throw') {
+      Expect.isTrue(error is CustomException);
+    } else {
+      Expect.fail('Unknown expectation $result');
+    }
+  }
+}
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
new file mode 100644
index 0000000..be550a1
--- /dev/null
+++ b/tests/standalone/io/secure_builtin_roots_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:io";
+import "dart:async";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future testGoogleUrl(SecurityContext? context, String outcome) async {
+  var client = new HttpClient(context: context);
+  // We need to use an external server that is backed by a
+  // built-in root certificate authority.
+  try {
+    // First, check if the lookup works.
+    await InternetAddress.lookup('www.google.com');
+    var request = await client.getUrl(Uri.parse('https://www.google.com'));
+    request.followRedirects = false;
+    var response = await request.close();
+    Expect.equals('pass', outcome, 'Unexpected successful connection');
+    try {
+      await response.drain();
+    } catch (e) {}
+  } on HandshakeException {
+    Expect.equals('fail', outcome, 'Unexpected failed connection');
+  } on SocketException {
+    // Lookup failed or connection failed.  Don't report a failure.
+  } finally {
+    client.close();
+  }
+}
+
+main() async {
+  asyncStart();
+  await testGoogleUrl(null, "pass");
+  await testGoogleUrl(SecurityContext.defaultContext, "pass");
+  await testGoogleUrl(new SecurityContext(withTrustedRoots: true), "pass");
+  await testGoogleUrl(new SecurityContext(withTrustedRoots: false), "fail");
+  await testGoogleUrl(new SecurityContext(), "fail");
+  asyncEnd();
+}
diff --git a/tests/standalone/io/secure_client_raw_server_test.dart b/tests/standalone/io/secure_client_raw_server_test.dart
new file mode 100644
index 0000000..22576c6
--- /dev/null
+++ b/tests/standalone/io/secure_client_raw_server_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+late InternetAddress HOST;
+Future<RawSecureServerSocket> startEchoServer() {
+  return RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((RawSecureSocket client) {
+      List<List<int>> readChunks = <List<int>>[];
+      List<int>? dataToWrite = null;
+      int bytesWritten = 0;
+      client.writeEventsEnabled = false;
+      client.listen((event) {
+        switch (event) {
+          case RawSocketEvent.read:
+            Expect.isTrue(bytesWritten == 0);
+            Expect.isTrue(client.available() > 0);
+            readChunks.add(client.read()!);
+            break;
+          case RawSocketEvent.write:
+            Expect.isFalse(client.writeEventsEnabled);
+            Expect.isNotNull(dataToWrite);
+            bytesWritten += client.write(
+                dataToWrite!, bytesWritten, dataToWrite!.length - bytesWritten);
+            if (bytesWritten < dataToWrite!.length) {
+              client.writeEventsEnabled = true;
+            }
+            if (bytesWritten == dataToWrite!.length) {
+              client.shutdown(SocketDirection.send);
+            }
+            break;
+          case RawSocketEvent.readClosed:
+            dataToWrite = readChunks.fold<List<int>>(<int>[], (list, x) {
+              list.addAll(x);
+              return list;
+            });
+            client.writeEventsEnabled = true;
+            break;
+        }
+      });
+    });
+    return server;
+  });
+}
+
+Future testClient(server) {
+  Completer success = new Completer();
+  List<String> chunks = <String>[];
+  SecureSocket.connect(HOST, server.port, context: clientContext)
+      .then((socket) {
+    socket.write("Hello server.");
+    socket.close();
+    socket.listen((List<int> data) {
+      var received = new String.fromCharCodes(data);
+      chunks.add(received);
+    }, onDone: () {
+      String reply = chunks.join();
+      Expect.equals("Hello server.", reply);
+      success.complete(server);
+    });
+  });
+  return success.future;
+}
+
+void main() {
+  asyncStart();
+  InternetAddress.lookup("localhost")
+      .then((hosts) => HOST = hosts.first)
+      .then((_) => startEchoServer())
+      .then(testClient)
+      .then((server) => server.close())
+      .then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/secure_client_server_test.dart b/tests/standalone/io/secure_client_server_test.dart
new file mode 100644
index 0000000..5d55b1b
--- /dev/null
+++ b/tests/standalone/io/secure_client_server_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+Future<SecureServerSocket> startEchoServer() {
+  return SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((SecureSocket client) {
+      client.fold<List<int>>(
+          <int>[], (message, data) => message..addAll(data)).then((message) {
+        client.add(message);
+        client.close();
+      });
+    });
+    return server;
+  });
+}
+
+void checkServerCertificate(X509Certificate serverCert) {
+  String serverCertString = serverCert.pem;
+  String certFile =
+      new File(localFile('certificates/server_chain.pem')).readAsStringSync();
+  Expect.isTrue(certFile.contains(serverCertString));
+
+  // Computed with:
+  // openssl x509 -noout -sha1 -fingerprint -in certificates/server_chain.pem
+  List<int> serverSha1 = <int>[
+    0xB3, 0x01, 0xCB, 0x7E, 0x6F, 0xEF, 0xBE, 0xEF, //
+    0x75, 0x6D, 0xA8, 0x80, 0x60, 0xA8, 0x5D, 0x6F, //
+    0xC4, 0xED, 0xCD, 0x48, //
+  ];
+  Expect.listEquals(serverSha1, serverCert.sha1);
+}
+
+Future testClient(server) {
+  return SecureSocket.connect(HOST, server.port, context: clientContext)
+      .then((socket) {
+    checkServerCertificate(socket.peerCertificate!);
+    socket.write("Hello server.");
+    socket.close();
+    return socket.fold<List<int>>(
+        <int>[], (message, data) => message..addAll(data)).then((message) {
+      Expect.listEquals("Hello server.".codeUnits, message);
+      return server;
+    });
+  });
+}
+
+void main() {
+  asyncStart();
+  InternetAddress.lookup("localhost")
+      .then((hosts) => HOST = hosts.first)
+      .then((_) => startEchoServer())
+      .then(testClient)
+      .then((server) => server.close())
+      .then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/secure_multiple_client_server_test.dart b/tests/standalone/io/secure_multiple_client_server_test.dart
new file mode 100644
index 0000000..a908045
--- /dev/null
+++ b/tests/standalone/io/secure_multiple_client_server_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+late SecureServerSocket SERVER;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+Future startServer() {
+  return SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    SERVER = server;
+    SERVER.listen((SecureSocket client) {
+      client.fold<List<int>>(
+          <int>[], (message, data) => message..addAll(data)).then((message) {
+        String received = new String.fromCharCodes(message);
+        Expect.isTrue(received.contains("Hello from client "));
+        String name = received.substring(received.indexOf("client ") + 7);
+        client.add("Welcome, client $name".codeUnits);
+        client.close();
+      });
+    });
+  });
+}
+
+Future testClient(name) {
+  return SecureSocket.connect(HOST, SERVER.port, context: clientContext)
+      .then((socket) {
+    socket.add("Hello from client $name".codeUnits);
+    socket.close();
+    return socket.fold<List<int>>(
+        <int>[], (message, data) => message..addAll(data)).then((message) {
+      Expect.listEquals("Welcome, client $name".codeUnits, message);
+    });
+  });
+}
+
+void main() {
+  asyncStart();
+  InternetAddress.lookup("localhost")
+      .then((hosts) => HOST = hosts.first)
+      .then((_) => startServer())
+      .then((_) => ['ale', 'bar', 'che', 'den', 'els'].map(testClient))
+      .then((futures) => Future.wait(futures))
+      .then((_) => SERVER.close())
+      .then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
new file mode 100644
index 0000000..18ae856
--- /dev/null
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -0,0 +1,121 @@
+// 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.
+
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=certificates/client_authority.pem
+// OtherResources=certificates/client1.pem
+// OtherResources=certificates/client1_key.pem
+// OtherResources=certificates/server_chain.p12
+// OtherResources=certificates/server_key.p12
+// OtherResources=certificates/trusted_certs.p12
+// OtherResources=certificates/client_authority.p12
+// OtherResources=certificates/client1.p12
+// OtherResources=certificates/client1_key.p12
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext(String certType, String password) =>
+    new SecurityContext()
+      ..useCertificateChain(localFile('certificates/server_chain.$certType'),
+          password: password)
+      ..usePrivateKey(localFile('certificates/server_key.$certType'),
+          password: password)
+      ..setTrustedCertificates(
+          localFile('certificates/client_authority.$certType'),
+          password: password)
+      ..setClientAuthorities(
+          localFile('certificates/client_authority.$certType'),
+          password: password);
+
+SecurityContext clientCertContext(String certType, String password) =>
+    new SecurityContext()
+      ..setTrustedCertificates(
+          localFile('certificates/trusted_certs.$certType'),
+          password: password)
+      ..useCertificateChain(localFile('certificates/client1.$certType'),
+          password: password)
+      ..usePrivateKey(localFile('certificates/client1_key.$certType'),
+          password: password);
+
+SecurityContext clientNoCertContext(String certType, String password) =>
+    new SecurityContext()
+      ..setTrustedCertificates(
+          localFile('certificates/trusted_certs.$certType'),
+          password: password);
+
+Future testClientCertificate(
+    {required bool required,
+    required bool sendCert,
+    required String certType,
+    required String password}) async {
+  var server = await SecureServerSocket.bind(
+      HOST, 0, serverContext(certType, password),
+      requestClientCertificate: true, requireClientCertificate: required);
+  var clientContext = sendCert
+      ? clientCertContext(certType, password)
+      : clientNoCertContext(certType, password);
+  var clientEndFuture =
+      SecureSocket.connect(HOST, server.port, context: clientContext);
+  if (required && sendCert) {
+    try {
+      await server.first;
+    } catch (e) {
+      try {
+        await clientEndFuture;
+      } catch (e) {
+        return;
+      }
+    }
+    Expect.fail("Connection succeeded with no required client certificate");
+  }
+  var serverEnd = await server.first;
+  var clientEnd = await clientEndFuture;
+
+  X509Certificate? clientCertificate = serverEnd.peerCertificate;
+  if (sendCert) {
+    Expect.isNotNull(clientCertificate);
+    Expect.isTrue(clientCertificate!.subject.contains("user1"));
+    Expect.isTrue(clientCertificate.issuer.contains("clientauthority"));
+  } else {
+    Expect.isNull(clientCertificate);
+  }
+  X509Certificate serverCertificate = clientEnd.peerCertificate!;
+  Expect.isTrue(serverCertificate.subject.contains("localhost"));
+  Expect.isTrue(serverCertificate.issuer.contains("intermediateauthority"));
+  clientEnd.close();
+  serverEnd.close();
+}
+
+main() async {
+  asyncStart();
+  HOST = (await InternetAddress.lookup("localhost")).first;
+  await testClientCertificate(
+      required: false, sendCert: true, certType: 'pem', password: 'dartdart');
+  await testClientCertificate(
+      required: true, sendCert: true, certType: 'pem', password: 'dartdart');
+  await testClientCertificate(
+      required: false, sendCert: false, certType: 'pem', password: 'dartdart');
+  await testClientCertificate(
+      required: true, sendCert: false, certType: 'pem', password: 'dartdart');
+
+  await testClientCertificate(
+      required: false, sendCert: true, certType: 'p12', password: 'dartdart');
+  await testClientCertificate(
+      required: true, sendCert: true, certType: 'p12', password: 'dartdart');
+  await testClientCertificate(
+      required: false, sendCert: false, certType: 'p12', password: 'dartdart');
+  await testClientCertificate(
+      required: true, sendCert: false, certType: 'p12', password: 'dartdart');
+  asyncEnd();
+}
diff --git a/tests/standalone/io/secure_server_closing_test.dart b/tests/standalone/io/secure_server_closing_test.dart
new file mode 100644
index 0000000..a6769c8
--- /dev/null
+++ b/tests/standalone/io/secure_server_closing_test.dart
@@ -0,0 +1,178 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testCloseOneEnd(String toClose) {
+  asyncStart();
+  Completer serverDone = new Completer();
+  Completer serverEndDone = new Completer();
+  Completer clientEndDone = new Completer();
+  Future.wait([serverDone.future, serverEndDone.future, clientEndDone.future])
+      .then((_) {
+    asyncEnd();
+  });
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((serverConnection) {
+      serverConnection.listen((data) {
+        Expect.fail("No data should be received by server");
+      }, onDone: () {
+        serverConnection.close();
+        serverEndDone.complete(null);
+        server.close();
+      });
+      if (toClose == "server") {
+        serverConnection.close();
+      }
+    }, onDone: () {
+      serverDone.complete(null);
+    });
+    SecureSocket.connect(HOST, server.port, context: clientContext)
+        .then((clientConnection) {
+      clientConnection.listen((data) {
+        Expect.fail("No data should be received by client");
+      }, onDone: () {
+        clientConnection.close();
+        clientEndDone.complete(null);
+      });
+      if (toClose == "client") {
+        clientConnection.close();
+      }
+    });
+  });
+}
+
+void testCloseBothEnds() {
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    var clientEndFuture =
+        SecureSocket.connect(HOST, server.port, context: clientContext);
+    server.listen((serverEnd) {
+      clientEndFuture.then((clientEnd) {
+        clientEnd.destroy();
+        serverEnd.destroy();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+testPauseServerSocket() {
+  const int socketCount = 10;
+  var acceptCount = 0;
+  var resumed = false;
+
+  asyncStart();
+
+  SecureServerSocket.bind(HOST, 0, serverContext, backlog: 2 * socketCount)
+      .then((server) {
+    Expect.isTrue(server.port > 0);
+    var subscription;
+    subscription = server.listen((connection) {
+      Expect.isTrue(resumed);
+      connection.close();
+      if (++acceptCount == 2 * socketCount) {
+        server.close();
+        asyncEnd();
+      }
+    });
+
+    // Pause the server socket subscription and resume it after having
+    // connected a number client sockets. Then connect more client sockets.
+    subscription.pause();
+    var connectCount = 0;
+    for (int i = 0; i < socketCount; i++) {
+      SecureSocket.connect(HOST, server.port, context: clientContext)
+          .then((connection) {
+        connection.close();
+      });
+    }
+    new Timer(const Duration(milliseconds: 500), () {
+      subscription.resume();
+      resumed = true;
+      for (int i = 0; i < socketCount; i++) {
+        SecureSocket.connect(HOST, server.port, context: clientContext)
+            .then((connection) {
+          connection.close();
+        });
+      }
+    });
+  });
+}
+
+testCloseServer() {
+  const int socketCount = 3;
+  var endCount = 0;
+  asyncStart();
+  List ends = [];
+
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Expect.isTrue(server.port > 0);
+    void checkDone() {
+      if (ends.length < 2 * socketCount) return;
+      for (var end in ends) {
+        end.destroy();
+      }
+      server.close();
+      asyncEnd();
+    }
+
+    server.listen((connection) {
+      ends.add(connection);
+      checkDone();
+    });
+
+    for (int i = 0; i < socketCount; i++) {
+      SecureSocket.connect(HOST, server.port, context: clientContext)
+          .then((connection) {
+        ends.add(connection);
+        checkDone();
+      });
+    }
+  });
+}
+
+main() {
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests();
+    asyncEnd();
+  });
+}
+
+runTests() {
+  testCloseOneEnd("client");
+  testCloseOneEnd("server");
+  testCloseBothEnds();
+  testPauseServerSocket();
+  testCloseServer();
+  // TODO(whesse): Add testPauseSocket from raw_socket_test.dart.
+  // TODO(whesse): Add testCancelResubscribeSocket from raw_socket_test.dart.
+}
diff --git a/tests/standalone/io/secure_server_socket_test.dart b/tests/standalone/io/secure_server_socket_test.dart
new file mode 100644
index 0000000..627ed6d
--- /dev/null
+++ b/tests/standalone/io/secure_server_socket_test.dart
@@ -0,0 +1,235 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testSimpleBind() {
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    Expect.isTrue(s.port > 0);
+    s.close();
+    asyncEnd();
+  });
+}
+
+void testInvalidBind() {
+  int count = 0;
+
+  // Bind to a unknown DNS name.
+  asyncStart();
+  SecureServerSocket.bind("ko.faar.__hest__", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to an unavaliable IP-address.
+  asyncStart();
+  SecureServerSocket.bind("8.8.8.8", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to a port already in use.
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    SecureServerSocket.bind(HOST, s.port, serverContext).then((t) {
+      Expect.fail("Multiple listens on same port");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException);
+      s.close();
+      asyncEnd();
+    });
+  });
+}
+
+void testSimpleConnect() {
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    var clientEndFuture =
+        SecureSocket.connect(HOST, server.port, context: clientContext);
+    server.listen((serverEnd) {
+      clientEndFuture.then((clientEnd) {
+        var x5 = clientEnd.peerCertificate!;
+        print(x5.subject);
+        print(x5.issuer);
+        print(x5.startValidity);
+        print(x5.endValidity);
+        clientEnd.close();
+        serverEnd.close();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+void testSimpleConnectFail(SecurityContext? serverContext,
+    SecurityContext? clientContext, bool cancelOnError) {
+  print('$serverContext $clientContext $cancelOnError');
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Future<void> clientEndFuture =
+        SecureSocket.connect(HOST, server.port, context: clientContext)
+            .then((clientEnd) {
+      Expect.fail("No client connection expected.");
+    }).catchError((error) {
+      // TODO(whesse): When null context is supported, disallow
+      // the ArgumentError type here.
+      Expect.isTrue(error is ArgumentError ||
+          error is HandshakeException ||
+          error is SocketException);
+    });
+    server.listen((serverEnd) {
+      Expect.fail("No server connection expected.");
+    }, onError: (error) {
+      // TODO(whesse): When null context is supported, disallow
+      // the ArgumentError type here.
+      Expect.isTrue(error is ArgumentError ||
+          error is HandshakeException ||
+          error is SocketException);
+      clientEndFuture.then((_) {
+        if (!cancelOnError) server.close();
+        asyncEnd();
+      });
+    }, cancelOnError: cancelOnError);
+  });
+}
+
+void testServerListenAfterConnect() {
+  asyncStart();
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Expect.isTrue(server.port > 0);
+    var clientEndFuture =
+        SecureSocket.connect(HOST, server.port, context: clientContext);
+    new Timer(const Duration(milliseconds: 500), () {
+      server.listen((serverEnd) {
+        clientEndFuture.then((clientEnd) {
+          clientEnd.close();
+          serverEnd.close();
+          server.close();
+          asyncEnd();
+        });
+      });
+    });
+  });
+}
+
+void testSimpleReadWrite() {
+  // This test creates a server and a client connects. The client then
+  // writes and the server echos. When the server has finished its
+  // echo it half-closes. When the client gets the close event is
+  // closes fully.
+  asyncStart();
+
+  const messageSize = 1000;
+
+  List<int> createTestData() {
+    List<int> data = new List<int>.filled(messageSize, 0);
+    for (int i = 0; i < messageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  void verifyTestData(List<int> data) {
+    Expect.equals(messageSize, data.length);
+    List<int> expected = createTestData();
+    for (int i = 0; i < messageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((client) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      List<int> data = new List<int>.filled(messageSize, 0);
+
+      client.listen((buffer) {
+        Expect.isTrue(bytesWritten == 0);
+        data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+        bytesRead += buffer.length;
+        if (bytesRead == data.length) {
+          verifyTestData(data);
+          client.add(data);
+          client.close();
+        }
+      }, onDone: () {
+        server.close();
+      });
+    });
+
+    SecureSocket.connect(HOST, server.port, context: clientContext)
+        .then((socket) {
+      int bytesRead = 0;
+      int bytesWritten = 0;
+      List<int> dataSent = createTestData();
+      List<int> dataReceived = new List<int>.filled(dataSent.length, 0);
+      socket.add(dataSent);
+      socket.close(); // Can also be delayed.
+      socket.listen((List<int> buffer) {
+        dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
+        bytesRead += buffer.length;
+      }, onDone: () {
+        verifyTestData(dataReceived);
+        socket.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests();
+    asyncEnd();
+  });
+}
+
+runTests() {
+  testSimpleBind();
+  testInvalidBind();
+  testSimpleConnect();
+  for (var server in [serverContext, null]) {
+    for (var client in [clientContext, null]) {
+      for (bool cancelOnError in [true, false]) {
+        if (server == null || client == null) {
+          testSimpleConnectFail(server, client, cancelOnError);
+        }
+      }
+    }
+  }
+  testServerListenAfterConnect();
+  testSimpleReadWrite();
+}
diff --git a/tests/standalone/io/secure_session_resume_test.dart b/tests/standalone/io/secure_session_resume_test.dart
new file mode 100644
index 0000000..6f7f1e1
--- /dev/null
+++ b/tests/standalone/io/secure_session_resume_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.
+//
+// This test tests TLS session resume, by making multiple client connections
+// on the same port to the same server, with a delay of 200 ms between them.
+// The unmodified secure_server_test creates all sessions simultaneously,
+// which means that no handshake completes and caches its keys in the session
+// cache in time for other connections to use it.
+//
+// Session resume is currently disabled - see issue
+// https://code.google.com/p/dart/issues/detail?id=7230
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+late InternetAddress HOST;
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+Future<SecureServerSocket> startServer() {
+  return SecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    server.listen((SecureSocket client) {
+      client.fold<List<int>>(
+          <int>[], (message, data) => message..addAll(data)).then((message) {
+        String received = new String.fromCharCodes(message);
+        Expect.isTrue(received.contains("Hello from client "));
+        String name = received.substring(received.indexOf("client ") + 7);
+        client.write("Welcome, client $name");
+        client.close();
+      });
+    });
+    return server;
+  });
+}
+
+Future testClient(server, name) {
+  return SecureSocket.connect(HOST, server.port, context: clientContext)
+      .then((socket) {
+    socket.write("Hello from client $name");
+    socket.close();
+    return socket.fold<List<int>>(
+        <int>[], (message, data) => message..addAll(data)).then((message) {
+      Expect.listEquals("Welcome, client $name".codeUnits, message);
+      return server;
+    });
+  });
+}
+
+void main() {
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests().then((_) => asyncEnd());
+  });
+}
+
+Future runTests() {
+  Duration delay = const Duration(milliseconds: 0);
+  Duration delay_between_connections = const Duration(milliseconds: 300);
+  return startServer()
+      .then((server) => Future.wait(
+              ['able', 'baker', 'charlie', 'dozen', 'elapse'].map((name) {
+            delay += delay_between_connections;
+            return new Future.delayed(delay, () => server)
+                .then((server) => testClient(server, name));
+          })))
+      .then((servers) => servers.first.close());
+}
diff --git a/tests/standalone/io/secure_socket_alpn_test.dart b/tests/standalone/io/secure_socket_alpn_test.dart
new file mode 100644
index 0000000..15bb92b
--- /dev/null
+++ b/tests/standalone/io/secure_socket_alpn_test.dart
@@ -0,0 +1,184 @@
+// 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.
+//
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import 'dart:io';
+import 'dart:convert';
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+const String NAME_LENGTH_ERROR = 'Length of protocol must be between 1 and 255';
+
+const String MESSAGE_LENGTH_ERROR =
+    'The maximum message length supported is 2^13-1';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext clientContext() => new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+SecurityContext serverContext() => new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+// Tests that client/server with same protocol can securely establish a
+// connection, negotiate the protocol and can send data to each other.
+void testSuccessfulAlpnNegotiationConnection(List<String> clientProtocols,
+    List<String> serverProtocols, String? selectedProtocol) {
+  asyncStart();
+  var sContext = serverContext()..setAlpnProtocols(serverProtocols, true);
+  SecureServerSocket.bind('localhost', 0, sContext)
+      .then((SecureServerSocket server) {
+    asyncStart();
+    server.first.then((SecureSocket socket) {
+      Expect.equals(selectedProtocol, socket.selectedProtocol);
+      socket
+        ..write('server message')
+        ..close();
+      ascii.decoder.bind(socket).join('').then((String s) {
+        Expect.equals('client message', s);
+        asyncEnd();
+      });
+    });
+
+    asyncStart();
+    SecureSocket.connect('localhost', server.port,
+            context: clientContext(), supportedProtocols: clientProtocols)
+        .then((socket) {
+      Expect.equals(selectedProtocol, socket.selectedProtocol);
+      socket
+        ..write('client message')
+        ..close();
+      ascii.decoder.bind(socket).join('').then((String s) {
+        Expect.equals('server message', s);
+        server.close();
+        asyncEnd();
+      });
+    });
+
+    asyncEnd();
+  });
+}
+
+void testInvalidArgument(List<String> protocols, String errorIncludes) {
+  testInvalidArgumentServerContext(protocols, errorIncludes);
+  testInvalidArgumentClientContext(protocols, errorIncludes);
+  testInvalidArgumentClientConnect(protocols, errorIncludes);
+}
+
+void testInvalidArgumentServerContext(
+    List<String> protocols, String errorIncludes) {
+  Expect.throws(() => serverContext().setAlpnProtocols(protocols, true), (e) {
+    Expect.isTrue(e is ArgumentError);
+    Expect.isTrue(e.toString().contains(errorIncludes));
+    return true;
+  });
+}
+
+void testInvalidArgumentClientContext(
+    List<String> protocols, String errorIncludes) {
+  Expect.throws(() => clientContext().setAlpnProtocols(protocols, false), (e) {
+    Expect.isTrue(e is ArgumentError);
+    Expect.isTrue(e.toString().contains(errorIncludes));
+    return true;
+  });
+}
+
+void testInvalidArgumentClientConnect(
+    List<String> protocols, String errorIncludes) {
+  asyncStart();
+  var sContext = serverContext()..setAlpnProtocols(['abc'], true);
+  SecureServerSocket.bind('localhost', 0, sContext).then((server) async {
+    asyncStart();
+    server.listen((SecureSocket socket) {
+      Expect.fail(
+          "Unexpected connection made to server, with bad client argument");
+    }, onError: (e) {
+      Expect.fail("Unexpected error on server stream: $e");
+    }, onDone: () {
+      asyncEnd();
+    });
+
+    asyncStart();
+    SecureSocket.connect('localhost', server.port,
+            context: clientContext(), supportedProtocols: protocols)
+        .then((socket) {
+      Expect.fail(
+          "Unexpected connection made from client, with bad client argument");
+    }, onError: (e) {
+      Expect.isTrue(e is ArgumentError);
+      Expect.isTrue(e.toString().contains(errorIncludes));
+      server.close();
+      asyncEnd();
+    });
+    asyncEnd();
+  });
+}
+
+main() {
+  final longname256 = 'p' * 256;
+  final String longname255 = 'p' * 255;
+  final String strangelongname255 = 'ø' + 'p' * 253;
+  final String strangelongname256 = 'ø' + 'p' * 254;
+
+  // This produces a message of (1 << 13) - 2 bytes. 2^12 -1 strings are each
+  // encoded by 1 length byte and 1 ascii byte.
+  final List<String> manyProtocols =
+      new Iterable.generate((1 << 12) - 1, (i) => '0').toList();
+
+  // This produces a message of (1 << 13) bytes. 2^12 strings are each
+  // encoded by 1 length byte and 1 ascii byte.
+  final List<String> tooManyProtocols =
+      new Iterable.generate((1 << 12), (i) => '0').toList();
+
+  // Protocols are in order of decreasing priority. The server will select
+  // the first protocol from its list that has a match in the client list.
+  // Test successful negotiation, including priority.
+  testSuccessfulAlpnNegotiationConnection(['a'], ['a'], 'a');
+
+  testSuccessfulAlpnNegotiationConnection(
+      [longname255], [longname255], longname255);
+
+  testSuccessfulAlpnNegotiationConnection(
+      [strangelongname255], [strangelongname255], strangelongname255);
+  testSuccessfulAlpnNegotiationConnection(manyProtocols, manyProtocols, '0');
+  testSuccessfulAlpnNegotiationConnection(
+      ['a', 'b', 'c'], ['a', 'b', 'c'], 'a');
+
+  testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'], ['c'], 'c');
+
+  // Server precedence.
+  testSuccessfulAlpnNegotiationConnection(
+      ['a', 'b', 'c'], ['c', 'b', 'a'], 'c');
+
+  testSuccessfulAlpnNegotiationConnection(['c'], ['a', 'b', 'c'], 'c');
+
+  testSuccessfulAlpnNegotiationConnection(
+      ['s1', 'b', 'e1'], ['s2', 'b', 'e2'], 'b');
+  // Test no protocol negotiation support
+  testSuccessfulAlpnNegotiationConnection([], ['a', 'b', 'c'], null);
+
+  testSuccessfulAlpnNegotiationConnection([], [], null);
+
+  testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'], [], null);
+
+  testSuccessfulAlpnNegotiationConnection([], ['a', 'b', 'c'], null);
+
+  // Test non-overlapping protocols.  The ALPN RFC says the connection
+  // should be terminated, but OpenSSL continues as if no ALPN is present.
+  // Issue  https://github.com/dart-lang/sdk/issues/23580
+  // Chromium issue https://code.google.com/p/chromium/issues/detail?id=497770
+  testSuccessfulAlpnNegotiationConnection(['a'], ['b'], null);
+
+  // Test too short / too long protocol names.
+  testInvalidArgument([longname256], NAME_LENGTH_ERROR);
+  testInvalidArgument([strangelongname256], NAME_LENGTH_ERROR);
+  testInvalidArgument([''], NAME_LENGTH_ERROR);
+  testInvalidArgument(tooManyProtocols, MESSAGE_LENGTH_ERROR);
+}
diff --git a/tests/standalone/io/secure_socket_argument_test.dart b/tests/standalone/io/secure_socket_argument_test.dart
new file mode 100644
index 0000000..676801e
--- /dev/null
+++ b/tests/standalone/io/secure_socket_argument_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.
+
+import "package:expect/expect.dart";
+import "dart:io";
+
+const SERVER_ADDRESS = "127.0.0.1";
+
+void testServerSocketArguments() {
+  Expect.throws(() => SecureServerSocket.bind(SERVER_ADDRESS, 65536, null));
+  Expect.throws(() => SecureServerSocket.bind(SERVER_ADDRESS, -1, null));
+  Expect.throws(() =>
+      SecureServerSocket.bind(SERVER_ADDRESS, 0, "not a context" as dynamic));
+}
+
+void main() {
+  testServerSocketArguments();
+}
diff --git a/tests/standalone/io/secure_socket_renegotiate_client.dart b/tests/standalone/io/secure_socket_renegotiate_client.dart
new file mode 100644
index 0000000..775891b
--- /dev/null
+++ b/tests/standalone/io/secure_socket_renegotiate_client.dart
@@ -0,0 +1,72 @@
+// 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.
+
+// Client for secure_socket_renegotiate_test, that runs in a subprocess.
+// The test verifies that client certificates work, if the client and server
+// are in separate processes, and that connection renegotiation can request
+// a client certificate to be sent.
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+
+const HOST_NAME = "localhost";
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+class ExpectException implements Exception {
+  ExpectException(this.message);
+  String toString() => message;
+  String message;
+}
+
+void expectEquals(expected, actual) {
+  if (actual != expected) {
+    throw new ExpectException('Expected $expected, found $actual');
+  }
+}
+
+void expect(condition) {
+  if (!condition) {
+    throw new ExpectException('');
+  }
+}
+
+void runClient(int port) {
+  SecureSocket.connect(HOST_NAME, port, context: clientContext)
+      .then((SecureSocket socket) {
+    X509Certificate? certificate = socket.peerCertificate;
+    expect(certificate != null);
+    expectEquals('CN=localhost', certificate!.subject);
+    expectEquals('CN=myauthority', certificate.issuer);
+    StreamIterator<String> input = new StreamIterator(
+        socket.transform(utf8.decoder).transform(new LineSplitter()));
+    socket.writeln('first');
+    input.moveNext().then((success) {
+      expect(success);
+      expectEquals('first reply', input.current);
+      socket.renegotiate();
+      socket.writeln('renegotiated');
+      return input.moveNext();
+    }).then((success) {
+      expect(success);
+      expectEquals('server renegotiated', input.current);
+      X509Certificate? certificate = socket.peerCertificate;
+      expect(certificate != null);
+      expectEquals("CN=localhost", certificate!.subject);
+      expectEquals("CN=myauthority", certificate.issuer);
+      socket.writeln('second');
+      return input.moveNext();
+    }).then((success) {
+      expect(success != true);
+      socket.close();
+    });
+  });
+}
+
+void main(List<String> args) {
+  runClient(int.parse(args[0]));
+}
diff --git a/tests/standalone/io/secure_socket_renegotiate_test.dart b/tests/standalone/io/secure_socket_renegotiate_test.dart
new file mode 100644
index 0000000..05aa2f1
--- /dev/null
+++ b/tests/standalone/io/secure_socket_renegotiate_test.dart
@@ -0,0 +1,85 @@
+// 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.
+//
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=secure_socket_renegotiate_client.dart
+
+// This test verifies that client certificates work, if the client and server
+// are in separate processes, and that connection renegotiation works, and
+// can request a client certificate to be sent.
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+const HOST_NAME = "localhost";
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+Future<SecureServerSocket> runServer() {
+  return SecureServerSocket.bind(HOST_NAME, 0, serverContext)
+      .then((SecureServerSocket server) {
+    server.listen((SecureSocket socket) {
+      Expect.isNull(socket.peerCertificate);
+
+      StreamIterator<String> input = new StreamIterator(
+          utf8.decoder.bind(socket).transform(new LineSplitter()));
+      input.moveNext().then((success) {
+        Expect.isTrue(success);
+        Expect.equals('first', input.current);
+        socket.writeln('first reply');
+        return input.moveNext();
+      }).then((success) {
+        Expect.isTrue(success);
+        Expect.equals('renegotiated', input.current);
+        Expect.isNull(socket.peerCertificate);
+        socket.renegotiate(
+            requestClientCertificate: true,
+            requireClientCertificate: true,
+            useSessionCache: false);
+        socket.writeln('server renegotiated');
+        return input.moveNext();
+      }).then((success) {
+        Expect.isTrue(success);
+        Expect.equals('second', input.current);
+        X509Certificate certificate = socket.peerCertificate!;
+        Expect.equals("CN=localhost", certificate.subject);
+        Expect.equals("CN=myauthority", certificate.issuer);
+        server.close();
+        socket.close();
+      });
+    });
+    return server;
+  });
+}
+
+void main() {
+  runServer().then((SecureServerSocket server) {
+    var clientScript = Platform.script
+        .resolve('secure_socket_renegotiate_client.dart')
+        .toFilePath();
+    Process.run(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..addAll([clientScript, server.port.toString()]))
+        .then((ProcessResult result) {
+      if (result.exitCode != 0) {
+        print("Client failed, stdout:");
+        print(result.stdout);
+        print("  stderr:");
+        print(result.stderr);
+        Expect.fail('Client subprocess exit code: ${result.exitCode}');
+      }
+    });
+  });
+}
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
new file mode 100644
index 0000000..0293f4d
--- /dev/null
+++ b/tests/standalone/io/secure_socket_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=certificates/server_chain.p12
+// OtherResources=certificates/server_key.p12
+// OtherResources=certificates/trusted_certs.p12
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "dart:async";
+import "dart:io";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext(String certType, String password) =>
+    new SecurityContext()
+      ..useCertificateChain(localFile('certificates/server_chain.$certType'),
+          password: password)
+      ..usePrivateKey(localFile('certificates/server_key.$certType'),
+          password: password);
+
+SecurityContext clientContext(String certType, String password) =>
+    new SecurityContext()
+      ..setTrustedCertificates(
+          localFile('certificates/trusted_certs.$certType'),
+          password: password);
+
+Future<HttpServer> startServer(String certType, String password) {
+  return HttpServer.bindSecure(
+          "localhost", 0, serverContext(certType, password),
+          backlog: 5)
+      .then((server) {
+    server.listen((HttpRequest request) {
+      request.listen((_) {}, onDone: () {
+        request.response.contentLength = 100;
+        for (int i = 0; i < 10; i++) {
+          request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+        }
+        request.response.close();
+      });
+    });
+    return server;
+  });
+}
+
+Future test(String certType, String password) {
+  List<int> body = <int>[];
+  Completer completer = new Completer();
+  startServer(certType, password).then((server) {
+    SecureSocket.connect("localhost", server.port,
+            context: clientContext(certType, password))
+        .then((socket) {
+      socket.write("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n");
+      socket.close();
+      socket.listen((List<int> data) {
+        body.addAll(data);
+      }, onDone: () {
+        Expect.isTrue(body.length > 100, "$body\n${body.length}");
+        Expect.equals(72, body[0]);
+        Expect.equals(9, body[body.length - 1]);
+        server.close();
+        completer.complete(null);
+      }, onError: (e, trace) {
+        String msg = "Unexpected error $e";
+        if (trace != null) msg += "\nStackTrace: $trace";
+        Expect.fail(msg);
+        completer.complete(null);
+      });
+    });
+  });
+  return completer.future;
+}
+
+void testConnectTimeout() {
+  asyncStart();
+  Duration timeout = new Duration(milliseconds: 20);
+  SecureSocket.connect("8.8.8.7", 80, timeout: timeout).then((socket) {
+    Expect.fail("Unexpected connection made.");
+    asyncEnd();
+  }).catchError((e) {
+    Expect.isTrue(e is SocketException);
+    asyncEnd();
+  });
+}
+
+main() async {
+  asyncStart();
+  await test('pem', 'dartdart');
+  await test('p12', 'dartdart');
+  testConnectTimeout();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/secure_unauthorized_client.dart b/tests/standalone/io/secure_unauthorized_client.dart
new file mode 100644
index 0000000..184365b
--- /dev/null
+++ b/tests/standalone/io/secure_unauthorized_client.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.
+
+// Client for secure_bad_certificate_test, that runs in a subprocess.
+// The test verifies that the client bad certificate callback works.
+
+import "dart:async";
+import "dart:io";
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+class ExpectException implements Exception {
+  ExpectException(this.message);
+  String toString() => "ExpectException: $message";
+  String message;
+}
+
+void expect(condition) {
+  if (!condition) {
+    throw new ExpectException('');
+  }
+}
+
+const HOST_NAME = "localhost";
+
+Future runClients(int port) {
+  var testFutures = <Future>[];
+  for (int i = 0; i < 20; ++i) {
+    testFutures.add(
+        SecureSocket.connect(HOST_NAME, port, context: clientContext).then(
+            (SecureSocket socket) {
+      expect(false);
+    }, onError: (e) {
+      expect(e is HandshakeException || e is SocketException);
+    }));
+  }
+  return Future.wait(testFutures);
+}
+
+void main(List<String> args) {
+  runClients(int.parse(args[0])).then((_) => print('SUCCESS'));
+}
diff --git a/tests/standalone/io/secure_unauthorized_test.dart b/tests/standalone/io/secure_unauthorized_test.dart
new file mode 100644
index 0000000..c31191a
--- /dev/null
+++ b/tests/standalone/io/secure_unauthorized_test.dart
@@ -0,0 +1,62 @@
+// 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.
+
+// OtherResources=certificates/untrusted_server_chain.pem
+// OtherResources=certificates/untrusted_server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=secure_unauthorized_client.dart
+
+// This test verifies that failing secure connection attempts always complete
+// their returned future.
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "dart:async";
+import "dart:io";
+
+const HOST_NAME = "localhost";
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/untrusted_server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/untrusted_server_key.pem'),
+      password: 'dartdart');
+
+Future<SecureServerSocket> runServer() {
+  return SecureServerSocket.bind(HOST_NAME, 0, serverContext)
+      .then((SecureServerSocket server) {
+    server.listen((SecureSocket socket) {
+      socket.listen((_) {}, onDone: () {
+        socket.close();
+      });
+    }, onError: (e) => Expect.isTrue(e is HandshakeException));
+    return server;
+  });
+}
+
+void main() {
+  var clientScript = localFile('secure_unauthorized_client.dart');
+
+  Future clientProcess(int port) {
+    List<String> args = new List<String>.from(Platform.executableArguments);
+    args.add(clientScript);
+    args.add(port.toString());
+    return Process.run(Platform.executable, args).then((ProcessResult result) {
+      if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
+        print("Client failed");
+        print("  stdout:");
+        print(result.stdout);
+        print("  stderr:");
+        print(result.stderr);
+        Expect.fail('Client subprocess exit code: ${result.exitCode}');
+      }
+    });
+  }
+
+  runServer().then((server) {
+    clientProcess(server.port).then((_) {
+      server.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/server_socket_close_listen_test.dart b/tests/standalone/io/server_socket_close_listen_test.dart
new file mode 100644
index 0000000..cfeb11a
--- /dev/null
+++ b/tests/standalone/io/server_socket_close_listen_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void serverSocketCloseListenTest() {
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.destroy();
+      server.close();
+      server.listen((incoming) => Expect.fail("Unexpected socket"),
+          onDone: asyncEnd);
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  serverSocketCloseListenTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/server_socket_exception_test.dart b/tests/standalone/io/server_socket_exception_test.dart
new file mode 100644
index 0000000..16d1c34
--- /dev/null
+++ b/tests/standalone/io/server_socket_exception_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void serverSocketExceptionTest() {
+  bool exceptionCaught = false;
+  bool wrongExceptionCaught = false;
+
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Expect.isNotNull(server);
+    server.close();
+    try {
+      server.close();
+    } on SocketException catch (ex) {
+      exceptionCaught = true;
+    } catch (ex) {
+      wrongExceptionCaught = true;
+    }
+    Expect.equals(false, exceptionCaught);
+    Expect.equals(true, !wrongExceptionCaught);
+
+    // Test invalid host.
+    ServerSocket.bind("__INVALID_HOST__", 0).then((server) {
+      Expect.fail('Connection succeeded.');
+    }).catchError((e) => Expect.isTrue(e is SocketException));
+  });
+}
+
+main() {
+  asyncStart();
+  serverSocketExceptionTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/server_socket_listen_close_test.dart b/tests/standalone/io/server_socket_listen_close_test.dart
new file mode 100644
index 0000000..5a1fb71
--- /dev/null
+++ b/tests/standalone/io/server_socket_listen_close_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void serverSocketListenCloseTest() {
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      server.listen((incoming) {
+        incoming.destroy();
+        socket.destroy();
+        server.close();
+      }, onDone: asyncEnd);
+    });
+  });
+}
+
+main() {
+  asyncStart();
+  serverSocketListenCloseTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/shared_socket_test.dart b/tests/standalone/io/shared_socket_test.dart
new file mode 100644
index 0000000..7f70a14
--- /dev/null
+++ b/tests/standalone/io/shared_socket_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:http/http.dart' as http;
+
+void main() async {
+  final workers = List<ServerWorker>.generate(4, (i) => ServerWorker(i));
+  workers.forEach((w) => w.start());
+  await Future.delayed(Duration(seconds: 1));
+  // spawn client isolate
+  final clientisolate = await Isolate.spawn(client, 0);
+  // Wait for 20 secs. It used to crash within 10 seconds.
+  await Future.delayed(Duration(seconds: 20));
+
+  workers.forEach((w) {
+    w.respawn = false;
+    w.terminate();
+  });
+  print('kill client isolates');
+  clientisolate.kill();
+}
+
+class ServerWorker {
+  final int workerid;
+  Isolate? _isolate;
+  bool respawn = true;
+
+  ServerWorker(this.workerid);
+
+  Future<void> start() async {
+    final onExit = ReceivePort();
+    onExit.listen((_) {
+      onExit.close();
+      // Respawn another isolate
+      if (respawn) start();
+    });
+    _isolate = await Isolate.spawn(_main, workerid,
+        errorsAreFatal: true, onExit: onExit.sendPort);
+    if (workerid == 0) terminate();
+  }
+
+  void terminate() {
+    Future.delayed(Duration(seconds: 1), () {
+      print('terminate ${workerid}');
+      _isolate?.kill();
+      _isolate = null;
+    });
+  }
+
+  static _main(int workerid) async {
+    bool shared = true;
+    final server = await HttpServer.bind('::1', 1234, shared: shared);
+    server.listen((HttpRequest request) {
+      print('from worker ${workerid}');
+      final response = request.response;
+      response.statusCode = HttpStatus.ok;
+      response.write('server worker ${workerid}');
+      response.close();
+    });
+  }
+}
+
+Future<String> get(String url) async {
+  while (true) {
+    try {
+      await http.get(url);
+      return '';
+    } catch (err) {}
+  }
+}
+
+void client(int i) async {
+  while (true) {
+    final futures = <Future>[];
+    final numAtOnce = 16; // enough to keep the server busy
+    for (int i = 0; i < numAtOnce; ++i) {
+      futures.add(get('http://localhost:1234').then((_) {}));
+    }
+    await Future.wait(futures);
+  }
+}
diff --git a/tests/standalone/io/signal_test_script.dart b/tests/standalone/io/signal_test_script.dart
new file mode 100644
index 0000000..772c2af
--- /dev/null
+++ b/tests/standalone/io/signal_test_script.dart
@@ -0,0 +1,41 @@
+// 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:io";
+import "dart:async";
+
+void main(args) {
+  // This process should die if it never receives a signal.
+  var timeout = new Timer(new Duration(seconds: 25), () => exit(1));
+  for (var arg in args) {
+    var signal;
+    switch (arg) {
+      case 'SIGHUP':
+        signal = ProcessSignal.sighup;
+        break;
+      case 'SIGINT':
+        signal = ProcessSignal.sigint;
+        break;
+      case 'SIGTERM':
+        signal = ProcessSignal.sigterm;
+        break;
+      case 'SIGUSR1':
+        signal = ProcessSignal.sigusr1;
+        break;
+      case 'SIGUSR2':
+        signal = ProcessSignal.sigusr2;
+        break;
+      case 'SIGWINCH':
+        signal = ProcessSignal.sigwinch;
+        break;
+    }
+    signal.watch().first.then((s) {
+      if (signal != s) exit(1);
+      if (signal.toString() != arg) exit(1);
+      print(signal);
+      exit(0);
+    });
+  }
+  print("ready");
+}
diff --git a/tests/standalone/io/signals_exception_test.dart b/tests/standalone/io/signals_exception_test.dart
new file mode 100644
index 0000000..28f552e
--- /dev/null
+++ b/tests/standalone/io/signals_exception_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.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+main() {
+  var ps = ProcessSignal.sigint.watch().listen((signal) {
+    Expect.fail("Unreachable");
+  });
+  throw "Death"; //# 01: runtime error
+  ps.cancel();
+}
diff --git a/tests/standalone/io/signals_test.dart b/tests/standalone/io/signals_test.dart
new file mode 100644
index 0000000..0ada166
--- /dev/null
+++ b/tests/standalone/io/signals_test.dart
@@ -0,0 +1,147 @@
+// 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.
+
+// OtherResources=signal_test_script.dart
+// OtherResources=signals_test_script.dart
+
+import "dart:io";
+import "dart:convert";
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void testSignals(int usr1Expect, int usr2Expect,
+    [int? usr1Send, int? usr2Send, bool shouldFail = false]) {
+  if (usr1Send == null) usr1Send = usr1Expect;
+  if (usr2Send == null) usr2Send = usr2Expect;
+  asyncStart();
+  Process.start(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..addAll([
+              Platform.script.resolve('signals_test_script.dart').toFilePath(),
+              usr1Expect.toString(),
+              usr2Expect.toString()
+            ]))
+      .then((process) {
+    process.stdin.close();
+    process.stderr.drain();
+    int v = 0;
+    process.stdout.listen((out) {
+      // Send as many signals as 'ready\n' received on stdout
+      int count = out.where((c) => c == '\n'.codeUnitAt(0)).length;
+      for (int i = 0; i < count; i++) {
+        if (v < usr1Send!) {
+          process.kill(ProcessSignal.sigusr1);
+        } else if (v < usr1Send + usr2Send!) {
+          process.kill(ProcessSignal.sigusr2);
+        }
+        v++;
+      }
+    });
+    process.exitCode.then((exitCode) {
+      Expect.equals(shouldFail, exitCode != 0);
+      asyncEnd();
+    });
+  });
+}
+
+void testSignal(ProcessSignal signal) {
+  asyncStart();
+  Process.start(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..addAll([
+              Platform.script.resolve('signal_test_script.dart').toFilePath(),
+              signal.toString()
+            ]))
+      .then((process) {
+    process.stdin.close();
+    process.stderr.drain();
+
+    var output = "";
+    process.stdout.transform(utf8.decoder).listen((str) {
+      output += str;
+      if (output == 'ready\n') {
+        process.kill(signal);
+      }
+    }, onDone: () {
+      Expect.equals('ready\n$signal\n', output);
+    });
+    process.exitCode.then((exitCode) {
+      Expect.equals(0, exitCode);
+      asyncEnd();
+    });
+  });
+}
+
+void testMultipleSignals(List<ProcessSignal> signals) {
+  for (var signal in signals) {
+    asyncStart();
+    Process.start(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..add(Platform.script
+                  .resolve('signal_test_script.dart')
+                  .toFilePath())
+              ..addAll(signals.map((s) => s.toString())))
+        .then((process) {
+      process.stdin.close();
+      process.stderr.drain();
+
+      var output = "";
+      process.stdout.transform(utf8.decoder).listen((str) {
+        output += str;
+        if (output == 'ready\n') {
+          process.kill(signal);
+        }
+      }, onDone: () {
+        Expect.equals('ready\n$signal\n', output);
+      });
+      process.exitCode.then((exitCode) {
+        Expect.equals(0, exitCode);
+        asyncEnd();
+      });
+    });
+  }
+}
+
+void testListenCancel() {
+  for (int i = 0; i < 10; i++) {
+    ProcessSignal.sigint.watch().listen(null).cancel();
+  }
+}
+
+void main() {
+  testListenCancel();
+  if (Platform.isWindows) return;
+  testSignals(0, 0);
+  testSignals(1, 0);
+  testSignals(0, 1);
+  testSignals(1, 1);
+  testSignals(10, 10);
+  testSignals(10, 1);
+  testSignals(1, 10);
+  testSignals(1, 0, 0, 1, true);
+  testSignals(0, 1, 1, 0, true);
+
+  testSignal(ProcessSignal.sighup);
+  testSignal(ProcessSignal.sigint);
+  testSignal(ProcessSignal.sigterm);
+  testSignal(ProcessSignal.sigusr1);
+  testSignal(ProcessSignal.sigusr2);
+  testSignal(ProcessSignal.sigwinch);
+
+  testMultipleSignals([
+    ProcessSignal.sighup,
+    ProcessSignal.sigint,
+    ProcessSignal.sigterm,
+    ProcessSignal.sigusr1,
+    ProcessSignal.sigusr2,
+    ProcessSignal.sigwinch,
+  ]);
+}
diff --git a/tests/standalone/io/signals_test_script.dart b/tests/standalone/io/signals_test_script.dart
new file mode 100644
index 0000000..b5b5210
--- /dev/null
+++ b/tests/standalone/io/signals_test_script.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:io";
+
+void main(args) {
+  int usr1Count = int.parse(args[0]);
+  int usr2Count = int.parse(args[1]);
+  var sub1;
+  var sub2;
+  void check() {
+    if (usr1Count < 0 || usr2Count < 0) exit(1);
+    if (usr1Count == 0 && usr2Count == 0) {
+      sub1.cancel();
+      sub2.cancel();
+    }
+    print("ready");
+  }
+
+  sub1 = ProcessSignal.sigusr1.watch().listen((signal) {
+    if (signal != ProcessSignal.sigusr1) exit(1);
+    usr1Count--;
+    check();
+  });
+  sub2 = ProcessSignal.sigusr2.watch().listen((signal) {
+    if (signal != ProcessSignal.sigusr2) exit(1);
+    usr2Count--;
+    check();
+  });
+  check();
+}
diff --git a/tests/standalone/io/sleep_test.dart b/tests/standalone/io/sleep_test.dart
new file mode 100644
index 0000000..f240296
--- /dev/null
+++ b/tests/standalone/io/sleep_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.
+
+import "dart:io";
+import "package:unittest/unittest.dart";
+
+test(int milliseconds) {
+  var watch = new Stopwatch();
+  watch.start();
+  sleep(new Duration(milliseconds: milliseconds));
+  watch.stop();
+  expect(watch.elapsedMilliseconds, greaterThanOrEqualTo(milliseconds));
+}
+
+main() {
+  test(0);
+  test(1);
+  test(10);
+  test(100);
+  bool sawError = false;
+  try {
+    sleep(new Duration(milliseconds: -1));
+    expect(false, isTrue); // should not reach here.
+  } on ArgumentError catch (e) {
+    sawError = true;
+  }
+  expect(sawError, isTrue);
+}
diff --git a/tests/standalone/io/snapshot_fail_script.dart b/tests/standalone/io/snapshot_fail_script.dart
new file mode 100644
index 0000000..86099d8
--- /dev/null
+++ b/tests/standalone/io/snapshot_fail_script.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.
+
+main() {
+  print("Oops!");
diff --git a/tests/standalone/io/snapshot_fail_test.dart b/tests/standalone/io/snapshot_fail_test.dart
new file mode 100644
index 0000000..b5b681d
--- /dev/null
+++ b/tests/standalone/io/snapshot_fail_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.
+
+// Dart test making sure we don't create an empty snapshot file when there
+// is an error in the script.
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+main() {
+  // Try to generate a snapshot.
+  File thisscript = new File.fromUri(Platform.script);
+  Directory dir = thisscript.parent;
+  String snapshot = "${dir.path}/dummy.snapshot";
+  String script = "${dir.path}/snapshot_fail_script.dart";
+  var pr =
+      Process.runSync(Platform.executable, ["--snapshot=$snapshot", script]);
+
+  // There should be no dummy.snapshot file created.
+  File dummy = new File(snapshot);
+  bool exists = dummy.existsSync();
+  if (exists) {
+    dummy.deleteSync();
+  }
+  Expect.isFalse(exists);
+}
diff --git a/tests/standalone/io/socket_arguments_test.dart b/tests/standalone/io/socket_arguments_test.dart
new file mode 100644
index 0000000..251adc6
--- /dev/null
+++ b/tests/standalone/io/socket_arguments_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  Expect.throws(() => ServerSocket.bind("127.0.0.1", 65536));
+  Expect.throws(() => ServerSocket.bind("127.0.0.1", -1));
+  Expect.throws(() => ServerSocket.bind("127.0.0.1", 0, backlog: -1));
+}
diff --git a/tests/standalone/io/socket_bind_test.dart b/tests/standalone/io/socket_bind_test.dart
new file mode 100644
index 0000000..0cc540e
--- /dev/null
+++ b/tests/standalone/io/socket_bind_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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+
+import 'test_utils.dart' show retry, throws;
+
+Future testBindShared(String host, bool v6Only) async {
+  final socket = await ServerSocket.bind(host, 0, v6Only: v6Only, shared: true);
+  Expect.isTrue(socket.port > 0);
+
+  final socket2 =
+      await ServerSocket.bind(host, socket.port, v6Only: v6Only, shared: true);
+
+  Expect.equals(socket.address.address, socket2.address.address);
+  Expect.equals(socket.port, socket2.port);
+
+  await socket.close();
+  await socket2.close();
+}
+
+Future negTestBindSharedMismatch(String host, bool v6Only) async {
+  final socket = await ServerSocket.bind(host, 0, v6Only: v6Only);
+  Expect.isTrue(socket.port > 0);
+
+  await throws(() => ServerSocket.bind(host, socket.port, v6Only: v6Only),
+      (error) => error is SocketException && '$error'.contains('shared flag'));
+  await socket.close();
+}
+
+Future negTestBindV6OnlyMismatch(String host, bool v6Only) async {
+  final socket = await ServerSocket.bind(host, 0, v6Only: v6Only, shared: true);
+  Expect.isTrue(socket.port > 0);
+
+  await throws(
+      () => ServerSocket.bind(host, socket.port, v6Only: !v6Only, shared: true),
+      (error) => error is SocketException && '$error'.contains('v6Only flag'));
+
+  await socket.close();
+}
+
+Future testBindDifferentAddresses(InternetAddress addr1, InternetAddress addr2,
+    bool addr1V6Only, bool addr2V6Only) async {
+  var socket =
+      await ServerSocket.bind(addr1, 0, v6Only: addr1V6Only, shared: false);
+
+  try {
+    Expect.isTrue(socket.port > 0);
+
+    var socket2 = await ServerSocket.bind(addr2, socket.port,
+        v6Only: addr2V6Only, shared: false);
+    try {
+      Expect.equals(socket.port, socket2.port);
+    } finally {
+      await socket2.close();
+    }
+  } finally {
+    await socket.close();
+  }
+}
+
+Future testListenCloseListenClose(String host) async {
+  ServerSocket socket = await ServerSocket.bind(host, 0, shared: true);
+  ServerSocket socket2 =
+      await ServerSocket.bind(host, socket.port, shared: true);
+
+  var subscription = socket.listen((_) {
+    throw 'error';
+  });
+  subscription.cancel();
+  await socket.close();
+
+  // The second socket should have kept the OS socket alive. We can therefore
+  // test if it is working correctly.
+
+  // For robustness we ignore any clients unrelated to this test.
+  final receivedClientPorts = <int>[];
+  socket2.listen((Socket client) async {
+    receivedClientPorts.add(client.remotePort);
+    await Future.wait([client.drain(), client.close()]);
+  });
+
+  final client = await Socket.connect(host, socket2.port);
+  final clientPort = client.port;
+  await client.close();
+  await client.drain();
+
+  Expect.isTrue(receivedClientPorts.contains(clientPort));
+
+  // Close the second server socket.
+  await socket2.close();
+}
+
+main() async {
+  await retry(() async {
+    await testBindDifferentAddresses(
+        InternetAddress.anyIPv6, InternetAddress.anyIPv4, true, false);
+  });
+  await retry(() async {
+    await testBindDifferentAddresses(
+        InternetAddress.anyIPv4, InternetAddress.anyIPv6, false, true);
+  });
+
+  for (var host in ['127.0.0.1', '::1']) {
+    await testBindShared(host, false);
+    await testBindShared(host, true);
+
+    await negTestBindSharedMismatch(host, false);
+    await negTestBindSharedMismatch(host, true);
+
+    await negTestBindV6OnlyMismatch(host, true);
+    await negTestBindV6OnlyMismatch(host, false);
+
+    await testListenCloseListenClose(host);
+  }
+}
diff --git a/tests/standalone/io/socket_cancel_connect_test.dart b/tests/standalone/io/socket_cancel_connect_test.dart
new file mode 100644
index 0000000..7a2e112
--- /dev/null
+++ b/tests/standalone/io/socket_cancel_connect_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  asyncStart();
+  Duration timeout = new Duration(milliseconds: 20);
+  Socket.startConnect("8.8.8.7", 80).then((task) {
+    task.socket.timeout(timeout, onTimeout: () {
+      task.cancel();
+    });
+    task.socket.then((socket) {
+      Expect.fail("Unexpected connection made.");
+      asyncEnd();
+    }).catchError((e) {
+      print(e);
+      Expect.isTrue(e is SocketException);
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_close_test.dart b/tests/standalone/io/socket_close_test.dart
new file mode 100644
index 0000000..72a15de
--- /dev/null
+++ b/tests/standalone/io/socket_close_test.dart
@@ -0,0 +1,389 @@
+// 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=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+//
+// Test socket close events.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+const SERVERSHUTDOWN = -1;
+const ITERATIONS = 10;
+
+Future sendReceive(SendPort port, message) {
+  ReceivePort receivePort = new ReceivePort();
+  port.send([message, receivePort.sendPort]);
+  return receivePort.first;
+}
+
+class SocketClose {
+  SocketClose.start(this._mode, this._done)
+      : _readBytes = 0,
+        _dataEvents = 0,
+        _closeEvents = 0,
+        _errorEvents = 0,
+        _iterations = 0 {
+    initialize();
+  }
+
+  void proceed() {
+    if (_iterations < ITERATIONS) {
+      Timer.run(sendData);
+    } else {
+      shutdown();
+    }
+  }
+
+  void sendData() {
+    void dataHandler(Uint8List bytes) {
+      switch (_mode) {
+        case 0:
+        case 1:
+        case 2:
+          Expect.fail("No data expected");
+          break;
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+          _readBytes += bytes.length;
+          if ((_readBytes % 5) == 0) {
+            _dataEvents++;
+          }
+          break;
+        default:
+          Expect.fail("Unknown test mode");
+      }
+    }
+
+    void closeHandler(socket) {
+      _closeEvents++;
+      switch (_mode) {
+        case 0:
+        case 1:
+          socket.close();
+          break;
+        case 2:
+        case 3:
+          socket.close();
+          proceed();
+          break;
+        case 4:
+          proceed();
+          break;
+        case 5:
+          socket.close();
+          proceed();
+          break;
+        case 6:
+          proceed();
+          break;
+        default:
+          Expect.fail("Unknown test mode");
+      }
+    }
+
+    void errorHandler(Socket socket) {
+      _errorEvents++;
+      socket.close();
+    }
+
+    void connectHandler(socket) {
+      socket.listen(dataHandler,
+          onDone: () => closeHandler(socket),
+          onError: (error) => errorHandler(socket));
+
+      void writeHello() {
+        socket.write("Hello");
+      }
+
+      _iterations++;
+      switch (_mode) {
+        case 0:
+          socket.destroy();
+          proceed();
+          break;
+        case 1:
+          writeHello();
+          socket.destroy();
+          proceed();
+          break;
+        case 2:
+        case 3:
+          writeHello();
+          break;
+        case 4:
+          writeHello();
+          socket.close(); // Half close.
+          break;
+        case 5:
+          writeHello();
+          break;
+        case 6:
+          writeHello();
+          socket.close(); // Half close.
+          break;
+        default:
+          Expect.fail("Unknown test mode");
+      }
+    }
+
+    Socket.connect(SocketCloseServer.HOST, _port).then(connectHandler);
+  }
+
+  void initialize() {
+    ReceivePort receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startSocketCloseServer, receivePort.sendPort);
+
+    receivePort.first.then((message) {
+      this._sendPort = message;
+      sendReceive(_sendPort, _mode).then((port) {
+        this._port = port;
+        proceed();
+      });
+    });
+  }
+
+  void shutdown() {
+    sendReceive(_sendPort, SERVERSHUTDOWN).then((_) {
+      _done();
+    });
+
+    switch (_mode) {
+      case 0:
+      case 1:
+        Expect.equals(0, _dataEvents);
+        Expect.equals(ITERATIONS, _closeEvents);
+        break;
+      case 2:
+        Expect.equals(0, _dataEvents);
+        Expect.equals(ITERATIONS, _closeEvents);
+        break;
+      case 3:
+      case 4:
+        Expect.isTrue(_dataEvents <= ITERATIONS);
+        Expect.isTrue(_dataEvents >= 0);
+        Expect.equals(ITERATIONS, _closeEvents);
+        break;
+      case 5:
+      case 6:
+        Expect.equals(ITERATIONS, _dataEvents);
+        Expect.equals(ITERATIONS, _closeEvents);
+        break;
+      default:
+        Expect.fail("Unknown test mode");
+    }
+    Expect.equals(0, _errorEvents);
+  }
+
+  late int _port;
+  late SendPort _sendPort;
+  int _readBytes;
+  int _dataEvents;
+  int _closeEvents;
+  int _errorEvents;
+  int _iterations;
+  int _mode;
+  Function _done;
+}
+
+class ConnectionData {
+  ConnectionData(Socket this.connection) : readBytes = 0;
+  Socket connection;
+  int readBytes;
+}
+
+void startSocketCloseServer(Object replyToObj) {
+  SendPort replyTo = replyToObj as SendPort;
+  var server = new SocketCloseServer();
+  replyTo.send(server.dispatchSendPort);
+}
+
+class SocketCloseServer {
+  static const HOST = "127.0.0.1";
+
+  SocketCloseServer() : _dispatchPort = new ReceivePort() {
+    _dispatchPort.listen(dispatch);
+  }
+
+  void connectionHandler(ConnectionData data) {
+    var connection = data.connection;
+
+    void readBytes(Uint8List bytes, whenFiveBytes) {
+      data.readBytes += bytes.length;
+      Expect.isTrue(data.readBytes <= 5);
+      if (data.readBytes == 5) {
+        whenFiveBytes();
+      }
+    }
+
+    void writeHello() {
+      connection.write("Hello");
+    }
+
+    void dataHandler(Uint8List bytes) {
+      switch (_mode) {
+        case 0:
+          Expect.fail("No data expected");
+          break;
+        case 1:
+          readBytes(bytes, () {
+            _dataEvents++;
+          });
+          break;
+        case 2:
+          readBytes(bytes, () {
+            _dataEvents++;
+            connection.destroy();
+          });
+          break;
+        case 3:
+          readBytes(bytes, () {
+            _dataEvents++;
+            writeHello();
+            connection.destroy();
+          });
+          break;
+        case 4:
+          readBytes(bytes, () {
+            _dataEvents++;
+            writeHello();
+          });
+          break;
+        case 5:
+        case 6:
+          readBytes(bytes, () {
+            _dataEvents++;
+            writeHello();
+            connection.close(); // Half close.
+          });
+          break;
+        default:
+          Expect.fail("Unknown test mode");
+      }
+    }
+
+    void closeHandler() {
+      _closeEvents++;
+      connection.close();
+    }
+
+    void errorHandler(e) {
+      Expect.fail("Socket error $e");
+    }
+
+    _iterations++;
+
+    connection.listen(dataHandler, onDone: closeHandler, onError: errorHandler);
+  }
+
+  void errorHandlerServer(e) {
+    Expect.fail("Server socket error");
+  }
+
+  waitForResult() {
+    // Make sure all iterations have been run. In multiple of these
+    // scenarios it is possible to get the SERVERSHUTDOWN message
+    // before we have received the last close event on the
+    // server. In these cases we wait for the correct number of
+    // close events.
+    if (_iterations == ITERATIONS &&
+        (_closeEvents == ITERATIONS || (_mode == 2 || _mode == 3))) {
+      switch (_mode) {
+        case 0:
+          Expect.equals(0, _dataEvents);
+          Expect.equals(ITERATIONS, _closeEvents);
+          break;
+        case 1:
+          Expect.isTrue(_dataEvents <= ITERATIONS);
+          Expect.isTrue(_dataEvents >= 0);
+          Expect.equals(ITERATIONS, _closeEvents);
+          break;
+        case 2:
+        case 3:
+          Expect.equals(ITERATIONS, _dataEvents);
+          Expect.equals(ITERATIONS, _closeEvents);
+          break;
+        case 4:
+        case 5:
+        case 6:
+          Expect.equals(ITERATIONS, _dataEvents);
+          Expect.equals(ITERATIONS, _closeEvents);
+          break;
+        default:
+          Expect.fail("Unknown test mode");
+      }
+      Expect.equals(0, _errorEvents);
+      _server.close();
+      _dispatchPort.close();
+      _donePort.send(null);
+    } else {
+      new Timer(new Duration(milliseconds: 100), waitForResult);
+    }
+  }
+
+  SendPort get dispatchSendPort => _dispatchPort.sendPort;
+
+  void dispatch(message) {
+    var command = message[0];
+    SendPort replyTo = message[1];
+    _donePort = replyTo;
+    if (command != SERVERSHUTDOWN) {
+      _readBytes = 0;
+      _errorEvents = 0;
+      _dataEvents = 0;
+      _closeEvents = 0;
+      _iterations = 0;
+      _mode = command;
+      ServerSocket.bind("127.0.0.1", 0).then((server) {
+        _server = server;
+        _server.listen((socket) {
+          var data = new ConnectionData(socket);
+          connectionHandler(data);
+        }, onError: errorHandlerServer);
+        replyTo.send(_server.port);
+      });
+    } else {
+      Timer.run(waitForResult);
+    }
+  }
+
+  late ServerSocket _server;
+  final ReceivePort _dispatchPort;
+  late SendPort _donePort;
+  int _readBytes = 0;
+  int _errorEvents = 0;
+  int _dataEvents = 0;
+  int _closeEvents = 0;
+  int _iterations = 0;
+  int _mode = 0;
+}
+
+main() {
+  // Run the close test in these different "modes".
+  // 0: Client closes without sending at all.
+  // 1: Client sends and destroys.
+  // 2: Client sends. Server destroys.
+  // 3: Client sends. Server responds and destroys.
+  // 4: Client sends and half-closes. Server responds and destroys.
+  // 5: Client sends. Server responds and half closes.
+  // 6: Client sends and half-closes. Server responds and half closes.
+  var tests = 7;
+  for (var i = 0; i < tests; i++) {
+    asyncStart();
+    new SocketClose.start(i, asyncEnd);
+  }
+}
diff --git a/tests/standalone/io/socket_connect_consume_close_test.dart b/tests/standalone/io/socket_connect_consume_close_test.dart
new file mode 100644
index 0000000..20a078e
--- /dev/null
+++ b/tests/standalone/io/socket_connect_consume_close_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  // Connect socket then immediate close the consumer without
+  // listening on the stream.
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((_) {});
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.close();
+      socket.done.then((_) {
+        socket.destroy();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_connect_consume_write_close_test.dart b/tests/standalone/io/socket_connect_consume_write_close_test.dart
new file mode 100644
index 0000000..8b021abd
--- /dev/null
+++ b/tests/standalone/io/socket_connect_consume_write_close_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  // Connect socket write some data immediate close the consumer
+  // without listening on the stream.
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((_) {});
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+      socket.close();
+      socket.done.then((_) {
+        socket.destroy();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_connect_immediate_destory_test.dart b/tests/standalone/io/socket_connect_immediate_destory_test.dart
new file mode 100644
index 0000000..955f373
--- /dev/null
+++ b/tests/standalone/io/socket_connect_immediate_destory_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((_) {});
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.destroy();
+      server.close();
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_connect_stream_close_test.dart b/tests/standalone/io/socket_connect_stream_close_test.dart
new file mode 100644
index 0000000..6c9fcc2
--- /dev/null
+++ b/tests/standalone/io/socket_connect_stream_close_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  // Connect socket and listen on the stream. The server closes
+  // immediately so only a done event is received.
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      client.close();
+      client.done.then((_) => client.destroy());
+    });
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      bool onDoneCalled = false;
+      socket.listen((_) {
+        Expect.fail("Unexpected data");
+      }, onDone: () {
+        Expect.isFalse(onDoneCalled);
+        onDoneCalled = true;
+        socket.close();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_connect_stream_data_close_cancel_test.dart b/tests/standalone/io/socket_connect_stream_data_close_cancel_test.dart
new file mode 100644
index 0000000..fa921d7
--- /dev/null
+++ b/tests/standalone/io/socket_connect_stream_data_close_cancel_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testConnectStreamDataCloseCancel(bool useDestroy) {
+  List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      client.add(sendData);
+      if (useDestroy) {
+        client.destroy();
+      } else {
+        client.close();
+      }
+      client.done.then((_) {
+        if (!useDestroy) client.destroy();
+      }).catchError((e) {/* can happen with short writes */});
+    });
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      List<int> data = [];
+      bool onDoneCalled = false;
+      var subscription;
+      subscription = socket.listen((_) {
+        subscription.cancel();
+        socket.close();
+        server.close();
+        asyncEnd();
+      }, onDone: () {
+        Expect.fail("Unexpected pipe completion");
+      });
+    });
+  });
+}
+
+main() {
+  testConnectStreamDataCloseCancel(true);
+  testConnectStreamDataCloseCancel(false);
+}
diff --git a/tests/standalone/io/socket_connect_stream_data_close_test.dart b/tests/standalone/io/socket_connect_stream_data_close_test.dart
new file mode 100644
index 0000000..ddce584
--- /dev/null
+++ b/tests/standalone/io/socket_connect_stream_data_close_test.dart
@@ -0,0 +1,54 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testConnectStreamDataClose(bool useDestroy) {
+  // Connect socket and listen on the stream. The server sends data
+  // and then closes so both data and a done event is received.
+  List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((client) {
+      client.add(sendData);
+      if (useDestroy) {
+        client.destroy();
+      } else {
+        client.close();
+      }
+      client.done.then((_) {
+        if (!useDestroy) {
+          client.destroy();
+        }
+      });
+    });
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      List<int> data = [];
+      bool onDoneCalled = false;
+      socket.listen(data.addAll, onDone: () {
+        Expect.isFalse(onDoneCalled);
+        onDoneCalled = true;
+        if (!useDestroy) Expect.listEquals(sendData, data);
+        socket.add([0]);
+        socket.close();
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() {
+  testConnectStreamDataClose(true);
+  testConnectStreamDataClose(false);
+}
diff --git a/tests/standalone/io/socket_connect_timeout_test.dart b/tests/standalone/io/socket_connect_timeout_test.dart
new file mode 100644
index 0000000..d507a2a
--- /dev/null
+++ b/tests/standalone/io/socket_connect_timeout_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  asyncStart();
+  Duration timeout = new Duration(milliseconds: 20);
+  Socket.connect("8.8.8.7", 80, timeout: timeout).then((socket) {
+    Expect.fail("Unexpected connection made.");
+    asyncEnd();
+  }).catchError((e) {
+    Expect.isTrue(e is SocketException);
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/socket_cross_process_test.dart b/tests/standalone/io/socket_cross_process_test.dart
new file mode 100644
index 0000000..295f216
--- /dev/null
+++ b/tests/standalone/io/socket_cross_process_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 "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:io';
+
+const int serversCount = 10;
+
+void main(List<String> args) {
+  if (args.isEmpty) {
+    for (int i = 0; i < serversCount; ++i) {
+      makeServer().then((server) {
+        runClientProcess(server.port).then((_) => server.close());
+      });
+    }
+  } else if (args[0] == '--client') {
+    int port = int.parse(args[1]);
+    runClient(port);
+  } else {
+    Expect.fail('Unknown arguments to socket_cross_process_test.dart');
+  }
+}
+
+Future makeServer() {
+  return ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+    server.listen((request) {
+      request.cast<List<int>>().pipe(request);
+    });
+    return server;
+  });
+}
+
+Future runClientProcess(int port) {
+  return Process.run(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(Platform.script.toFilePath())
+            ..add('--client')
+            ..add(port.toString()))
+      .then((ProcessResult result) {
+    if (result.exitCode != 0 || !result.stdout.contains('SUCCESS')) {
+      print("Client failed, exit code ${result.exitCode}");
+      print("  stdout:");
+      print(result.stdout);
+      print("  stderr:");
+      print(result.stderr);
+      Expect.fail('Client subprocess exit code: ${result.exitCode}');
+    }
+  });
+}
+
+runClient(int port) {
+  Socket.connect(InternetAddress.loopbackIPv4, port).then((connection) {
+    connection.listen((_) {}, onDone: () => print('SUCCESS'));
+    connection.close();
+  });
+}
diff --git a/tests/standalone/io/socket_finalizer_test.dart b/tests/standalone/io/socket_finalizer_test.dart
new file mode 100644
index 0000000..d25ac1c
--- /dev/null
+++ b/tests/standalone/io/socket_finalizer_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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// This test checks that sockets belonging to an isolate are properly cleaned up
+// when the isolate shuts down abnormally. If the socket is not properly cleaned
+// up, the test will time out.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+ConnectorIsolate(Object portObj) async {
+  int port = portObj as int;
+  Socket socket = await Socket.connect("127.0.0.1", port);
+  socket.listen((_) {});
+}
+
+main() async {
+  asyncStart();
+  ServerSocket server = await ServerSocket.bind("127.0.0.1", 0);
+  Isolate isolate = await Isolate.spawn(ConnectorIsolate, server.port);
+  Completer<Null> completer = new Completer<Null>();
+  server.listen((Socket socket) {
+    socket.listen((_) {}, onDone: () {
+      print("Socket closed normally");
+      completer.complete(null);
+      socket.close();
+    }, onError: (e) {
+      Expect.fail("Socket error $e");
+    });
+    isolate.kill();
+  });
+  await completer.future;
+  await server.close();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/socket_info_ipv4_test.dart b/tests/standalone/io/socket_info_ipv4_test.dart
new file mode 100644
index 0000000..f32db33
--- /dev/null
+++ b/tests/standalone/io/socket_info_ipv4_test.dart
@@ -0,0 +1,33 @@
+// 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 "dart:io";
+
+void testHostAndPort() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Socket.connect("127.0.0.1", server.port).then((clientSocket) {
+      server.listen((socket) {
+        Expect.equals(socket.port, server.port);
+        Expect.equals(clientSocket.port, socket.remotePort);
+        Expect.equals(clientSocket.remotePort, socket.port);
+        Expect.equals(socket.remoteAddress.address, "127.0.0.1");
+        Expect.equals(socket.remoteAddress.type, InternetAddressType.IPv4);
+        Expect.listEquals(socket.remoteAddress.rawAddress, [127, 0, 0, 1]);
+        Expect.equals(clientSocket.remoteAddress.address, "127.0.0.1");
+        Expect.equals(
+            clientSocket.remoteAddress.type, InternetAddressType.IPv4);
+        Expect.listEquals(
+            clientSocket.remoteAddress.rawAddress, [127, 0, 0, 1]);
+        socket.destroy();
+        clientSocket.destroy();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testHostAndPort();
+}
diff --git a/tests/standalone/io/socket_info_ipv6_test.dart b/tests/standalone/io/socket_info_ipv6_test.dart
new file mode 100644
index 0000000..11920fb
--- /dev/null
+++ b/tests/standalone/io/socket_info_ipv6_test.dart
@@ -0,0 +1,34 @@
+// 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 "dart:io";
+
+void testHostAndPort() {
+  ServerSocket.bind("::1", 0).then((server) {
+    Socket.connect("::1", server.port).then((clientSocket) {
+      server.listen((socket) {
+        Expect.equals(socket.port, server.port);
+        Expect.equals(clientSocket.port, socket.remotePort);
+        Expect.equals(clientSocket.remotePort, socket.port);
+        Expect.equals(socket.remoteAddress.address, "::1");
+        Expect.equals(socket.remoteAddress.type, InternetAddressType.IPv6);
+        Expect.listEquals(socket.remoteAddress.rawAddress,
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+        Expect.equals(clientSocket.remoteAddress.address, "::1");
+        Expect.equals(
+            clientSocket.remoteAddress.type, InternetAddressType.IPv6);
+        Expect.listEquals(clientSocket.remoteAddress.rawAddress,
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+        socket.destroy();
+        clientSocket.destroy();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testHostAndPort();
+}
diff --git a/tests/standalone/io/socket_invalid_arguments_test.dart b/tests/standalone/io/socket_invalid_arguments_test.dart
new file mode 100644
index 0000000..3e8b889
--- /dev/null
+++ b/tests/standalone/io/socket_invalid_arguments_test.dart
@@ -0,0 +1,84 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class NotAnInteger {
+  operator ==(other) => other == 1;
+  operator <(other) => other > 1;
+  operator +(other) => 1;
+}
+
+testSocketCreation(host, port) {
+  asyncStart();
+  try {
+    Socket.connect(host, port)
+        .then((socket) => Expect.fail("Shouldn't get connected"))
+        .catchError((e) {
+      Expect.isTrue(e is ArgumentError || e is SocketException);
+      asyncEnd();
+    });
+  } catch (e) {
+    Expect.isTrue(e is ArgumentError || e is SocketException);
+    asyncEnd();
+  }
+}
+
+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;
+  try {
+    ServerSocket.bind(address, port, backlog: backlog).then((_) {
+      Expect.fail("ServerSocket bound");
+    }).catchError((e) => asyncEnd());
+  } catch (e) {
+    asyncEnd();
+  }
+}
+
+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);
+  testServerSocketCreation("localhost", 65536, 123);
+  asyncEnd();
+}
diff --git a/tests/standalone/io/socket_invalid_bind_test.dart b/tests/standalone/io/socket_invalid_bind_test.dart
new file mode 100644
index 0000000..f19d551
--- /dev/null
+++ b/tests/standalone/io/socket_invalid_bind_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  // Bind to a unknown DNS name.
+  asyncStart();
+  ServerSocket.bind("ko.faar.__hest__", 0).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to an unavaliable IP-address.
+  asyncStart();
+  ServerSocket.bind("8.8.8.8", 0).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    asyncEnd();
+  });
+
+  // Bind to a port already in use.
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((s) {
+    ServerSocket.bind("127.0.0.1", s.port).then((t) {
+      Expect.fail("Multiple listens on same port");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException);
+      s.close();
+      asyncEnd();
+    });
+  });
+}
diff --git a/tests/standalone/io/socket_ipv6_test.dart b/tests/standalone/io/socket_ipv6_test.dart
new file mode 100644
index 0000000..4fb14cd
--- /dev/null
+++ b/tests/standalone/io/socket_ipv6_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:async';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "test_utils.dart" show retry;
+
+const ANY = InternetAddressType.any;
+
+Future testIPv6toIPv6() {
+  asyncStart();
+  return InternetAddress.lookup("::0", type: ANY).then((serverAddr) {
+    return InternetAddress.lookup("::1", type: ANY).then((clientAddr) {
+      return ServerSocket.bind(serverAddr.first, 0).then((server) {
+        Expect.equals('::0', server.address.host);
+        Expect.equals('::', server.address.address);
+        server.listen((socket) {
+          socket.destroy();
+          server.close();
+          asyncEnd();
+        });
+        return Socket.connect(clientAddr.first, server.port).then((socket) {
+          socket.destroy();
+        });
+      });
+    });
+  });
+}
+
+Future testIPv4toIPv6() {
+  asyncStart();
+  return InternetAddress.lookup("::0", type: ANY).then((serverAddr) {
+    return ServerSocket.bind(serverAddr.first, 0).then((server) {
+      Expect.equals('::0', server.address.host);
+      Expect.equals('::', server.address.address);
+      server.listen((socket) {
+        socket.destroy();
+        server.close();
+        asyncEnd();
+      });
+      return Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.destroy();
+      });
+    });
+  });
+}
+
+Future testIPv6toIPv4() {
+  asyncStart();
+  return InternetAddress.lookup("::1", type: ANY).then((clientAddr) {
+    return ServerSocket.bind("127.0.0.1", 0).then((server) {
+      Expect.equals('127.0.0.1', server.address.host);
+      Expect.equals('127.0.0.1', server.address.address);
+      server.listen((socket) {
+        throw "Unexpected socket";
+      });
+      return Socket.connect(clientAddr.first, server.port).then((socket) {
+        socket.destroy();
+        throw "Unexpected connect";
+      }, onError: (e) {}).whenComplete(() {
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+Future testIPv4toIPv4() {
+  asyncStart();
+  return ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Expect.equals('127.0.0.1', server.address.host);
+    Expect.equals('127.0.0.1', server.address.address);
+    server.listen((socket) {
+      socket.destroy();
+      server.close();
+      asyncEnd();
+    });
+    return Socket.connect("127.0.0.1", server.port).then((socket) {
+      socket.destroy();
+    });
+  });
+}
+
+Future testIPv6Lookup() {
+  asyncStart();
+  return InternetAddress.lookup("::0", type: ANY).then((list) {
+    if (list.length < 0) throw "no address";
+    for (var entry in list) {
+      if (entry.type != InternetAddressType.IPv6) {
+        throw "Wrong IP type";
+      }
+    }
+    asyncEnd();
+  });
+}
+
+Future testIPv4Lookup() {
+  asyncStart();
+  return InternetAddress.lookup("127.0.0.1").then((list) {
+    if (list.length < 0) throw "no address";
+    for (var entry in list) {
+      if (entry.type != InternetAddressType.IPv4) {
+        throw "Wrong IP type";
+      }
+    }
+    asyncEnd();
+  });
+}
+
+Future testIPv4toIPv6_IPV6Only() {
+  asyncStart();
+  return InternetAddress.lookup("::0", type: ANY).then((serverAddr) {
+    return ServerSocket.bind(serverAddr.first, 0, v6Only: true).then((server) {
+      server.listen((socket) {
+        throw "Unexpected socket";
+      });
+      return Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.destroy();
+        throw "Unexpected connect";
+      }, onError: (e) {}).whenComplete(() {
+        server.close();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() async {
+  asyncStart();
+  await testIPv6toIPv6(); //               //# 01: ok
+  await testIPv4toIPv6(); //               //# 02: ok
+  await testIPv4toIPv4(); //               //# 03: ok
+  await testIPv6Lookup(); //               //# 04: ok
+  await testIPv4Lookup(); //               //# 05: ok
+
+  await retry(testIPv6toIPv4); //          //# 06: ok
+  await retry(testIPv4toIPv6_IPV6Only); // //# 07: ok
+  asyncEnd();
+}
diff --git a/tests/standalone/io/socket_many_connections_test.dart b/tests/standalone/io/socket_many_connections_test.dart
new file mode 100644
index 0000000..0140df7
--- /dev/null
+++ b/tests/standalone/io/socket_many_connections_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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// Test creating a large number of socket connections.
+library ServerTest;
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+part "testing_server.dart";
+
+const connectionsCount = 200;
+
+class SocketManyConnectionsTest {
+  SocketManyConnectionsTest.start()
+      : _connections = 0,
+        _sockets = new List<Socket?>.filled(connectionsCount, null) {
+    initialize();
+  }
+
+  void run() {
+    void connectHandler() {
+      _connections++;
+      if (_connections == connectionsCount) {
+        for (int i = 0; i < connectionsCount; i++) {
+          _sockets[i]!.destroy();
+        }
+        close();
+      }
+    }
+
+    for (int i = 0; i < connectionsCount; i++) {
+      Socket.connect(TestingServer.HOST, _port).then((socket) {
+        Expect.isNotNull(socket);
+        _sockets[i] = socket;
+        connectHandler();
+      });
+    }
+  }
+
+  void initialize() {
+    var receivePort = new ReceivePort();
+    var remote = Isolate.spawn(startTestServer, receivePort.sendPort);
+    receivePort.first.then((msg) {
+      this._port = msg[0];
+      this._closeSendPort = msg[1];
+      run();
+    });
+  }
+
+  void close() {
+    _closeSendPort.send(null);
+    asyncEnd();
+  }
+
+  late int _port;
+  late SendPort _closeSendPort;
+  List<Socket?> _sockets;
+  int _connections;
+}
+
+void startTestServer(SendPort replyPort) {
+  var server = new TestServer();
+  server.init().then((port) {
+    replyPort.send([port, server.closeSendPort]);
+  });
+}
+
+class TestServer extends TestingServer {
+  void onConnection(Socket connection) {
+    Socket _client;
+
+    void closeHandler() {
+      connection.close();
+    }
+
+    void errorHandler(e, trace) {
+      String msg = "Socket error $e";
+      if (trace != null) msg += "\nStackTrace: $trace";
+      print(msg);
+      connection.close();
+    }
+
+    _connections++;
+    connection.listen((data) {}, onDone: closeHandler, onError: errorHandler);
+  }
+
+  int _connections = 0;
+}
+
+main() {
+  asyncStart();
+  SocketManyConnectionsTest test = new SocketManyConnectionsTest.start();
+}
diff --git a/tests/standalone/io/socket_port_test.dart b/tests/standalone/io/socket_port_test.dart
new file mode 100644
index 0000000..e7a24ec
--- /dev/null
+++ b/tests/standalone/io/socket_port_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";
+import "dart:io";
+
+void testPort() {
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    Socket.connect("127.0.0.1", server.port).then((clientSocket) {
+      server.listen((Socket socket) {
+        Expect.equals(socket.port, server.port);
+        Expect.equals(clientSocket.port, socket.remotePort);
+        Expect.equals(clientSocket.remotePort, socket.port);
+        clientSocket.destroy();
+        socket.destroy();
+        server.close();
+      });
+    });
+  });
+}
+
+void main() {
+  testPort();
+}
diff --git a/tests/standalone/io/socket_simple_bind_test.dart b/tests/standalone/io/socket_simple_bind_test.dart
new file mode 100644
index 0000000..661815d
--- /dev/null
+++ b/tests/standalone/io/socket_simple_bind_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void main() {
+  asyncStart();
+  ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((s) {
+    Expect.isTrue(s.port > 0);
+    s.close();
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/socket_source_address_test.dart b/tests/standalone/io/socket_source_address_test.dart
new file mode 100644
index 0000000..4fe8b39
--- /dev/null
+++ b/tests/standalone/io/socket_source_address_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.
+//
+
+import "dart:async";
+import "dart:io";
+
+import 'test_utils.dart' show retry, throws;
+
+Future testArguments(connectFunction) async {
+  var sourceAddress;
+  final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  server.listen((_) {
+    throw 'Unexpected connection from address $sourceAddress';
+  });
+
+  // Illegal type for sourceAddress.
+  for (sourceAddress in ['www.google.com', 'abc']) {
+    await throws(
+        () => connectFunction('127.0.0.1', server.port,
+            sourceAddress: sourceAddress),
+        (e) => e is ArgumentError);
+  }
+  // Unsupported local address.
+  for (sourceAddress in ['8.8.8.8', new InternetAddress('8.8.8.8')]) {
+    await throws(
+        () => connectFunction('127.0.0.1', server.port,
+            sourceAddress: sourceAddress),
+        (e) =>
+            e is SocketException &&
+            e.address == new InternetAddress('8.8.8.8'));
+  }
+  // Address family mismatch.
+  for (sourceAddress in ['::1', InternetAddress.loopbackIPv6]) {
+    await throws(
+        () => connectFunction('127.0.0.1', server.port,
+            sourceAddress: sourceAddress),
+        (e) => e is SocketException);
+  }
+  await server.close();
+}
+
+// IPv4 addresses to use as source address when connecting locally.
+var ipV4SourceAddresses = [
+  InternetAddress.loopbackIPv4,
+  InternetAddress.anyIPv4,
+  '127.0.0.1',
+  '0.0.0.0'
+];
+
+// IPv6 addresses to use as source address when connecting locally.
+var ipV6SourceAddresses = [
+  InternetAddress.loopbackIPv6,
+  InternetAddress.anyIPv6,
+  '::1',
+  '::'
+];
+
+Future testConnect(InternetAddress bindAddress, bool v6Only,
+    Function connectFunction, Function closeDestroyFunction) async {
+  var successCount = 0;
+  if (!v6Only) successCount += ipV4SourceAddresses.length;
+  if (bindAddress.type == InternetAddressType.IPv6) {
+    successCount += ipV6SourceAddresses.length;
+  }
+  var count = 0;
+  var allConnected = new Completer();
+  if (successCount == 0) allConnected.complete();
+
+  var server = await ServerSocket.bind(bindAddress, 0, v6Only: v6Only);
+  server.listen((s) {
+    s.destroy();
+    count++;
+    if (count == successCount) allConnected.complete();
+  });
+
+  // Connect with IPv4 source addresses.
+  for (var sourceAddress in ipV4SourceAddresses) {
+    if (!v6Only) {
+      var s = await connectFunction(InternetAddress.loopbackIPv4, server.port,
+          sourceAddress: sourceAddress);
+      closeDestroyFunction(s);
+    } else {
+      // Cannot use an IPv4 source address to connect to IPv6 if
+      // v6Only is specified.
+      await throws(
+          () => connectFunction(InternetAddress.loopbackIPv6, server.port,
+              sourceAddress: sourceAddress),
+          (e) => e is SocketException);
+    }
+  }
+
+  // Connect with IPv6 source addresses.
+  for (var sourceAddress in ipV6SourceAddresses) {
+    if (bindAddress.type == InternetAddressType.IPv6) {
+      var s = await connectFunction(InternetAddress.loopbackIPv6, server.port,
+          sourceAddress: sourceAddress);
+      closeDestroyFunction(s);
+    } else {
+      // Cannot use an IPv6 source address to connect to IPv4.
+      await throws(
+          () => connectFunction(InternetAddress.loopbackIPv4, server.port,
+              sourceAddress: sourceAddress),
+          (e) => e is SocketException);
+    }
+  }
+
+  await allConnected.future;
+  await server.close();
+}
+
+main() async {
+  await retry(() async {
+    await testArguments(RawSocket.connect);
+  });
+  await retry(() async {
+    await testArguments(Socket.connect);
+  });
+
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv4, false, RawSocket.connect, (s) => s.close());
+  });
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv4, false, Socket.connect, (s) => s.destroy());
+  });
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv6, false, RawSocket.connect, (s) => s.close());
+  });
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv6, false, Socket.connect, (s) => s.destroy());
+  });
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv6, true, RawSocket.connect, (s) => s.close());
+  });
+  await retry(() async {
+    await testConnect(
+        InternetAddress.anyIPv6, true, Socket.connect, (s) => s.destroy());
+  });
+}
diff --git a/tests/standalone/io/socket_upgrade_to_secure_test.dart b/tests/standalone/io/socket_upgrade_to_secure_test.dart
new file mode 100644
index 0000000..116de62
--- /dev/null
+++ b/tests/standalone/io/socket_upgrade_to_secure_test.dart
@@ -0,0 +1,238 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+late InternetAddress HOST;
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+List<int> readLocalFile(path) => (new File(localFile(path))).readAsBytesSync();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+// This test creates a server and a client connects. After connecting
+// and an optional initial handshake the connection is secured by
+// upgrading to a secure connection The client then writes and the
+// server echos. When the server has finished its echo it
+// half-closes. When the client gets the close event is closes fully.
+//
+// The test can be run in different configurations based on
+// the boolean arguments:
+//
+// handshakeBeforeSecure
+// When this argument is true some initial clear text handshake is done
+// between client and server before the connection is secured. This argument
+// only makes sense when both listenSecure and connectSecure are false.
+//
+// postponeSecure
+// When this argument is false the securing of the server end will
+// happen as soon as the last byte of the handshake before securing
+// has been written. When this argument is true the securing of the
+// server will not happen until the first TLS handshake data has been
+// received from the client. This argument only takes effect when
+// handshakeBeforeSecure is true.
+void test(bool hostnameInConnect, bool handshakeBeforeSecure,
+    [bool postponeSecure = false]) {
+  asyncStart();
+
+  const messageSize = 1000;
+  const handshakeMessageSize = 100;
+
+  List<int> createTestData() {
+    List<int> data = new List<int>.filled(messageSize, 0);
+    for (int i = 0; i < messageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  List<int> createHandshakeTestData() {
+    List<int> data = new List<int>.filled(handshakeMessageSize, 0);
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  void verifyTestData(List<int> data) {
+    Expect.equals(messageSize, data.length);
+    List<int> expected = createTestData();
+    for (int i = 0; i < messageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  void verifyHandshakeTestData(List<int> data) {
+    Expect.equals(handshakeMessageSize, data.length);
+    List<int> expected = createHandshakeTestData();
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  Future runServer(Socket client) {
+    var completer = new Completer();
+    var dataReceived = <int>[];
+    client.listen((data) {
+      dataReceived.addAll(data);
+      if (dataReceived.length == messageSize) {
+        verifyTestData(dataReceived);
+        client.add(dataReceived);
+        client.close();
+      }
+    }, onDone: () => completer.complete(null));
+    return completer.future;
+  }
+
+  Future<RawSocket> runClient(Socket socket) {
+    Completer<RawSocket> completer = new Completer<RawSocket>();
+    var dataReceived = <int>[];
+    socket.listen((data) {
+      dataReceived.addAll(data);
+    }, onDone: () {
+      Expect.equals(messageSize, dataReceived.length);
+      verifyTestData(dataReceived);
+      socket.close();
+      completer.complete(null);
+    });
+    socket.add(createTestData());
+    return completer.future;
+  }
+
+  Future runServerHandshake(Socket client) {
+    var completer = new Completer();
+    var dataReceived = <int>[];
+    var subscription;
+    subscription = client.listen((data) {
+      if (dataReceived.length == handshakeMessageSize) {
+        Expect.isTrue(postponeSecure);
+        subscription.pause();
+        completer.complete(data);
+      }
+      dataReceived.addAll(data);
+      if (dataReceived.length == handshakeMessageSize) {
+        verifyHandshakeTestData(dataReceived);
+        client.add(dataReceived);
+        if (!postponeSecure) {
+          completer.complete(null);
+        }
+      }
+    }, onDone: () => completer.complete(null));
+    return completer.future;
+  }
+
+  Future runClientHandshake(Socket socket) {
+    var completer = new Completer();
+    var dataReceived = <int>[];
+    socket.listen((data) {
+      dataReceived.addAll(data);
+      if (dataReceived.length == handshakeMessageSize) {
+        verifyHandshakeTestData(dataReceived);
+        completer.complete(null);
+      }
+    }, onDone: () => Expect.fail("Should not be called"));
+    socket.add(createHandshakeTestData());
+    return completer.future;
+  }
+
+  Future<SecureSocket> connectClient(int port) {
+    if (!handshakeBeforeSecure) {
+      return Socket.connect(HOST, port).then((socket) {
+        Future<SecureSocket> future;
+        if (hostnameInConnect) {
+          future = SecureSocket.secure(socket, context: clientContext);
+        } else {
+          future =
+              SecureSocket.secure(socket, host: HOST, context: clientContext);
+        }
+        return future.then<SecureSocket>((SecureSocket secureSocket) {
+          Expect.throws(() {
+            socket.add([0]);
+          });
+          return secureSocket;
+        });
+      });
+    } else {
+      return Socket.connect(HOST, port).then((socket) {
+        return runClientHandshake(socket).then((_) {
+          var future;
+          if (hostnameInConnect) {
+            future = SecureSocket.secure(socket, context: clientContext);
+          } else {
+            future =
+                SecureSocket.secure(socket, host: HOST, context: clientContext);
+          }
+          return future.then((secureSocket) {
+            Expect.throws(() {
+              socket.add([0]);
+            });
+            return secureSocket;
+          });
+        });
+      });
+    }
+  }
+
+  serverReady(server) {
+    server.listen((client) {
+      if (!handshakeBeforeSecure) {
+        SecureSocket.secureServer(client, serverContext).then((secureClient) {
+          Expect.throws(() {
+            client.add([0]);
+          });
+          runServer(secureClient).then((_) => server.close());
+        });
+      } else {
+        runServerHandshake(client).then((carryOverData) {
+          SecureSocket.secureServer(client, serverContext,
+                  bufferedData: carryOverData)
+              .then((secureClient) {
+            Expect.throws(() {
+              client.add([0]);
+            });
+            runServer(secureClient).then((_) => server.close());
+          });
+        });
+      }
+    });
+
+    connectClient(server.port).then(runClient).then((socket) {
+      asyncEnd();
+    });
+  }
+
+  ServerSocket.bind(HOST, 0).then(serverReady);
+}
+
+main() {
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    test(false, false);
+    // TODO(whesse): Enable the test with all argument combinations:
+    //  test(true, false);
+    //  test(false, true);
+    //  test(true, true);
+    //  test(false, true, true);
+    //  test(true, true, true);
+    asyncEnd();
+  });
+}
diff --git a/tests/standalone/io/stdin_has_terminal_test.dart b/tests/standalone/io/stdin_has_terminal_test.dart
new file mode 100644
index 0000000..2b9cae1
--- /dev/null
+++ b/tests/standalone/io/stdin_has_terminal_test.dart
@@ -0,0 +1,26 @@
+// 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:io";
+
+import "package:expect/expect.dart";
+
+void fiddleWithEchoMode() {
+  final bool echoMode = stdin.echoMode;
+  stdin.echoMode = false;
+  stdin.echoMode = true;
+  stdin.echoMode = echoMode;
+}
+
+void main() {
+  Expect.isNotNull(stdin.hasTerminal);
+  Expect.isTrue(stdin.hasTerminal is bool);
+  if (stdin.hasTerminal) {
+    fiddleWithEchoMode();
+  } else {
+    Expect.throws(() {
+      fiddleWithEchoMode();
+    }, (e) => e is StdinException);
+  }
+}
diff --git a/tests/standalone/io/stdin_sync_script.dart b/tests/standalone/io/stdin_sync_script.dart
new file mode 100644
index 0000000..c666c79
--- /dev/null
+++ b/tests/standalone/io/stdin_sync_script.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:convert";
+import "dart:io";
+
+void main(List<String> arguments) {
+  int i = 0;
+  while (true) {
+    final line = stdin.readLineSync(encoding: utf8);
+    if (line == null) break;
+    if (json.decode(arguments[i]) != line) {
+      throw "bad line at $i: ${line.codeUnits}";
+    }
+    i++;
+  }
+  if (i != arguments.length) throw "expect ${arguments.length} lines";
+  print('true');
+}
diff --git a/tests/standalone/io/stdin_sync_test.dart b/tests/standalone/io/stdin_sync_test.dart
new file mode 100644
index 0000000..7d26a29
--- /dev/null
+++ b/tests/standalone/io/stdin_sync_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.
+
+// OtherResources=stdin_sync_script.dart
+
+import "dart:convert";
+import "dart:io";
+
+import "package:path/path.dart";
+import "package:expect/expect.dart";
+
+void testReadByte() {
+  void test(String line, List<String> expected) {
+    var script = Platform.script.resolve("stdin_sync_script.dart").toFilePath();
+    Process.start(
+            Platform.executable,
+            []
+              ..addAll(Platform.executableArguments)
+              ..add(script)
+              ..addAll(expected.map(json.encode)))
+        .then((process) {
+      process.stdin.write(line);
+      process.stdin.flush().then((_) => process.stdin.close());
+      process.stderr
+          .transform(utf8.decoder)
+          .transform(new LineSplitter())
+          .fold<StringBuffer>(new StringBuffer(), (b, d) => b..write(d))
+          .then((data) {
+        if (data.toString() != '') throw "Bad output: '$data'";
+      });
+      process.stdout
+          .transform(utf8.decoder)
+          .transform(new LineSplitter())
+          .fold<StringBuffer>(new StringBuffer(), (b, d) => b..write(d))
+          .then((data) {
+        if (data.toString() != 'true') throw "Bad output: '$data'";
+      });
+    });
+  }
+
+  test("hej\x01\x00\x0d\x0a\x0a4\x0a", ['hej\x01\x00', '', '4']);
+
+  test("hej\u0187", ['hej\u0187']);
+
+  test("hej\rhej\nhej\r", ['hej\rhej', 'hej\r']);
+
+  test("hej\r\r\nhej\r\nhej\r", ['hej\r', 'hej', 'hej\r']);
+
+  test("hej", ['hej']);
+}
+
+void testEchoMode() {
+  stdin.echoMode = true;
+  Expect.isTrue(stdin.echoMode);
+  stdin.echoMode = false;
+  Expect.isFalse(stdin.echoMode);
+  var line;
+  while ((line = stdin.readLineSync()) != null) {
+    print("You typed: $line");
+  }
+}
+
+void testLineMode() {
+  stdin.lineMode = true;
+  Expect.isTrue(stdin.lineMode);
+  stdin.lineMode = false;
+  Expect.isFalse(stdin.lineMode);
+  var char;
+  while ((char = stdin.readByteSync()) != -1) {
+    print("You typed: $char");
+  }
+}
+
+void main() {
+  testReadByte();
+
+  // testEchoMode and testLineMode is developer-interactive tests, thus not
+  // enabled.
+  //testEchoMode();
+  //testLineMode();
+}
diff --git a/tests/standalone/io/stdio_implicit_close_script.dart b/tests/standalone/io/stdio_implicit_close_script.dart
new file mode 100644
index 0000000..2b09e2f
--- /dev/null
+++ b/tests/standalone/io/stdio_implicit_close_script.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main(List<String> arguments) {
+  // Access stdout and stderr so that the system grabs a handle to it. This
+  // initializes some internal structures.
+  stdout.write("APPLE");
+  stderr.write("BANANA");
+
+  if (arguments.contains("stdout")) {
+    stdout.close();
+  }
+  if (arguments.contains("stderr")) {
+    stderr.close();
+  }
+}
diff --git a/tests/standalone/io/stdio_implicit_close_test.dart b/tests/standalone/io/stdio_implicit_close_test.dart
new file mode 100644
index 0000000..11a615c
--- /dev/null
+++ b/tests/standalone/io/stdio_implicit_close_test.dart
@@ -0,0 +1,44 @@
+// 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.
+
+// OtherResources=stdio_implicit_close_script.dart
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "dart:convert";
+import "dart:io";
+
+void test({required bool closeStdout, required bool closeStderr}) {
+  var scriptFile = "stdio_implicit_close_script.dart";
+  var script = Platform.script.resolve(scriptFile).toFilePath();
+
+  var arguments = <String>[]
+    ..addAll(Platform.executableArguments)
+    ..add(script);
+  if (closeStdout) arguments.add("stdout");
+  if (closeStderr) arguments.add("stderr");
+
+  asyncStart();
+  Process.run(Platform.executable, arguments,
+          stdoutEncoding: ascii, stderrEncoding: ascii)
+      .then((result) {
+    print(result.stdout);
+    print(result.stderr);
+    Expect.equals(0, result.exitCode);
+
+    Expect.isTrue(result.stdout.contains("APPLE"));
+    Expect.isTrue(result.stderr.contains("BANANA"));
+
+    asyncEnd();
+  });
+}
+
+void main() {
+  asyncStart();
+  test(closeStdout: false, closeStderr: false);
+  test(closeStdout: false, closeStderr: true);
+  test(closeStdout: true, closeStderr: false);
+  test(closeStdout: true, closeStderr: true);
+  asyncEnd();
+}
diff --git a/tests/standalone/io/stdio_nonblocking_script.dart b/tests/standalone/io/stdio_nonblocking_script.dart
new file mode 100644
index 0000000..99ada55
--- /dev/null
+++ b/tests/standalone/io/stdio_nonblocking_script.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.
+
+import "dart:async";
+import "dart:io";
+
+class Message {
+  final message;
+  Message(this.message);
+  toString() => message;
+}
+
+void test(IOSink sink) {
+  sink.add([65, 66, 67]);
+  sink.write('DEF');
+  sink.writeAll(['GH', 'I']);
+  sink.writeCharCode(74);
+  sink.writeln('KLM');
+}
+
+void main(List<String> arguments) {
+  stdout.nonBlocking.writeln('stdout');
+  stderr.nonBlocking.writeln('stderr');
+  stdout.nonBlocking.writeln();
+  stderr.nonBlocking.writeln();
+  stdout.nonBlocking.writeln(new Message('tuodts'));
+  stderr.nonBlocking.writeln(new Message('rredts'));
+  test(stdout.nonBlocking);
+  test(stderr.nonBlocking);
+  Future.wait([stdout.nonBlocking.close(), stderr.nonBlocking.close()])
+      .then((_) => exit(1));
+}
diff --git a/tests/standalone/io/stdio_nonblocking_test.dart b/tests/standalone/io/stdio_nonblocking_test.dart
new file mode 100644
index 0000000..1eab14e
--- /dev/null
+++ b/tests/standalone/io/stdio_nonblocking_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.
+
+// OtherResources=stdio_nonblocking_script.dart
+
+import "dart:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+void main() {
+  var script =
+      Platform.script.resolve("stdio_nonblocking_script.dart").toFilePath();
+  Process.run(
+          Platform.executable,
+          []
+            ..addAll(Platform.executableArguments)
+            ..add(script),
+          stdoutEncoding: ascii,
+          stderrEncoding: ascii)
+      .then((result) {
+    print(result.stdout);
+    print(result.stderr);
+    Expect.equals(1, result.exitCode);
+    Expect.equals('stdout\n\ntuodts\nABCDEFGHIJKLM\n', result.stdout);
+    Expect.equals('stderr\n\nrredts\nABCDEFGHIJKLM\n', result.stderr);
+  });
+}
diff --git a/tests/standalone/io/stdio_socket_finalizer_test.dart b/tests/standalone/io/stdio_socket_finalizer_test.dart
new file mode 100644
index 0000000..c33da51
--- /dev/null
+++ b/tests/standalone/io/stdio_socket_finalizer_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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+//
+// This test checks that stdin is *not* closed when an Isolate leaks it.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void ConnectorIsolate(Object sendPortObj) {
+  SendPort sendPort = sendPortObj as SendPort;
+  stdin;
+  sendPort.send(true);
+}
+
+main() async {
+  asyncStart();
+  ReceivePort receivePort = new ReceivePort();
+  Isolate isolate = await Isolate.spawn(ConnectorIsolate, receivePort.sendPort);
+  Completer<Null> completer = new Completer<Null>();
+  receivePort.listen((msg) {
+    Expect.isTrue(msg is bool);
+    Expect.isTrue(msg);
+    isolate.kill();
+    completer.complete(null);
+  });
+  await completer.future;
+  stdin.listen((_) {}).cancel();
+  receivePort.close();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/stdout_close_test.dart b/tests/standalone/io/stdout_close_test.dart
new file mode 100644
index 0000000..128c230
--- /dev/null
+++ b/tests/standalone/io/stdout_close_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 "package:expect/expect.dart";
+import "dart:io";
+
+void main() {
+  var dir = Directory.systemTemp.createTempSync('dart_stdout_close');
+  stdout.close().then((_) {
+    var file = new File('${dir.path}/file');
+    var io = file.openSync(mode: FileMode.write);
+    print("to file");
+    io.closeSync();
+    var content = file.readAsStringSync();
+    file.deleteSync();
+    dir.deleteSync();
+    Expect.equals("", content);
+  });
+}
diff --git a/tests/standalone/io/stdout_stderr_non_blocking_test.dart b/tests/standalone/io/stdout_stderr_non_blocking_test.dart
new file mode 100644
index 0000000..2be201f
--- /dev/null
+++ b/tests/standalone/io/stdout_stderr_non_blocking_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.
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+
+callIOSink(IOSink sink) {
+  // Call all methods on IOSink.
+  sink.encoding = ascii;
+  Expect.equals(ascii, sink.encoding);
+  sink.write("Hello\n");
+  sink.writeln("Hello");
+  sink.writeAll(["H", "e", "l", "lo\n"]);
+  sink.writeCharCode(72);
+  sink.add([101, 108, 108, 111, 10]);
+
+  var controller = new StreamController<List<int>>(sync: true);
+  var future = sink.addStream(controller.stream);
+  controller.add([72, 101, 108]);
+  controller.add([108, 111, 10]);
+  controller.close();
+
+  future.then((_) {
+    controller = new StreamController(sync: true);
+    controller.stream.pipe(sink);
+    controller.add([72, 101, 108]);
+    controller.add([108, 111, 10]);
+    controller.close();
+  });
+}
+
+main() {
+  callIOSink(stdout.nonBlocking);
+  stdout.nonBlocking.done.then((_) {
+    callIOSink(stderr.nonBlocking);
+    stderr.nonBlocking.done.then((_) {
+      stdout.close();
+      stderr.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/stdout_stderr_terminal_test.dart b/tests/standalone/io/stdout_stderr_terminal_test.dart
new file mode 100644
index 0000000..9de52d64
--- /dev/null
+++ b/tests/standalone/io/stdout_stderr_terminal_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.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+void testTerminalSize(std) {
+  if (std.hasTerminal) {
+    Expect.notEquals(0, std.terminalColumns);
+    Expect.notEquals(0, std.terminalLines);
+  } else {
+    Expect.throws(() => std.terminalColumns, (e) => e is StdoutException);
+    Expect.throws(() => std.terminalLines, (e) => e is StdoutException);
+  }
+}
+
+void main() {
+  testTerminalSize(stdout);
+  testTerminalSize(stderr);
+}
diff --git a/tests/standalone/io/stdout_stderr_test.dart b/tests/standalone/io/stdout_stderr_test.dart
new file mode 100644
index 0000000..a6a7657
--- /dev/null
+++ b/tests/standalone/io/stdout_stderr_test.dart
@@ -0,0 +1,44 @@
+// 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 "dart:async";
+import "dart:convert";
+import "dart:io";
+
+callIOSink(IOSink sink) {
+  // Call all methods on IOSink.
+  sink.encoding = ascii;
+  Expect.equals(ascii, sink.encoding);
+  sink.write("Hello\n");
+  sink.writeln("Hello");
+  sink.writeAll(["H", "e", "l", "lo\n"]);
+  sink.writeCharCode(72);
+  sink.add([101, 108, 108, 111, 10]);
+
+  var controller = new StreamController<List<int>>(sync: true);
+  var future = sink.addStream(controller.stream);
+  controller.add([72, 101, 108]);
+  controller.add([108, 111, 10]);
+  controller.close();
+
+  future.then((_) {
+    controller = new StreamController(sync: true);
+    controller.stream.pipe(sink);
+    controller.add([72, 101, 108]);
+    controller.add([108, 111, 10]);
+    controller.close();
+  });
+}
+
+main() {
+  callIOSink(stdout);
+  stdout.done.then((_) {
+    callIOSink(stderr);
+    stderr.done.then((_) {
+      stdout.close();
+      stderr.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/stream_pipe_test.dart b/tests/standalone/io/stream_pipe_test.dart
new file mode 100644
index 0000000..7955725
--- /dev/null
+++ b/tests/standalone/io/stream_pipe_test.dart
@@ -0,0 +1,162 @@
+// 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.
+//
+// OtherResources=readline_test1.dat
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+// Helper method to be able to run the test from the runtime
+// directory, or the top directory.
+String getDataFilename(String path) =>
+    Platform.script.resolve(path).toFilePath();
+
+bool compareFileContent(String fileName1, String fileName2,
+    {int file1Offset: 0, int file2Offset: 0, int? count}) {
+  var file1 = new File(fileName1).openSync();
+  var file2 = new File(fileName2).openSync();
+  var length1 = file1.lengthSync();
+  var length2 = file2.lengthSync();
+  if (file1Offset == 0 && file2Offset == 0 && count == null) {
+    if (length1 != length2) {
+      file1.closeSync();
+      file2.closeSync();
+      return false;
+    }
+  }
+  if (count == null) count = length1;
+  var data1 = new List<int>.filled(count, 0);
+  var data2 = new List<int>.filled(count, 0);
+  if (file1Offset != 0) file1.setPositionSync(file1Offset);
+  if (file2Offset != 0) file2.setPositionSync(file2Offset);
+  var read1 = file1.readIntoSync(data1, 0, count);
+  Expect.equals(count, read1);
+  var read2 = file2.readIntoSync(data2, 0, count);
+  Expect.equals(count, read2);
+  for (var i = 0; i < count; i++) {
+    if (data1[i] != data2[i]) {
+      file1.closeSync();
+      file2.closeSync();
+      return false;
+    }
+  }
+  file1.closeSync();
+  file2.closeSync();
+  return true;
+}
+
+// Test piping from one file to another and closing both streams
+// after wards.
+testFileToFilePipe1() {
+  // Force test to timeout if one of the handlers is
+  // not called.
+  asyncStart();
+
+  String srcFileName = getDataFilename("readline_test1.dat");
+  var srcStream = new File(srcFileName).openRead();
+
+  var tempDir = Directory.systemTemp.createTempSync('dart_stream_pipe');
+  String dstFileName = tempDir.path + "/readline_test1.dat";
+  new File(dstFileName).createSync();
+  var output = new File(dstFileName).openWrite();
+  srcStream.cast<List<int>>().pipe(output).then((_) {
+    bool result = compareFileContent(srcFileName, dstFileName);
+    new File(dstFileName).deleteSync();
+    tempDir.deleteSync();
+    Expect.isTrue(result);
+    asyncEnd();
+  });
+}
+
+// Test piping from one file to another and write additional data to
+// the output stream after piping finished.
+testFileToFilePipe2() {
+  // Force test to timeout if one of the handlers is
+  // not called.
+  asyncStart();
+
+  String srcFileName = getDataFilename("readline_test1.dat");
+  var srcFile = new File(srcFileName);
+  var srcStream = srcFile.openRead();
+
+  var tempDir = Directory.systemTemp.createTempSync('dart_stream_pipe');
+  var dstFileName = tempDir.path + "/readline_test1.dat";
+  var dstFile = new File(dstFileName);
+  dstFile.createSync();
+  var output = dstFile.openWrite();
+  output.addStream(srcStream.cast<List<int>>()).then((_) {
+    output.add([32]);
+    output.close();
+    output.done.then((_) {
+      var src = srcFile.openSync();
+      var dst = dstFile.openSync();
+      var srcLength = src.lengthSync();
+      var dstLength = dst.lengthSync();
+      Expect.equals(srcLength + 1, dstLength);
+      Expect.isTrue(
+          compareFileContent(srcFileName, dstFileName, count: srcLength));
+      dst.setPositionSync(srcLength);
+      var data = new List<int>.filled(1, 0);
+      var read2 = dst.readIntoSync(data, 0, 1);
+      Expect.equals(32, data[0]);
+      src.closeSync();
+      dst.closeSync();
+      dstFile.deleteSync();
+      tempDir.deleteSync();
+      asyncEnd();
+    });
+  });
+}
+
+// Test piping two copies of one file to another.
+testFileToFilePipe3() {
+  // Force test to timeout if one of the handlers is
+  // not called.
+  asyncStart();
+
+  String srcFileName = getDataFilename("readline_test1.dat");
+  var srcFile = new File(srcFileName);
+  var srcStream = srcFile.openRead();
+
+  var tempDir = Directory.systemTemp.createTempSync('dart_stream_pipe');
+  var dstFileName = tempDir.path + "/readline_test1.dat";
+  var dstFile = new File(dstFileName);
+  dstFile.createSync();
+  var output = dstFile.openWrite();
+  output.addStream(srcStream.cast<List<int>>()).then((_) {
+    var srcStream2 = srcFile.openRead();
+    output.addStream(srcStream2.cast<List<int>>()).then((_) {
+      output.close();
+      output.done.then((_) {
+        var src = srcFile.openSync();
+        var dst = dstFile.openSync();
+        var srcLength = src.lengthSync();
+        var dstLength = dst.lengthSync();
+        Expect.equals(srcLength * 2, dstLength);
+        Expect.isTrue(
+            compareFileContent(srcFileName, dstFileName, count: srcLength));
+        Expect.isTrue(compareFileContent(srcFileName, dstFileName,
+            file2Offset: srcLength, count: srcLength));
+        src.closeSync();
+        dst.closeSync();
+        dstFile.deleteSync();
+        tempDir.deleteSync();
+        asyncEnd();
+      });
+    });
+  });
+}
+
+main() {
+  testFileToFilePipe1();
+  testFileToFilePipe2();
+  testFileToFilePipe3();
+}
diff --git a/tests/standalone/io/system_encoding_test.dart b/tests/standalone/io/system_encoding_test.dart
new file mode 100644
index 0000000..40a6bf6
--- /dev/null
+++ b/tests/standalone/io/system_encoding_test.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.
+
+import 'dart:io';
+import 'dart:convert';
+
+import "package:expect/expect.dart";
+
+// This only works reliabily for "ASCII" cross platform as that is the only
+// well known part of the default Windows code page.
+void testEncodeDecode(String str) {
+  Expect.equals(systemEncoding.decode(systemEncoding.encode(str)), str);
+}
+
+// This only works reliabily for "ASCII" cross platform as that is the only
+// common set of bytes between UTF-8 Windows code pages that convert back
+// and forth.
+void testDecodeEncode(List<int> bytes) {
+  Expect.listEquals(systemEncoding.encode(systemEncoding.decode(bytes)), bytes);
+}
+
+void test(List<int> bytes) {
+  var str = new String.fromCharCodes(bytes);
+  Expect.equals(systemEncoding.decode(bytes), str);
+  Expect.listEquals(systemEncoding.encode(str), bytes);
+  testDecodeEncode(bytes);
+  testEncodeDecode(str);
+}
+
+main() {
+  test([65, 66, 67]);
+  test([65, 0, 67]);
+  test([0, 65, 0, 67, 0]);
+  test([0, 0, 0]);
+  test(new Iterable.generate(128, (i) => i).toList());
+  if (Platform.isWindows) {
+    // On Windows the default Windows code page cannot encode these
+    // Unicode characters and the ? character is used.
+    Expect.listEquals(
+        systemEncoding.encode('\u1234\u5678\u9abc'), '???'.codeUnits);
+  } else {
+    // On all systems except for Windows UTF-8 is used as the system
+    // encoding.
+    Expect.listEquals(systemEncoding.encode('\u1234\u5678\u9abc'),
+        utf8.encode('\u1234\u5678\u9abc'));
+  }
+}
diff --git a/tests/standalone/io/test_extension.dart b/tests/standalone/io/test_extension.dart
new file mode 100644
index 0000000..beed87c
--- /dev/null
+++ b/tests/standalone/io/test_extension.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.
+
+library test_extension;
+
+import "dart-ext:test_extension";
+
+class Cat {
+  Cat(this.x);
+
+  num x;
+
+  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 throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
+}
diff --git a/tests/standalone/io/test_extension_fail_test.dart b/tests/standalone/io/test_extension_fail_test.dart
new file mode 100644
index 0000000..dae4411
--- /dev/null
+++ b/tests/standalone/io/test_extension_fail_test.dart
@@ -0,0 +1,98 @@
+// 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 native extensions.
+
+import "package:path/path.dart";
+import "dart:async";
+import "dart:io";
+
+Future copyFileToDirectory(String file, String directory) {
+  switch (Platform.operatingSystem) {
+    case 'linux':
+    case 'macos':
+      return Process.run('cp', [file, directory]);
+    case 'windows':
+      return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
+    default:
+      throw new StateError(
+          'Unknown operating system ${Platform.operatingSystem}');
+  }
+}
+
+String getExtensionPath(String buildDirectory) {
+  switch (Platform.operatingSystem) {
+    case 'linux':
+      return join(buildDirectory, 'libtest_extension.so');
+    case 'macos':
+      return join(buildDirectory, 'libtest_extension.dylib');
+    case 'windows':
+      return join(buildDirectory, 'test_extension.dll');
+    default:
+      throw new StateError(
+          'Unknown operating system ${Platform.operatingSystem}');
+  }
+}
+
+bool checkExitCode(int code) {
+  return ((code == 255) || (code == 254) || (code == 253));
+}
+
+bool checkStdError(String err) {
+  return err.contains("Unhandled exception:") ||
+      err.contains(
+          "Native extension path must be absolute, or simply the file name");
+}
+
+// name is either "extension" or "relative_extension"
+Future test(String name, bool checkForBall) async {
+  String scriptDirectory = dirname(Platform.script.toFilePath());
+  String buildDirectory = dirname(Platform.executable);
+  Directory tempDirectory =
+      Directory.systemTemp.createTempSync('dart_test_${name}_fail');
+  String testDirectory = tempDirectory.path;
+
+  // Copy test_extension shared library, test_extension.dart and
+  // test_extension_fail_tester.dart to the temporary test directory.
+  try {
+    if (name == "extension") {
+      print(getExtensionPath(buildDirectory));
+      await copyFileToDirectory(
+          getExtensionPath(buildDirectory), testDirectory);
+    } else {
+      var extensionDir = testDirectory + "/extension";
+      Directory dir = await (new Directory(extensionDir).create());
+      await copyFileToDirectory(getExtensionPath(buildDirectory), extensionDir);
+    }
+    var extensionDartFile = join(scriptDirectory, 'test_${name}.dart');
+    await copyFileToDirectory(extensionDartFile, testDirectory);
+    var testExtensionTesterFile =
+        join(scriptDirectory, 'test_${name}_fail_tester.dart');
+    await copyFileToDirectory(testExtensionTesterFile, testDirectory);
+    var args = new List<String>.from(Platform.executableArguments)
+      ..add('--trace-loading')
+      ..add(join(testDirectory, 'test_${name}_fail_tester.dart'));
+    var result = await Process.run(Platform.executable, args);
+    print("ERR: ${result.stderr}\n\n");
+    print("OUT: ${result.stdout}\n\n");
+    if (!checkExitCode(result.exitCode)) {
+      throw new StateError("bad exit code: ${result.exitCode}");
+    }
+    if (!checkStdError(result.stderr)) {
+      throw new StateError("stderr doesn't contain unhandled exception.");
+    }
+    if (checkForBall) {
+      if (!result.stderr.contains("ball")) {
+        throw new StateError("stderr doesn't contain 'ball'.");
+      }
+    }
+  } finally {
+    tempDirectory.deleteSync(recursive: true);
+  }
+}
+
+main() async {
+  await test("extension", true);
+  await test("relative_extension", false);
+}
diff --git a/tests/standalone/io/test_extension_fail_tester.dart b/tests/standalone/io/test_extension_fail_tester.dart
new file mode 100644
index 0000000..f2e72ae
--- /dev/null
+++ b/tests/standalone/io/test_extension_fail_tester.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.
+
+library test_extension_test;
+
+import "dart:async";
+import "dart:isolate";
+import "test_extension.dart";
+
+main() {
+  try {
+    Cat.throwMeTheBall("ball");
+  } on String catch (e) {
+    if (e != "ball") throw new StateError("exception not equal to 'ball'");
+  }
+  // Make sure the exception is thrown out to the event handler from C++ code.
+  // The harness expects the string "ball" to be thrown and the process to
+  // end with an unhandled exception.
+  Timer.run(() => Cat.throwMeTheBall("ball"));
+}
diff --git a/tests/standalone/io/test_extension_test.dart b/tests/standalone/io/test_extension_test.dart
new file mode 100644
index 0000000..e69ae28
--- /dev/null
+++ b/tests/standalone/io/test_extension_test.dart
@@ -0,0 +1,112 @@
+// 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 native extensions.
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+Future copyFileToDirectory(String file, String directory) {
+  switch (Platform.operatingSystem) {
+    case 'android':
+    case 'linux':
+    case 'macos':
+      return Process.run('cp', [file, directory]);
+    case 'windows':
+      return Process.run('cmd.exe', ['/C', 'copy $file $directory']);
+    default:
+      Expect.fail('Unknown operating system ${Platform.operatingSystem}');
+  }
+}
+
+// Returns a list containing the source file name in the first element and the
+// target file name in the second element.
+List<String> getExtensionNames(String arch) {
+  switch (Platform.operatingSystem) {
+    case 'android':
+    case 'linux':
+      return ['libtest_extension.so', 'libtest_extension$arch.so'];
+    case 'macos':
+      return ['libtest_extension.dylib', 'libtest_extension$arch.dylib'];
+    case 'windows':
+      return ['test_extension.dll', 'test_extension$arch.dll'];
+    default:
+      Expect.fail('Unknown operating system ${Platform.operatingSystem}');
+  }
+}
+
+String getExtensionPath(String buildDirectory, String filename) {
+  return join(buildDirectory, filename);
+}
+
+String getArchFromBuildDir(String buildDirectory) {
+  if (buildDirectory.endsWith('SIMARM')) return '';
+  if (buildDirectory.endsWith('SIMARM64')) return '';
+  if (buildDirectory.endsWith('ARM')) return '-arm';
+  if (buildDirectory.endsWith('ARM64')) return '-arm64';
+  if (buildDirectory.endsWith('IA32')) return '-ia32';
+  if (buildDirectory.endsWith('X64')) return '-x64';
+  return 'unknown';
+}
+
+Future testExtension(bool withArchSuffix) async {
+  String scriptDirectory = dirname(Platform.script.toFilePath());
+  String buildDirectory = dirname(Platform.executable);
+  Directory tempDirectory =
+      Directory.systemTemp.createTempSync('dart_test_extension');
+  String testDirectory = tempDirectory.path;
+
+  List<String> fileNames;
+  if (withArchSuffix) {
+    String arch = getArchFromBuildDir(buildDirectory);
+    fileNames = getExtensionNames(arch);
+  } else {
+    fileNames = getExtensionNames('');
+  }
+
+  try {
+    // Copy test_extension shared library, test_extension.dart and
+    // test_extension_tester.dart to the temporary test directory.
+    await copyFileToDirectory(getExtensionPath(buildDirectory, fileNames[0]),
+        join(testDirectory, fileNames[1]));
+
+    var extensionDartFile = join(scriptDirectory, 'test_extension.dart');
+    await copyFileToDirectory(extensionDartFile, testDirectory);
+
+    var testExtensionTesterFile =
+        join(scriptDirectory, 'test_extension_tester.dart');
+    await copyFileToDirectory(testExtensionTesterFile, testDirectory);
+
+    var args = new List<String>.from(Platform.executableArguments)
+      ..add(join(testDirectory, 'test_extension_tester.dart'));
+    ProcessResult result = await Process.run(Platform.executable, args);
+
+    if (result.exitCode != 0) {
+      print('Subprocess failed with exit code ${result.exitCode}');
+      print('stdout:');
+      print('${result.stdout}');
+      print('stderr:');
+      print('${result.stderr}');
+    }
+    Expect.equals(0, result.exitCode);
+  } finally {
+    tempDirectory.deleteSync(recursive: true);
+  }
+}
+
+Future testWithArchSuffix() {
+  return testExtension(true);
+}
+
+Future testWithoutArchSuffix() {
+  return testExtension(false);
+}
+
+main() async {
+  await testWithArchSuffix();
+  await testWithoutArchSuffix();
+}
diff --git a/tests/standalone/io/test_extension_tester.dart b/tests/standalone/io/test_extension_tester.dart
new file mode 100644
index 0000000..7a3308c
--- /dev/null
+++ b/tests/standalone/io/test_extension_tester.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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+library test_extension_test;
+
+import 'dart:isolate';
+
+import "test_extension.dart";
+
+class Expect {
+  static void equals(expected, actual, [msg]) {
+    if (expected != actual) {
+      if (msg == null) msg = "Expected: $expected. Actual: $actual";
+      throw new StateError(msg);
+    }
+  }
+
+  static void isNull(x, [msg]) {
+    if (x != null) {
+      if (msg != null) msg = "$x not null";
+      throw new StateError(msg);
+    }
+  }
+}
+
+isolateHandler(_) {}
+
+main() async {
+  Expect.equals('cat 13', new Cat(13).toString(), 'new Cat(13).toString()');
+
+  Expect.equals(3, Cat.ifNull(null, 3), 'Cat.ifNull(null, 3)');
+  Expect.equals(4, Cat.ifNull(4, null), 'Cat.ifNull(4, null)');
+  Expect.equals(5, Cat.ifNull(5, 9), 'Cat.ifNull(5, 9)');
+  Expect.isNull(Cat.ifNull(null, null), 'Cat.ifNull(null, null)');
+
+  try {
+    Cat.throwMeTheBall("ball");
+  } on String catch (e) {
+    Expect.equals("ball", e);
+  }
+
+  await Isolate.spawn(isolateHandler, []);
+}
diff --git a/tests/standalone/io/test_relative_extension.dart b/tests/standalone/io/test_relative_extension.dart
new file mode 100644
index 0000000..79f9489
--- /dev/null
+++ b/tests/standalone/io/test_relative_extension.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.
+
+library test_extension;
+
+import "dart-ext:extension/test_extension";
+
+class Cat {
+  Cat(this.x);
+
+  num x;
+
+  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 throwMeTheBall(ball) native 'TestExtension_ThrowMeTheBall';
+}
diff --git a/tests/standalone/io/test_relative_extension_fail_tester.dart b/tests/standalone/io/test_relative_extension_fail_tester.dart
new file mode 100644
index 0000000..ad37cf0
--- /dev/null
+++ b/tests/standalone/io/test_relative_extension_fail_tester.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.
+
+library test_extension_test;
+
+import "dart:async";
+import "dart:isolate";
+import "test_relative_extension.dart";
+
+main() {
+  try {
+    Cat.throwMeTheBall("ball");
+  } on String catch (e) {
+    if (e != "ball") throw new StateError("exception not equal to 'ball'");
+  }
+  // Make sure the exception is thrown out to the event handler from C++ code.
+  // The harness expects the string "ball" to be thrown and the process to
+  // end with an unhandled exception.
+  Timer.run(() => Cat.throwMeTheBall("ball"));
+}
diff --git a/tests/standalone/io/test_utils.dart b/tests/standalone/io/test_utils.dart
new file mode 100644
index 0000000..fb3b3ef
--- /dev/null
+++ b/tests/standalone/io/test_utils.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 'dart:async';
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+int lastRetryId = 0;
+
+Future retry(Future fun(), {int maxCount: 10}) async {
+  final int id = lastRetryId++;
+  for (int i = 0; i < maxCount; i++) {
+    try {
+      // If there is no exception this will simply return, otherwise we keep
+      // trying.
+      return await fun();
+    } catch (e, stack) {
+      print("Failed to execute test closure (retry id: ${id}) in attempt $i "
+          "(${maxCount - i} retries left).");
+      print("Exception: ${e}");
+      print("Stacktrace: ${stack}");
+    }
+  }
+  return await fun();
+}
+
+Future throws(Function f, bool check(Object exception)) async {
+  try {
+    await f();
+  } catch (e) {
+    if (!check(e)) {
+      Expect.fail('Unexpected: $e');
+    }
+    return;
+  }
+  Expect.fail('Did not throw');
+}
diff --git a/tests/standalone/io/testing_server.dart b/tests/standalone/io/testing_server.dart
new file mode 100644
index 0000000..e4c5c26
--- /dev/null
+++ b/tests/standalone/io/testing_server.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of ServerTest;
+
+abstract class TestingServer {
+  static const HOST = "127.0.0.1";
+  static const INIT = 0;
+  static const SHUTDOWN = -1;
+
+  void onConnection(Socket connection); // Abstract.
+
+  void errorHandlerServer(e, trace) {
+    String msg = "Server socket error $e";
+    if (trace != null) msg += "\nStackTrace: $trace";
+    Expect.fail(msg);
+  }
+
+  SendPort get closeSendPort => _closePort.sendPort;
+
+  Future<int> init() {
+    _closePort.first.then((_) {
+      close();
+    });
+    return ServerSocket.bind(HOST, 0).then((server) {
+      _server = server;
+      _server.listen(onConnection, onError: errorHandlerServer);
+      return _server.port;
+    });
+  }
+
+  void close() {
+    _server.close();
+  }
+
+  late ServerSocket _server;
+  final ReceivePort _closePort = new ReceivePort();
+}
diff --git a/tests/standalone/io/unknown_host_test.dart b/tests/standalone/io/unknown_host_test.dart
new file mode 100644
index 0000000..6dafaf5
--- /dev/null
+++ b/tests/standalone/io/unknown_host_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.
+//
+// Tests socket exceptions.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void unknownHostTest() {
+  asyncStart();
+  Socket.connect("hede.hule.hest", 1234)
+      .then((socket) => Expect.fail("Connection completed"))
+      .catchError((e) => asyncEnd(), test: (e) => e is SocketException);
+}
+
+main() {
+  asyncStart();
+  unknownHostTest();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/uri_platform_test.dart b/tests/standalone/io/uri_platform_test.dart
new file mode 100644
index 0000000..f2d26dc
--- /dev/null
+++ b/tests/standalone/io/uri_platform_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.
+
+import "package:expect/expect.dart";
+import 'package:path/path.dart' as path;
+import "dart:io";
+
+main() {
+  if (Platform.isWindows) {
+    Expect.equals("a\\b", Uri.parse("a/b").toFilePath());
+    Expect.equals("a\\b\\", Uri.parse("a/b/").toFilePath());
+    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+    Expect.equals("\\a b", Uri.parse("file:///a%20b").toFilePath());
+    Expect.equals("\\a\\b", Uri.parse("file:///a/b").toFilePath());
+    Expect.equals("C:\\", Uri.parse("file:///C:").toFilePath());
+    Expect.equals("C:\\", Uri.parse("file:///C:/").toFilePath());
+    Expect.equals("\\\\host\\a\\b", Uri.parse("file://host/a/b").toFilePath());
+
+    Expect.equals("a\\b", new Uri.file("a/b").toFilePath());
+    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("/a/b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("\\a\\b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("\\a/b").toFilePath());
+    Expect.equals("\\a\\b", new Uri.file("/a\\b").toFilePath());
+  } else {
+    Expect.equals("a/b", Uri.parse("a/b").toFilePath());
+    Expect.equals("a/b/", Uri.parse("a/b/").toFilePath());
+    Expect.equals("a b", Uri.parse("a%20b").toFilePath());
+    Expect.equals("/a b", Uri.parse("file:///a%20b").toFilePath());
+    Expect.equals("/a/b", Uri.parse("file:///a/b").toFilePath());
+    Expect.equals("/C:", Uri.parse("file:///C:").toFilePath());
+    Expect.equals("/C:/", Uri.parse("file:///C:/").toFilePath());
+    Expect.throwsUnsupportedError(
+        () => Uri.parse("file://host/a/b").toFilePath());
+
+    Expect.equals("a/b", new Uri.file("a/b").toFilePath());
+    Expect.equals("a\\b", new Uri.file("a\\b").toFilePath());
+  }
+  // If the current path is only the root prefix (/ (or c:\), then don't add a
+  // separator at the end.
+  Expect.equals(
+      Uri.base,
+      (Directory.current.path.toString() !=
+              path.rootPrefix(Directory.current.path.toString()))
+          ? new Uri.file(Directory.current.path + Platform.pathSeparator)
+          : new Uri.file(Directory.current.path));
+}
diff --git a/tests/standalone/io/wait_for_event_helper.dart b/tests/standalone/io/wait_for_event_helper.dart
new file mode 100644
index 0000000..b22a1e0
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_helper.dart
@@ -0,0 +1,24 @@
+// 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:mirrors';
+import 'dart:cli';
+
+late void Function({Duration timeout}) waitForEvent;
+
+void initWaitForEvent() {
+  LibraryMirror lib = currentMirrorSystem().findLibrary(#dart.cli);
+  for (Symbol s in lib.declarations.keys) {
+    if (s.toString().contains("_WaitForUtils")) {
+      DeclarationMirror d = lib.declarations[s]!;
+      ClassMirror utils = (d as ClassMirror);
+      for (Symbol m in utils.staticMembers.keys) {
+        if (m.toString().contains("waitForEvent")) {
+          waitForEvent = utils.getField(m).reflectee;
+        }
+      }
+    }
+  }
+}
diff --git a/tests/standalone/io/wait_for_event_isolate_test.dart b/tests/standalone/io/wait_for_event_isolate_test.dart
new file mode 100644
index 0000000..ce624e2
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_isolate_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() returns on an Isolate message.
+
+messageSender(SendPort s) {
+  new Timer(const Duration(seconds: 1), () {
+    s.send(true);
+  });
+}
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag1 = false;
+  bool flag2 = false;
+  ReceivePort r = new ReceivePort();
+  Isolate.spawn(messageSender, r.sendPort).then((Isolate i) {
+    r.listen((message) {
+      flag1 = true;
+    });
+    Expect.isFalse(flag1);
+    waitForEvent();
+    Expect.isTrue(flag1);
+    r.close();
+    flag2 = true;
+  });
+  Expect.isFalse(flag1);
+  Expect.isFalse(flag2);
+  waitForEvent();
+  Expect.isTrue(flag1);
+  Expect.isTrue(flag2);
+  asyncEnd();
+}
diff --git a/tests/standalone/io/wait_for_event_microtask_test.dart b/tests/standalone/io/wait_for_event_microtask_test.dart
new file mode 100644
index 0000000..b707265
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_microtask_test.dart
@@ -0,0 +1,26 @@
+// 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:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that microtasks are run before waitForEvent() blocks.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  scheduleMicrotask(() {
+    flag = true;
+    asyncEnd();
+  });
+  Expect.isFalse(flag);
+  waitForEvent(timeout: const Duration(milliseconds: 10));
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/wait_for_event_nested_microtask_test.dart b/tests/standalone/io/wait_for_event_nested_microtask_test.dart
new file mode 100644
index 0000000..cb11bf9
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_nested_microtask_test.dart
@@ -0,0 +1,36 @@
+// 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:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() drains microtasks before blocking even when
+// called from a microtask.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag1 = false;
+  bool flag2 = false;
+  scheduleMicrotask(() {
+    scheduleMicrotask(() {
+      flag1 = true;
+      asyncEnd();
+    });
+    Expect.isFalse(flag1);
+    waitForEvent(timeout: const Duration(milliseconds: 10));
+    Expect.isTrue(flag1);
+    flag2 = true;
+  });
+  Expect.isFalse(flag1);
+  Expect.isFalse(flag2);
+  waitForEvent(timeout: const Duration(milliseconds: 10));
+  Expect.isTrue(flag1);
+  Expect.isTrue(flag2);
+}
diff --git a/tests/standalone/io/wait_for_event_nested_timer_microtask_test.dart b/tests/standalone/io/wait_for_event_nested_timer_microtask_test.dart
new file mode 100644
index 0000000..7fbac17
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_nested_timer_microtask_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 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that the microtasks for a message handler are run before
+// waitForEvent() returns.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  Timer.run(() {
+    scheduleMicrotask(() {
+      flag = true;
+      asyncEnd();
+    });
+  });
+  Expect.isFalse(flag);
+  waitForEvent();
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/wait_for_event_nested_timer_test.dart b/tests/standalone/io/wait_for_event_nested_timer_test.dart
new file mode 100644
index 0000000..6971952
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_nested_timer_test.dart
@@ -0,0 +1,32 @@
+// 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:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that all messages are processed before waitForEvent() returns.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  Timer.run(() {
+    Timer.run(() {
+      Timer.run(() {
+        Timer.run(() {
+          flag = true;
+          asyncEnd();
+        });
+      });
+    });
+  });
+  Expect.isFalse(flag);
+  waitForEvent();
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/wait_for_event_nested_waits_test.dart b/tests/standalone/io/wait_for_event_nested_waits_test.dart
new file mode 100644
index 0000000..0701996
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_nested_waits_test.dart
@@ -0,0 +1,71 @@
+// 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:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works when called from a message handler.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag1 = false;
+  bool flag2 = false;
+  bool flag3 = false;
+  bool flag4 = false;
+  Timer.run(() {
+    Timer.run(() {
+      Timer.run(() {
+        Timer.run(() {
+          flag1 = true;
+          asyncEnd();
+        });
+        Expect.isFalse(flag1);
+        Expect.isFalse(flag2);
+        Expect.isFalse(flag3);
+        Expect.isFalse(flag4);
+        waitForEvent();
+        Expect.isTrue(flag1);
+        Expect.isFalse(flag2);
+        Expect.isFalse(flag3);
+        Expect.isFalse(flag4);
+        flag2 = true;
+      });
+      Expect.isFalse(flag1);
+      Expect.isFalse(flag2);
+      Expect.isFalse(flag3);
+      Expect.isFalse(flag4);
+      waitForEvent();
+      Expect.isTrue(flag1);
+      Expect.isTrue(flag2);
+      Expect.isFalse(flag3);
+      Expect.isFalse(flag4);
+      flag3 = true;
+    });
+    Expect.isFalse(flag1);
+    Expect.isFalse(flag2);
+    Expect.isFalse(flag3);
+    Expect.isFalse(flag4);
+    waitForEvent();
+    Expect.isTrue(flag1);
+    Expect.isTrue(flag2);
+    Expect.isTrue(flag3);
+    Expect.isFalse(flag4);
+    flag4 = true;
+  });
+  Expect.isFalse(flag1);
+  Expect.isFalse(flag2);
+  Expect.isFalse(flag3);
+  Expect.isFalse(flag4);
+  waitForEvent();
+  Expect.isTrue(flag1);
+  Expect.isTrue(flag2);
+  Expect.isTrue(flag3);
+  Expect.isTrue(flag4);
+}
diff --git a/tests/standalone/io/wait_for_event_timer_test.dart b/tests/standalone/io/wait_for_event_timer_test.dart
new file mode 100644
index 0000000..5ce0a64
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_timer_test.dart
@@ -0,0 +1,26 @@
+// 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:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works in a simple case.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  Timer.run(() {
+    flag = true;
+    asyncEnd();
+  });
+  Expect.isFalse(flag);
+  waitForEvent();
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/wait_for_event_zone_caught_error_test.dart b/tests/standalone/io/wait_for_event_zone_caught_error_test.dart
new file mode 100644
index 0000000..09e60c4
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_zone_caught_error_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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() doesn't cause an error to escape a Zone that
+// has an error handler.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  runZoned(() {
+    Timer.run(() {
+      asyncEnd();
+      throw "Exception";
+    });
+  }, onError: (e) {
+    flag = true;
+  });
+  Expect.isFalse(flag);
+  waitForEvent();
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/wait_for_event_zone_test.dart b/tests/standalone/io/wait_for_event_zone_test.dart
new file mode 100644
index 0000000..b6a7825
--- /dev/null
+++ b/tests/standalone/io/wait_for_event_zone_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 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works even when the message handler is run in
+// a different Zone.
+
+main() {
+  initWaitForEvent();
+  asyncStart();
+  bool flag = false;
+  runZoned(() {
+    Timer.run(() {
+      flag = true;
+      asyncEnd();
+    });
+  });
+  Expect.isFalse(flag);
+  waitForEvent();
+  Expect.isTrue(flag);
+}
diff --git a/tests/standalone/io/web_socket_compression_test.dart b/tests/standalone/io/web_socket_compression_test.dart
new file mode 100644
index 0000000..37b458e
--- /dev/null
+++ b/tests/standalone/io/web_socket_compression_test.dart
@@ -0,0 +1,382 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+import "dart:typed_data";
+import "dart:math";
+
+import "package:async_helper/async_helper.dart";
+import "package:crypto/crypto.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+const String HOST_NAME = 'localhost';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+class SecurityConfiguration {
+  final bool secure;
+
+  SecurityConfiguration(this.secure);
+
+  Future<HttpServer> createServer({int backlog: 0}) => secure
+      ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
+      : HttpServer.bind(HOST_NAME, 0, backlog: backlog);
+
+  Future<WebSocket> createClient(int port) =>
+      // TODO(whesse): Add client context argument to WebSocket.connect
+      WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
+
+  Future<HttpClientResponse> createWebsocket(String url, String headerValue) {
+    HttpClient _httpClient = new HttpClient();
+    Uri uri = Uri.parse(url);
+
+    Random random = new Random();
+    // Generate 16 random bytes.
+    Uint8List nonceData = new Uint8List(16);
+    for (int i = 0; i < 16; i++) {
+      nonceData[i] = random.nextInt(256);
+    }
+    String nonce = base64.encode(nonceData);
+
+    uri = new Uri(
+        scheme: uri.scheme == "wss" ? "https" : "http",
+        userInfo: uri.userInfo,
+        host: uri.host,
+        port: uri.port,
+        path: uri.path,
+        query: uri.query,
+        fragment: uri.fragment);
+    return _httpClient.openUrl("GET", uri).then((request) {
+      if (uri.userInfo != null && !uri.userInfo.isEmpty) {
+        // If the URL contains user information use that for basic
+        // authorization.
+        String auth = base64.encode(utf8.encode(uri.userInfo));
+        request.headers.set(HttpHeaders.authorizationHeader, "Basic $auth");
+      }
+      // Setup the initial handshake.
+      request.headers
+        ..set(HttpHeaders.connectionHeader, "Upgrade")
+        ..set(HttpHeaders.upgradeHeader, "websocket")
+        ..set("Sec-WebSocket-Key", nonce)
+        ..set("Cache-Control", "no-cache")
+        ..set("Sec-WebSocket-Version", "13")
+        ..set("Sec-WebSocket-Extensions", headerValue);
+
+      return request.close();
+    });
+  }
+
+  void testCompressionSupport(
+      {server: false, client: false, contextTakeover: false}) {
+    asyncStart();
+
+    var clientOptions = new CompressionOptions(
+        enabled: client,
+        serverNoContextTakeover: contextTakeover,
+        clientNoContextTakeover: contextTakeover);
+    var serverOptions = new CompressionOptions(
+        enabled: server,
+        serverNoContextTakeover: contextTakeover,
+        clientNoContextTakeover: contextTakeover);
+
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        WebSocketTransformer.upgrade(request, compression: serverOptions)
+            .then((webSocket) {
+          webSocket.listen((message) {
+            Expect.equals("Hello World", message);
+
+            webSocket.add(message);
+            webSocket.close();
+          });
+          webSocket.add("Hello World");
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+      WebSocket.connect(url, compression: clientOptions).then((websocket) {
+        var future = websocket.listen((message) {
+          Expect.equals("Hello World", message);
+        }).asFuture();
+        websocket.add("Hello World");
+        return future;
+      }).then((_) {
+        server.close();
+        asyncEnd();
+      });
+    });
+  }
+
+  void testContextSupport(
+      {CompressionOptions serverOpts: CompressionOptions.compressionDefault,
+      CompressionOptions clientOpts: CompressionOptions.compressionDefault,
+      int? messages}) {
+    asyncStart();
+
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        WebSocketTransformer.upgrade(request, compression: serverOpts)
+            .then((webSocket) {
+          webSocket.listen((message) {
+            Expect.equals("Hello World", message);
+            webSocket.add(message);
+          });
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+      WebSocket.connect(url, compression: clientOpts).then((websocket) {
+        var i = 1;
+        websocket.listen((message) {
+          Expect.equals("Hello World", message);
+          if (i == messages) {
+            websocket.close();
+            return;
+          }
+          websocket.add("Hello World");
+          i++;
+        }, onDone: () {
+          server.close();
+          asyncEnd();
+        });
+        websocket.add("Hello World");
+      });
+    });
+  }
+
+  void testCompressionHeaders() {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.equals(
+            'Upgrade', request.headers.value(HttpHeaders.connectionHeader));
+        Expect.equals(
+            'websocket', request.headers.value(HttpHeaders.upgradeHeader));
+
+        var key = request.headers.value('Sec-WebSocket-Key');
+        var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
+        var accept = base64.encode(digest.bytes);
+        request.response
+          ..statusCode = HttpStatus.switchingProtocols
+          ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
+          ..headers.add(HttpHeaders.upgradeHeader, "websocket")
+          ..headers.add("Sec-WebSocket-Accept", accept)
+          ..headers.add(
+              "Sec-WebSocket-Extensions",
+              "permessage-deflate;"
+                  // Test quoted values and space padded =
+                  'server_max_window_bits="10"; client_max_window_bits = 12'
+                  'client_no_context_takeover; server_no_context_takeover');
+        request.response.contentLength = 0;
+        request.response.detachSocket().then((socket) {
+          return new WebSocket.fromUpgradedSocket(socket, serverSide: true);
+        }).then((websocket) {
+          websocket.add("Hello");
+          websocket.close();
+          asyncEnd();
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+
+      WebSocket.connect(url).then((websocket) {
+        return websocket.listen((message) {
+          Expect.equals("Hello", message);
+          websocket.close();
+        }).asFuture();
+      }).then((_) => server.close());
+    });
+  }
+
+  void testReturnHeaders(String headerValue, String expected,
+      {CompressionOptions serverCompression:
+          CompressionOptions.compressionDefault}) {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        // Stuff
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        WebSocketTransformer.upgrade(request, compression: serverCompression)
+            .then((webSocket) {
+          webSocket.listen((message) {
+            Expect.equals("Hello World", message);
+
+            webSocket.add(message);
+            webSocket.close();
+          });
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+      createWebsocket(url, headerValue).then((HttpClientResponse response) {
+        Expect.equals(response.statusCode, HttpStatus.switchingProtocols);
+        print(response.headers.value('Sec-WebSocket-Extensions'));
+        Expect.equals(
+            response.headers.value("Sec-WebSocket-Extensions"), expected);
+
+        String accept = response.headers.value("Sec-WebSocket-Accept")!;
+
+        var protocol = response.headers.value('Sec-WebSocket-Protocol');
+        return response.detachSocket().then((socket) =>
+            new WebSocket.fromUpgradedSocket(socket,
+                protocol: protocol, serverSide: false));
+      }).then((websocket) {
+        var future = websocket.listen((message) {
+          Expect.equals("Hello", message);
+          websocket.close();
+        }).asFuture();
+        websocket.add("Hello World");
+        return future;
+      }).then((_) {
+        server.close();
+        asyncEnd();
+      });
+    }); // End createServer
+  }
+
+  void testClientRequestHeaders(CompressionOptions compression) {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        var extensionHeader =
+            request.headers.value('Sec-WebSocket-Extensions')!;
+        var hv = HeaderValue.parse(extensionHeader);
+        Expect.equals(compression.serverNoContextTakeover,
+            hv.parameters.containsKey('server_no_context_takeover'));
+        Expect.equals(compression.clientNoContextTakeover,
+            hv.parameters.containsKey('client_no_context_takeover'));
+        Expect.equals(compression.serverMaxWindowBits?.toString(),
+            hv.parameters['server_max_window_bits']);
+        Expect.equals(compression.clientMaxWindowBits?.toString(),
+            hv.parameters['client_max_window_bits']);
+
+        WebSocketTransformer.upgrade(request).then((webSocket) {
+          webSocket.listen((message) {
+            Expect.equals('Hello World', message);
+
+            webSocket.add(message);
+            webSocket.close();
+          });
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+
+      WebSocket.connect(url, compression: compression).then((websocket) {
+        var future = websocket.listen((message) {
+          Expect.equals('Hello World', message);
+          websocket.close();
+        }).asFuture();
+        websocket.add('Hello World');
+        return future;
+      }).then((_) {
+        server.close();
+        asyncEnd();
+      });
+    });
+  }
+
+  void runTests() {
+    // No compression or takeover
+    testCompressionSupport();
+    // compression no takeover
+    testCompressionSupport(server: true, client: true);
+    // compression and context takeover.
+    testCompressionSupport(server: true, client: true, contextTakeover: true);
+    // Compression on client but not server. No take over
+    testCompressionSupport(client: true);
+    // Compression on server but not client.
+    testCompressionSupport(server: true);
+
+    // Test Multiple messages with various context takeover configurations.
+    // no context takeover on the server.
+    var serverComp = new CompressionOptions(serverNoContextTakeover: true);
+    testContextSupport(
+        serverOpts: serverComp, clientOpts: serverComp, messages: 5);
+    // no contexttakeover on the client.
+    var clientComp = new CompressionOptions(clientNoContextTakeover: true);
+    testContextSupport(
+        serverOpts: clientComp, clientOpts: clientComp, messages: 5);
+    // no context takeover enabled for both.
+    var compression = new CompressionOptions(
+        serverNoContextTakeover: true, clientNoContextTakeover: true);
+    testContextSupport(
+        serverOpts: compression, clientOpts: compression, messages: 5);
+    // no context take over for opposing configurations.
+    testContextSupport(
+        serverOpts: serverComp, clientOpts: clientComp, messages: 5);
+    testContextSupport(
+        serverOpts: clientComp, clientOpts: serverComp, messages: 5);
+
+    testCompressionHeaders();
+    // Chrome headers
+    testReturnHeaders('permessage-deflate; client_max_window_bits',
+        "permessage-deflate; client_max_window_bits=15");
+    // Firefox headers
+    testReturnHeaders(
+        'permessage-deflate', "permessage-deflate; client_max_window_bits=15");
+    // Ensure max_window_bits resize appropriately.
+    testReturnHeaders(
+        'permessage-deflate; server_max_window_bits=10',
+        "permessage-deflate;"
+            " server_max_window_bits=10;"
+            " client_max_window_bits=10");
+    // Don't provider context takeover if requested but not enabled.
+    // Default is not enabled.
+    testReturnHeaders(
+        'permessage-deflate; client_max_window_bits;'
+            'client_no_context_takeover',
+        'permessage-deflate; client_max_window_bits=15');
+    // Enable context Takeover and provide if requested.
+    compression = new CompressionOptions(
+        clientNoContextTakeover: true, serverNoContextTakeover: true);
+    testReturnHeaders(
+        'permessage-deflate; client_max_window_bits; '
+            'client_no_context_takeover',
+        'permessage-deflate; client_no_context_takeover; '
+            'client_max_window_bits=15',
+        serverCompression: compression);
+    // Enable context takeover and don't provide if not requested
+    compression = new CompressionOptions(
+        clientNoContextTakeover: true, serverNoContextTakeover: true);
+    testReturnHeaders('permessage-deflate; client_max_window_bits; ',
+        'permessage-deflate; client_max_window_bits=15',
+        serverCompression: compression);
+
+    compression = CompressionOptions.compressionDefault;
+    testClientRequestHeaders(compression);
+    compression = new CompressionOptions(
+        clientNoContextTakeover: true, serverNoContextTakeover: true);
+    testClientRequestHeaders(compression);
+    compression = new CompressionOptions(
+        clientNoContextTakeover: true,
+        serverNoContextTakeover: true,
+        clientMaxWindowBits: 8,
+        serverMaxWindowBits: 8);
+    testClientRequestHeaders(compression);
+  }
+}
+
+main() {
+  new SecurityConfiguration(false).runTests();
+  // TODO(whesse): Make WebSocket.connect() take an optional context: parameter.
+  // new SecurityConfiguration(true).runTests();
+}
diff --git a/tests/standalone/io/web_socket_error_test.dart b/tests/standalone/io/web_socket_error_test.dart
new file mode 100644
index 0000000..659ee7f
--- /dev/null
+++ b/tests/standalone/io/web_socket_error_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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+
+// @dart = 2.6
+
+library dart._http;
+
+import "dart:async";
+import "dart:io";
+import "dart:math";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+part "../../../sdk/lib/_http/crypto.dart";
+
+const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+const String CERT_NAME = 'localhost_cert';
+const String HOST_NAME = 'localhost';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+/**
+ * A SecurityConfiguration lets us run the tests over HTTP or HTTPS.
+ */
+class SecurityConfiguration {
+  final bool secure;
+
+  SecurityConfiguration({bool this.secure});
+
+  Future<HttpServer> createServer({int backlog: 0}) => secure
+      ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
+      : HttpServer.bind(HOST_NAME, 0, backlog: backlog);
+
+  Future<WebSocket> createClient(int port) =>
+      // TODO(whesse): Add a client context argument to WebSocket.connect.
+      WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
+
+  void testForceCloseServerEnd(int totalConnections) {
+    createServer().then((server) {
+      server.listen((request) {
+        var response = request.response;
+        response.statusCode = HttpStatus.switchingProtocols;
+        response.headers.set(HttpHeaders.connectionHeader, "upgrade");
+        response.headers.set(HttpHeaders.upgradeHeader, "websocket");
+        String key = request.headers.value("Sec-WebSocket-Key");
+        _SHA1 sha1 = new _SHA1();
+        sha1.add("$key$webSocketGUID".codeUnits);
+        String accept = _CryptoUtils.bytesToBase64(sha1.close());
+        response.headers.add("Sec-WebSocket-Accept", accept);
+        response.headers.contentLength = 0;
+        response.detachSocket().then((socket) {
+          socket.destroy();
+        });
+      });
+
+      int closeCount = 0;
+      for (int i = 0; i < totalConnections; i++) {
+        createClient(server.port).then((webSocket) {
+          webSocket.add("Hello, world!");
+          webSocket.listen((message) {
+            Expect.fail("unexpected message");
+          }, onDone: () {
+            closeCount++;
+            if (closeCount == totalConnections) {
+              server.close();
+            }
+          });
+        });
+      }
+    });
+  }
+
+  void runTests() {
+    testForceCloseServerEnd(10);
+  }
+}
+
+main() {
+  asyncStart();
+  new SecurityConfiguration(secure: false).runTests();
+  // TODO(whesse): WebSocket.connect needs an optional context: parameter
+  // new SecurityConfiguration(secure: true).runTests();
+  asyncEnd();
+}
diff --git a/tests/standalone/io/web_socket_ping_test.dart b/tests/standalone/io/web_socket_ping_test.dart
new file mode 100644
index 0000000..3960958
--- /dev/null
+++ b/tests/standalone/io/web_socket_ping_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+// @dart = 2.6
+
+library dart._http;
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+import "dart:math";
+import "dart:typed_data";
+
+part "../../../sdk/lib/_http/crypto.dart";
+
+const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+void testPing(int totalConnections) {
+  HttpServer.bind('localhost', 0).then((server) {
+    int closed = 0;
+    server.listen((request) {
+      var response = request.response;
+      response.statusCode = HttpStatus.switchingProtocols;
+      response.headers.set(HttpHeaders.connectionHeader, "upgrade");
+      response.headers.set(HttpHeaders.upgradeHeader, "websocket");
+      String key = request.headers.value("Sec-WebSocket-Key");
+      _SHA1 sha1 = new _SHA1();
+      sha1.add("$key$webSocketGUID".codeUnits);
+      String accept = _CryptoUtils.bytesToBase64(sha1.close());
+      response.headers.add("Sec-WebSocket-Accept", accept);
+      response.headers.contentLength = 0;
+      response.detachSocket().then((socket) {
+        socket.drain().then((_) {
+          socket.close();
+          closed++;
+          if (closed == totalConnections) {
+            server.close();
+          }
+        });
+      });
+    });
+
+    for (int i = 0; i < totalConnections; i++) {
+      WebSocket.connect('ws://localhost:${server.port}').then((webSocket) {
+        webSocket.pingInterval = const Duration(milliseconds: 100);
+        webSocket.drain();
+      });
+    }
+  });
+}
+
+void main() {
+  testPing(10);
+}
diff --git a/tests/standalone/io/web_socket_pipe_test.dart b/tests/standalone/io/web_socket_pipe_test.dart
new file mode 100644
index 0000000..b54cd79
--- /dev/null
+++ b/tests/standalone/io/web_socket_pipe_test.dart
@@ -0,0 +1,65 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+createReverseStringTransformer() {
+  return new StreamTransformer.fromHandlers(handleData: (String data, sink) {
+    var sb = new StringBuffer();
+    for (int i = data.length - 1; i >= 0; i--) sb.write(data[i]);
+    sink.add(sb.toString());
+  });
+}
+
+testPipe({required int messages, required bool transform}) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      WebSocketTransformer.upgrade(request).then((websocket) {
+        (transform
+                ? websocket.transform(createReverseStringTransformer())
+                : websocket)
+            .pipe(websocket)
+            .then((_) => server.close());
+      });
+    });
+    WebSocket.connect("ws://127.0.0.1:${server.port}/").then((client) {
+      var count = 0;
+      next() {
+        if (count < messages) {
+          client.add("Hello");
+        } else {
+          client.close();
+        }
+      }
+
+      client.listen((data) {
+        count++;
+        if (transform) {
+          Expect.equals("olleH", data);
+        } else {
+          Expect.equals("Hello", data);
+        }
+        next();
+      }, onDone: () => print("Client received close"));
+
+      next();
+    });
+  });
+}
+
+void main() {
+  testPipe(messages: 0, transform: false);
+  testPipe(messages: 0, transform: true);
+  testPipe(messages: 1, transform: false);
+  testPipe(messages: 1, transform: true);
+  testPipe(messages: 10, transform: false);
+  testPipe(messages: 10, transform: true);
+}
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
new file mode 100644
index 0000000..fc50c61
--- /dev/null
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -0,0 +1,242 @@
+// 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 = 2.6
+
+library dart._http;
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:developer";
+import "dart:io";
+import "dart:math";
+import "dart:typed_data";
+import "dart:isolate";
+
+part "../../../sdk/lib/_http/crypto.dart";
+part "../../../sdk/lib/_http/http_impl.dart";
+part "../../../sdk/lib/_http/http_date.dart";
+part "../../../sdk/lib/_http/http_parser.dart";
+part "../../../sdk/lib/_http/http_headers.dart";
+part "../../../sdk/lib/_http/http_session.dart";
+part "../../../sdk/lib/_http/websocket.dart";
+part "../../../sdk/lib/_http/websocket_impl.dart";
+
+class WebSocketFrame {
+  WebSocketFrame(int opcode, List<int> data);
+}
+
+// Class that when hooked up to the web socket protocol transformer will
+// collect the message and expect it to be equal to the
+// expectedMessage field when fully received.
+class WebSocketMessageCollector {
+  List<int> expectedMessage;
+
+  int messageCount = 0;
+
+  var data;
+
+  Function onClosed;
+
+  WebSocketMessageCollector(Stream stream,
+      [List<int> this.expectedMessage = null]) {
+    stream.listen(onMessageData, onDone: onClosed, onError: onError);
+  }
+
+  void onMessageData(buffer) {
+    if (buffer is String) {
+      buffer = utf8.encode(buffer);
+    }
+    Expect.listEquals(expectedMessage, buffer);
+    messageCount++;
+    data = buffer;
+  }
+
+  void onError(e, trace) {
+    String msg = "Unexpected error $e";
+    if (trace != null) msg += "\nStackTrace: $trace";
+    Expect.fail(msg);
+  }
+}
+
+// Web socket constants.
+const int FRAME_OPCODE_TEXT = 1;
+const int FRAME_OPCODE_BINARY = 2;
+
+// Function for building a web socket frame.
+List<int> createFrame(bool fin, int opcode, int maskingKey, List<int> data,
+    int offset, int count) {
+  int frameSize = 2;
+  if (count > 125) frameSize += 2;
+  if (count > 65535) frameSize += 6;
+  frameSize += count;
+  // No masking.
+  assert(maskingKey == null);
+  List<int> frame = new Uint8List(frameSize);
+  int frameIndex = 0;
+  frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode;
+  if (count < 126) {
+    frame[frameIndex++] = count;
+  } else if (count < 65536) {
+    frame[frameIndex++] = 126;
+    frame[frameIndex++] = count >> 8;
+    frame[frameIndex++] = count & 0xFF;
+  } else {
+    frame[frameIndex++] = 127;
+    for (int i = 0; i < 8; i++) {
+      frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF;
+    }
+  }
+  frame.setRange(frameIndex, frameIndex + count, data, offset);
+  return frame;
+}
+
+// Test processing messages which are sent in a single frame.
+void testFullMessages() {
+  void testMessage(int opcode, List<int> message) {
+    int messageCount = 0;
+    // Use the same web socket protocol transformer for all frames.
+    var transformer = new _WebSocketProtocolTransformer();
+    var controller = new StreamController<List<int>>(sync: true);
+    WebSocketMessageCollector mc = new WebSocketMessageCollector(
+        controller.stream.transform(transformer), message);
+
+    List<int> frame =
+        createFrame(true, opcode, null, message, 0, message.length);
+
+    // Update the transformer with one big chunk.
+    messageCount++;
+    controller.add(frame);
+    mc.onClosed = () {
+      Expect.isNotNull(mc.data);
+      Expect.equals(0, transformer._state);
+
+      mc.data = null;
+
+      // Only run this part on small messages.
+      if (message.length < 1000) {
+        // Update the transformer one byte at the time.
+        messageCount++;
+        for (int i = 0; i < frame.length; i++) {
+          controller.add(<int>[frame[i]]);
+        }
+        Expect.equals(0, transformer._state);
+        Expect.isNotNull(mc.data);
+        mc.data = null;
+
+        // Update the transformer two bytes at the time.
+        messageCount++;
+        for (int i = 0; i < frame.length; i += 2) {
+          controller.add(frame.sublist(i, min(i + 2, frame.length)));
+        }
+        Expect.equals(0, transformer._state);
+        Expect.isNotNull(mc.data);
+      }
+      Expect.equals(messageCount, mc.messageCount);
+      print("Messages test, messages $messageCount");
+    };
+    controller.close();
+  }
+
+  void runTest(int from, int to, int step) {
+    for (int messageLength = from; messageLength < to; messageLength += step) {
+      List<int> message = new List<int>(messageLength);
+      for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
+      testMessage(FRAME_OPCODE_TEXT, message);
+      for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
+      testMessage(FRAME_OPCODE_BINARY, message);
+    }
+  }
+
+  // Test different message sizes.
+  runTest(0, 10, 1);
+  runTest(120, 130, 1);
+  runTest(0, 1000, 100);
+  runTest(65534, 65537, 1);
+}
+
+// Test processing of frames which are split into fragments.
+void testFragmentedMessages() {
+  // Use the same web socket protocol transformer for all frames.
+  var transformer = new _WebSocketProtocolTransformer();
+  var controller = new StreamController<List<int>>(sync: true);
+  WebSocketMessageCollector mc =
+      new WebSocketMessageCollector(controller.stream.transform(transformer));
+
+  int messageCount = 0;
+  int frameCount = 0;
+
+  void testFragmentMessage(int opcode, List<int> message, int fragmentSize) {
+    messageCount++;
+    int messageIndex = 0;
+    int remaining = message.length;
+    bool firstFrame = true;
+    bool lastFrame = false;
+    while (!lastFrame) {
+      int payloadSize = min(fragmentSize, remaining);
+      lastFrame = payloadSize == remaining;
+      List<int> frame = createFrame(lastFrame, firstFrame ? opcode : 0x00, null,
+          message, messageIndex, payloadSize);
+      frameCount++;
+      messageIndex += payloadSize;
+      controller.add(frame);
+      remaining -= payloadSize;
+      firstFrame = false;
+    }
+  }
+
+  void testMessageFragmentation(int opcode, List<int> message) {
+    mc.expectedMessage = message;
+
+    // Test with fragmenting the message in different fragment sizes.
+    if (message.length <= 10) {
+      for (int i = 1; i < 10; i++) {
+        testFragmentMessage(opcode, message, i);
+      }
+    } else {
+      testFragmentMessage(opcode, message, 10);
+      testFragmentMessage(opcode, message, 100);
+    }
+  }
+
+  void runTest(int from, int to, int step) {
+    for (int messageLength = from; messageLength < to; messageLength += step) {
+      List<int> message = new List<int>(messageLength);
+      for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
+      testMessageFragmentation(FRAME_OPCODE_TEXT, message);
+      for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
+      testMessageFragmentation(FRAME_OPCODE_BINARY, message);
+    }
+  }
+
+  // Test different message sizes.
+  runTest(0, 10, 1);
+  runTest(120, 130, 1);
+  runTest(0, 1000, 100);
+  runTest(65534, 65537, 1);
+  print("Fragment messages test, messages $messageCount, frames $frameCount");
+  Expect.equals(messageCount, mc.messageCount);
+}
+
+void testUnmaskedMessage() {
+  var transformer = new _WebSocketProtocolTransformer(true);
+  var controller = new StreamController<List<int>>(sync: true);
+  asyncStart();
+  controller.stream.transform(transformer).listen((_) {}, onError: (e) {
+    asyncEnd();
+  });
+  var message = new Uint8List(10);
+  List<int> frame =
+      createFrame(true, FRAME_OPCODE_BINARY, null, message, 0, message.length);
+  controller.add(frame);
+}
+
+void main() {
+  testFullMessages();
+  testFragmentedMessages();
+  testUnmaskedMessage();
+}
diff --git a/tests/standalone/io/web_socket_protocol_test.dart b/tests/standalone/io/web_socket_protocol_test.dart
new file mode 100644
index 0000000..529feb9
--- /dev/null
+++ b/tests/standalone/io/web_socket_protocol_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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+testEmptyProtocol() {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      WebSocketTransformer.upgrade(request).then((websocket) {
+        websocket.close();
+      });
+    });
+    WebSocket.connect("ws://127.0.0.1:${server.port}/", protocols: [])
+        .then((client) {
+      Expect.isNull(client.protocol);
+      client.close();
+      server.close();
+    });
+  });
+}
+
+testProtocol(List<String> protocols, String used) {
+  selector(List<String> receivedProtocols) {
+    Expect.listEquals(protocols, receivedProtocols);
+    return used;
+  }
+
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      WebSocketTransformer.upgrade(request, protocolSelector: selector)
+          .then((websocket) {
+        Expect.equals(used, websocket.protocol);
+        websocket.close();
+      });
+    });
+    WebSocket.connect("ws://127.0.0.1:${server.port}/", protocols: protocols)
+        .then((client) {
+      Expect.equals(used, client.protocol);
+      client.close();
+      server.close();
+    });
+  });
+}
+
+testProtocolHandler() {
+  // Test throwing an error.
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      selector(List<String> receivedProtocols) {
+        throw "error";
+      }
+
+      WebSocketTransformer.upgrade(request, protocolSelector: selector).then(
+          (websocket) {
+        Expect.fail('error expected');
+      }, onError: (error) {
+        Expect.equals('error', error);
+      });
+    });
+    WebSocket.connect("ws://127.0.0.1:${server.port}/",
+        protocols: ["v1.example.com"]).then((client) {
+      Expect.fail('error expected');
+    }, onError: (error) {
+      server.close();
+    });
+  });
+
+  // Test returning another protocol.
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    server.listen((request) {
+      selector(List<String> receivedProtocols) => "v2.example.com";
+      WebSocketTransformer.upgrade(request, protocolSelector: selector).then(
+          (websocket) {
+        Expect.fail('error expected');
+      }, onError: (error) {
+        Expect.isTrue(error is WebSocketException);
+      });
+    });
+    WebSocket.connect("ws://127.0.0.1:${server.port}/",
+        protocols: ["v1.example.com"]).then((client) {
+      Expect.fail('error expected');
+    }, onError: (error) {
+      server.close();
+    });
+  });
+}
+
+void main() {
+  testEmptyProtocol();
+  testProtocol(["v1.example.com", "v2.example.com"], "v1.example.com");
+  testProtocol(["v1.example.com", "v2.example.com"], "v2.example.com");
+  testProtocolHandler();
+}
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
new file mode 100644
index 0000000..45b94e8
--- /dev/null
+++ b/tests/standalone/io/web_socket_test.dart
@@ -0,0 +1,592 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+import "dart:typed_data";
+
+import "package:async_helper/async_helper.dart";
+import "package:convert/convert.dart";
+import "package:crypto/crypto.dart";
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+
+const WEB_SOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+const String HOST_NAME = 'localhost';
+
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+/**
+ * A SecurityConfiguration lets us run the tests over HTTP or HTTPS.
+ */
+class SecurityConfiguration {
+  final bool secure;
+
+  SecurityConfiguration({required this.secure});
+
+  Future<HttpServer> createServer({int backlog: 0}) => secure
+      ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
+      : HttpServer.bind(HOST_NAME, 0, backlog: backlog);
+
+  Future<WebSocket> createClient(int port) =>
+      // TODO(whesse): Add client context argument to WebSocket.connect
+      WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
+
+  checkCloseStatus(webSocket, closeStatus, closeReason) {
+    Expect.equals(
+        closeStatus == null ? WebSocketStatus.noStatusReceived : closeStatus,
+        webSocket.closeCode);
+    Expect.equals(
+        closeReason == null ? "" : closeReason, webSocket.closeReason);
+  }
+
+  void testRequestResponseClientCloses(int totalConnections, int? closeStatus,
+      String? closeReason, int numberOfMessages) {
+    assert(numberOfMessages >= 1);
+
+    asyncStart();
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        asyncStart();
+        webSocket.listen(webSocket.add, onDone: () {
+          checkCloseStatus(webSocket, closeStatus, closeReason);
+          asyncEnd();
+        });
+      }, onDone: () {
+        asyncEnd();
+      });
+
+      int closeCount = 0;
+      String messageText = "Hello, world!";
+      for (int i = 0; i < totalConnections; i++) {
+        asyncStart();
+        createClient(server.port).then((webSocket) {
+          webSocket.add(messageText);
+          webSocket.listen((message) {
+            numberOfMessages--;
+            Expect.equals(messageText, message);
+
+            if (numberOfMessages > 0) {
+              webSocket.add(message);
+            } else {
+              webSocket.close(closeStatus, closeReason);
+            }
+          }, onDone: () {
+            checkCloseStatus(webSocket, closeStatus, closeReason);
+            closeCount++;
+            if (closeCount == totalConnections) {
+              server.close();
+            }
+            asyncEnd();
+          });
+        });
+      }
+    });
+  }
+
+  void testRequestResponseServerCloses(
+      int totalConnections, int? closeStatus, String? closeReason) {
+    createServer().then((server) {
+      int closeCount = 0;
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        String messageText = "Hello, world!";
+        int messageCount = 0;
+        webSocket.listen((message) {
+          messageCount++;
+          if (messageCount < 10) {
+            Expect.equals(messageText, message);
+            webSocket.add(message);
+          } else {
+            webSocket.close(closeStatus, closeReason);
+          }
+        }, onDone: () {
+          checkCloseStatus(webSocket, closeStatus, closeReason);
+          closeCount++;
+          if (closeCount == totalConnections) {
+            server.close();
+          }
+        });
+        webSocket.add(messageText);
+      });
+
+      for (int i = 0; i < totalConnections; i++) {
+        createClient(server.port).then((webSocket) {
+          webSocket.listen(webSocket.add, onDone: () {
+            checkCloseStatus(webSocket, closeStatus, closeReason);
+          });
+        });
+      }
+    });
+  }
+
+  void testMessageLength(int messageLength) {
+    createServer().then((server) {
+      Uint8List originalMessage = new Uint8List(messageLength);
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        webSocket.listen((message) {
+          Expect.listEquals(originalMessage, message);
+          webSocket.add(message);
+        });
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.listen((message) {
+          Expect.listEquals(originalMessage, message);
+          webSocket.close();
+        }, onDone: server.close);
+        webSocket.add(originalMessage);
+      });
+    });
+  }
+
+  void testCloseNoListen() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.close();
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.close();
+      });
+    });
+  }
+
+  void testCancelThenClose() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        webSocket.listen(null).cancel();
+        webSocket.close();
+        server.close();
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.close();
+      });
+    });
+  }
+
+  void testCloseThenCancel() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        var subscription = webSocket.listen(null);
+        webSocket.close();
+        subscription.cancel();
+        server.close();
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.close();
+      });
+    });
+  }
+
+  void testListenAfterClose() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.close();
+        Expect.throws(() => webSocket.drain());
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.close();
+        Expect.throws(() => webSocket.drain());
+      });
+    });
+  }
+
+  void testDoubleCloseClient() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.listen((_) {}, onDone: webSocket.close);
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.listen((_) {}, onDone: webSocket.close);
+        webSocket.close();
+      });
+    });
+  }
+
+  void testDoubleCloseServer() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.listen((_) {}, onDone: webSocket.close);
+        webSocket.close();
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.listen((_) {}, onDone: webSocket.close);
+      });
+    });
+  }
+
+  void testImmediateCloseServer() {
+    createServer().then((server) {
+      server.listen((request) {
+        WebSocketTransformer.upgrade(request).then((webSocket) {
+          webSocket.listen((_) {
+            Expect.fail("Unexpected message");
+          }, onDone: server.close);
+          webSocket.close();
+        });
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.listen((_) {
+          Expect.fail("Unexpected message");
+        }, onDone: webSocket.close);
+      });
+    });
+  }
+
+  void testImmediateCloseClient() {
+    createServer().then((server) {
+      server.listen((request) {
+        WebSocketTransformer.upgrade(request).then((webSocket) {
+          webSocket.listen((_) {
+            Expect.fail("Unexpected message");
+          }, onDone: () {
+            server.close();
+            webSocket.close();
+          });
+        });
+      });
+
+      createClient(server.port).then((webSocket) {
+        webSocket.listen((_) {
+          Expect.fail("Unexpected message");
+        }, onDone: webSocket.close);
+        webSocket.close();
+      });
+    });
+  }
+
+  void testNoUpgrade() {
+    createServer().then((server) {
+      // Create a server which always responds with notFound.
+      server.listen((request) {
+        request.response.statusCode = HttpStatus.notFound;
+        request.response.close();
+      });
+
+      createClient(server.port).catchError((error) {
+        server.close();
+      });
+    });
+  }
+
+  void testUsePOST() {
+    asyncStart();
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        Expect.fail("No connection expected");
+      }, onError: (e) {
+        asyncEnd();
+      });
+
+      HttpClient client = new HttpClient();
+      client
+          .postUrl(Uri.parse(
+              "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/"))
+          .then((request) => request.close())
+          .then((response) {
+        Expect.equals(HttpStatus.badRequest, response.statusCode);
+        client.close();
+        server.close();
+      });
+    });
+  }
+
+  void testConnections(
+      int totalConnections, int closeStatus, String closeReason) {
+    createServer().then((server) {
+      int closeCount = 0;
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        String messageText = "Hello, world!";
+        int messageCount = 0;
+        webSocket.listen((message) {
+          messageCount++;
+          if (messageCount < 10) {
+            Expect.equals(messageText, message);
+            webSocket.add(message);
+          } else {
+            webSocket.close(closeStatus, closeReason);
+          }
+        }, onDone: () {
+          checkCloseStatus(webSocket, closeStatus, closeReason);
+          closeCount++;
+          if (closeCount == totalConnections) {
+            server.close();
+          }
+        });
+        webSocket.add(messageText);
+      });
+
+      void webSocketConnection() {
+        bool onopenCalled = false;
+        int onmessageCalled = 0;
+        bool oncloseCalled = false;
+
+        createClient(server.port).then((webSocket) {
+          Expect.isFalse(onopenCalled);
+          Expect.equals(0, onmessageCalled);
+          Expect.isFalse(oncloseCalled);
+          onopenCalled = true;
+          Expect.equals(WebSocket.open, webSocket.readyState);
+          webSocket.listen((message) {
+            onmessageCalled++;
+            Expect.isTrue(onopenCalled);
+            Expect.isFalse(oncloseCalled);
+            Expect.equals(WebSocket.open, webSocket.readyState);
+            webSocket.add(message);
+          }, onDone: () {
+            Expect.isTrue(onopenCalled);
+            Expect.equals(10, onmessageCalled);
+            Expect.isFalse(oncloseCalled);
+            oncloseCalled = true;
+            Expect.equals(3002, webSocket.closeCode);
+            Expect.equals("Got tired", webSocket.closeReason);
+            Expect.equals(WebSocket.closed, webSocket.readyState);
+          });
+        });
+      }
+
+      for (int i = 0; i < totalConnections; i++) {
+        webSocketConnection();
+      }
+    });
+  }
+
+  testIndividualUpgrade(int connections) {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        if (WebSocketTransformer.isUpgradeRequest(request)) {
+          WebSocketTransformer.upgrade(request).then((webSocket) {
+            webSocket.listen((_) {
+              webSocket.close();
+            });
+            webSocket.add("Hello");
+          });
+        } else {
+          Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request));
+          request.response.statusCode = HttpStatus.ok;
+          request.response.close();
+        }
+      });
+
+      var futures = <Future>[];
+
+      var wsProtocol = '${secure ? "wss" : "ws"}';
+      var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/';
+      var httpProtocol = '${secure ? "https" : "http"}';
+      var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/';
+      HttpClient client = new HttpClient();
+
+      for (int i = 0; i < connections; i++) {
+        var completer = new Completer();
+        futures.add(completer.future);
+        WebSocket.connect('${baseWsUrl}').then((websocket) {
+          websocket.listen((_) {
+            websocket.close();
+          }, onDone: completer.complete);
+        });
+
+        futures.add(client
+            .openUrl("GET", Uri.parse('${baseHttpUrl}'))
+            .then((request) => request.close())
+            .then((response) {
+          response.listen((_) {});
+          Expect.equals(HttpStatus.ok, response.statusCode);
+        }));
+      }
+
+      Future.wait(futures).then((_) {
+        server.close();
+        client.close();
+        asyncEnd();
+      });
+    });
+  }
+
+  testFromUpgradedSocket() {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.equals(
+            'Upgrade', request.headers.value(HttpHeaders.connectionHeader));
+        Expect.equals(
+            'websocket', request.headers.value(HttpHeaders.upgradeHeader));
+
+        var key = request.headers.value('Sec-WebSocket-Key');
+        var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
+        var accept = base64.encode(digest.bytes);
+        request.response
+          ..statusCode = HttpStatus.switchingProtocols
+          ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
+          ..headers.add(HttpHeaders.upgradeHeader, "websocket")
+          ..headers.add("Sec-WebSocket-Accept", accept);
+        request.response.contentLength = 0;
+        request.response.detachSocket().then((socket) {
+          return new WebSocket.fromUpgradedSocket(socket, serverSide: true);
+        }).then((websocket) {
+          websocket.add("Hello");
+          websocket.close();
+          asyncEnd();
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+
+      WebSocket.connect(url).then((websocket) {
+        return websocket.listen((message) {
+          Expect.equals("Hello", message);
+          websocket.close();
+        }).asFuture();
+      }).then((_) => server.close());
+    });
+  }
+
+  void testAdditionalHeaders() {
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        Expect.equals('my-value', request.headers['My-Header']![0]);
+        var header = request.headers['My-Header-Multiple']!;
+        Expect.equals(1, header.length);
+        Expect.equals('my-value-1, my-value-2', header[0]);
+        WebSocketTransformer.upgrade(request).then((webSocket) {
+          webSocket.listen((_) {
+            webSocket.close();
+          });
+          webSocket.add("Hello");
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+      var headers = {
+        'My-Header': 'my-value',
+        'My-Header-Multiple': ['my-value-1', 'my-value-2']
+      };
+      WebSocket.connect(url, headers: headers).then((websocket) {
+        return websocket.listen((message) {
+          Expect.equals("Hello", message);
+          websocket.close();
+        }).asFuture();
+      }).then((_) {
+        server.close();
+        asyncEnd();
+      });
+    });
+  }
+
+  void testBasicAuthentication() {
+    var userInfo = 'user:password';
+
+    asyncStart();
+    asyncStart();
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        String auth = base64.encode(utf8.encode(userInfo));
+        Expect.equals('Basic $auth', request.headers['Authorization']![0]);
+        Expect.equals(1, request.headers['Authorization']!.length);
+        WebSocketTransformer.upgrade(request).then((webSocket) {
+          webSocket.listen((_) {
+            throw 'Unexpected';
+          }, onDone: () {
+            asyncEnd();
+          });
+          webSocket.add("Hello");
+        });
+      });
+
+      var url =
+          '${secure ? "wss" : "ws"}://$userInfo@$HOST_NAME:${server.port}/';
+      WebSocket.connect(url).then((websocket) {
+        return websocket.listen((message) {
+          Expect.equals("Hello", message);
+          websocket.close();
+        }).asFuture();
+      }).then((_) {
+        return server.close();
+      }).whenComplete(() {
+        asyncEnd();
+      });
+    });
+  }
+
+  void testShouldSetUserAgent() {
+    asyncStart();
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        Expect.equals('Custom User Agent', WebSocket.userAgent);
+        server.close();
+        webSocket.close();
+        asyncEnd();
+      });
+
+      WebSocket.userAgent = 'Custom User Agent';
+      createClient(server.port).then((webSocket) {
+        webSocket.close();
+      });
+    });
+  }
+
+  void runTests() {
+    testRequestResponseClientCloses(2, null, null, 1);
+    testRequestResponseClientCloses(2, 3001, null, 2);
+    testRequestResponseClientCloses(2, 3002, "Got tired", 3);
+    testRequestResponseServerCloses(2, null, null);
+    testRequestResponseServerCloses(2, 3001, null);
+    testRequestResponseServerCloses(2, 3002, "Got tired");
+    testMessageLength(125);
+    testMessageLength(126);
+    testMessageLength(127);
+    testMessageLength(65535);
+    testMessageLength(65536);
+    testCloseNoListen();
+    testCancelThenClose();
+    testCloseThenCancel();
+    testListenAfterClose();
+    testDoubleCloseClient();
+    testDoubleCloseServer();
+    testImmediateCloseServer();
+    testImmediateCloseClient();
+    testNoUpgrade();
+    testUsePOST();
+    testConnections(10, 3002, "Got tired");
+    testIndividualUpgrade(5);
+    testFromUpgradedSocket();
+    testAdditionalHeaders();
+    testBasicAuthentication();
+    testShouldSetUserAgent();
+  }
+}
+
+main() {
+  new SecurityConfiguration(secure: false).runTests();
+  // TODO(whesse): Make WebSocket.connect() take an optional context: parameter.
+  // new SecurityConfiguration(secure: true).runTests();
+}
diff --git a/tests/standalone/io/web_socket_typed_data_test.dart b/tests/standalone/io/web_socket_typed_data_test.dart
new file mode 100644
index 0000000..595ca60
--- /dev/null
+++ b/tests/standalone/io/web_socket_typed_data_test.dart
@@ -0,0 +1,223 @@
+// 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=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+import "dart:typed_data";
+
+Future<HttpServer> createServer() => HttpServer.bind("127.0.0.1", 0);
+
+Future<WebSocket> createClient(int port, bool compression) => compression
+    ? WebSocket.connect('ws://127.0.0.1:$port/')
+    : WebSocket.connect('ws://127.0.0.1:$port/',
+        compression: CompressionOptions.compressionOff);
+
+void test(expected, testData, compression) {
+  createServer().then((server) {
+    var messageCount = 0;
+    var transformer = compression
+        ? new WebSocketTransformer()
+        : new WebSocketTransformer(
+            compression: CompressionOptions.compressionOff);
+    server.transform(transformer).listen((webSocket) {
+      webSocket.listen((message) {
+        Expect.listEquals(expected, message);
+        webSocket.add(testData[messageCount]);
+        messageCount++;
+      }, onDone: () => Expect.equals(testData.length, messageCount));
+    });
+
+    createClient(server.port, compression).then((webSocket) {
+      var messageCount = 0;
+      webSocket.listen((message) {
+        Expect.listEquals(expected, message);
+        messageCount++;
+        if (messageCount == testData.length) webSocket.close();
+      }, onDone: server.close);
+      testData.forEach(webSocket.add);
+    });
+  });
+}
+
+testUintLists({bool compression: false}) {
+  var fillData = new List.generate(256, (index) => index);
+  var testData = [
+    new Uint8List(256),
+    new Uint8ClampedList(256),
+    new Uint16List(256),
+    new Uint32List(256),
+    new Uint64List(256),
+  ];
+  testData.forEach((list) => list.setAll(0, fillData));
+  test(fillData, testData, compression);
+}
+
+testIntLists({bool compression: false}) {
+  var fillData = new List.generate(128, (index) => index);
+  var testData = [
+    new Int8List(128),
+    new Int16List(128),
+    new Int32List(128),
+    new Int64List(128),
+  ];
+  testData.forEach((list) => list.setAll(0, fillData));
+  test(fillData, testData, compression);
+}
+
+void testOutOfRangeClient({bool compression: false}) {
+  createServer().then((server) {
+    var messageCount = 0;
+    var transformer = compression
+        ? new WebSocketTransformer()
+        : new WebSocketTransformer(
+            compression: CompressionOptions.compressionOff);
+    server.transform(transformer).listen((webSocket) {
+      webSocket.listen((message) => Expect.fail("No message expected"));
+    });
+
+    Future clientError(data) {
+      return createClient(server.port, compression).then((webSocket) {
+        var messageCount = 0;
+        webSocket.listen((message) => Expect.fail("No message expected"));
+        webSocket.add(data);
+        webSocket.close();
+        return webSocket.done;
+      });
+    }
+
+    Future expectError(data) {
+      var completer = new Completer();
+      clientError(data)
+          .then((_) => completer.completeError("Message $data did not fail"))
+          .catchError((e) => completer.complete(true));
+      return completer.future;
+    }
+
+    var futures = <Future>[];
+    var data;
+    data = new Uint16List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data = new Uint32List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data = new Uint64List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data = new Int16List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data[0] = -1;
+    futures.add(expectError(data));
+    data = new Int32List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data[0] = -1;
+    futures.add(expectError(data));
+    data = new Int64List(1);
+    data[0] = 256;
+    futures.add(expectError(data));
+    data[0] = -1;
+    futures.add(expectError(data));
+    futures.add(expectError([-1]));
+    futures.add(expectError([256]));
+
+    Future.wait(futures).then((_) => server.close());
+  });
+}
+
+void testOutOfRangeServer({bool compression: false}) {
+  var futures = <Future>[];
+  var testData = [];
+  var data;
+  data = new Uint16List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Uint32List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Uint64List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Int16List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Int16List(1);
+  data[0] = -1;
+  testData.add(data);
+  data = new Int32List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Int32List(1);
+  data[0] = -1;
+  testData.add(data);
+  data = new Int64List(1);
+  data[0] = 256;
+  testData.add(data);
+  data = new Int64List(1);
+  data[0] = -1;
+  testData.add(data);
+  testData.add([-1]);
+  testData.add([256]);
+
+  var allDone = new Completer();
+
+  Future expectError(future) {
+    var completer = new Completer();
+    future
+        .then((_) => completer.completeError("Message $data did not fail"))
+        .catchError((e) => completer.complete(true));
+    return completer.future;
+  }
+
+  createServer().then((server) {
+    var messageCount = 0;
+    var transformer = compression
+        ? new WebSocketTransformer()
+        : new WebSocketTransformer(
+            compression: CompressionOptions.compressionOff);
+    server.transform(transformer).listen((webSocket) {
+      webSocket.listen((message) {
+        messageCount++;
+        webSocket.add(testData[message[0]]);
+        webSocket.close();
+        futures.add(expectError(webSocket.done));
+        if (messageCount == testData.length) allDone.complete(true);
+      });
+    });
+
+    Future x(int i) {
+      var completer = new Completer();
+      createClient(server.port, compression).then((webSocket) {
+        webSocket.listen((message) => Expect.fail("No message expected"),
+            onDone: () => completer.complete(true),
+            onError: (e) => completer.completeError(e));
+        webSocket.add(new List()..add(i));
+      });
+      return completer.future;
+    }
+
+    for (int i = 0; i < testData.length; i++) futures.add(x(i));
+    allDone.future
+        .then((_) => Future.wait(futures).then((_) => server.close()));
+  });
+}
+
+main() {
+  testUintLists();
+  testUintLists(compression: true);
+  testIntLists();
+  testIntLists(compression: true);
+  testOutOfRangeClient();
+  testOutOfRangeClient(compression: true);
+  // testOutOfRangeServer();
+  // testOutOfRangeServer(compression: true);
+}
diff --git a/tests/standalone/io/windows_environment_script.dart b/tests/standalone/io/windows_environment_script.dart
new file mode 100644
index 0000000..509ed5b
--- /dev/null
+++ b/tests/standalone/io/windows_environment_script.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:io";
+
+main() {
+  var scriptDir = Platform.environment['SCRIPTDIR']!;
+  if (!scriptDir.contains('å')) throw "scriptDir not containing character å";
+  scriptDir = Platform.environment['ScriptDir'];
+  if (!scriptDir.contains('å')) throw "scriptDir not containing character å";
+  var str = new File('$scriptDir/funky.bat').readAsStringSync();
+  if (!str.contains('%~dp0')) throw "str not containing dp0";
+}
diff --git a/tests/standalone/io/windows_environment_test.dart b/tests/standalone/io/windows_environment_test.dart
new file mode 100644
index 0000000..d2698c2
--- /dev/null
+++ b/tests/standalone/io/windows_environment_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:path/path.dart';
+import 'package:expect/expect.dart';
+import "dart:io";
+
+main() {
+  if (Platform.operatingSystem != 'windows') return;
+  var tempDir = Directory.systemTemp.createTempSync('dart_windows_environment');
+  var funkyDir = new Directory(join(tempDir.path, 'å'));
+  funkyDir.createSync();
+  var funkyFile = new File(join(funkyDir.path, 'funky.bat'));
+  funkyFile.writeAsStringSync("""
+@echo off
+set SCRIPTDIR=%~dp0
+%1 %2
+      """);
+  var dart = Platform.executable;
+  var script =
+      Platform.script.resolve('windows_environment_script.dart').toFilePath();
+  Process.run('cmd', ['/c', funkyFile.path, dart, script]).then((p) {
+    if (0 != p.exitCode) throw "Exit code not 0";
+    tempDir.deleteSync(recursive: true);
+  });
+}
diff --git a/tests/standalone/io/windows_file_system_async_links_test.dart b/tests/standalone/io/windows_file_system_async_links_test.dart
new file mode 100644
index 0000000..207d9a5
--- /dev/null
+++ b/tests/standalone/io/windows_file_system_async_links_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.
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class FutureExpect {
+  static Future isTrue(Future<bool> result) =>
+      result.then((value) => Expect.isTrue(value));
+  static Future isFalse(Future<bool> result) =>
+      result.then((value) => Expect.isFalse(value));
+  static Future equals(expected, Future result) =>
+      result.then((value) => Expect.equals(expected, value));
+  static Future listEquals(expected, Future result) =>
+      result.then((value) => Expect.listEquals(expected, value));
+  static Future throws(Future result) => result.then((value) {
+        throw new ExpectException(
+            "FutureExpect.throws received $value instead of an exception");
+      }, onError: (_) => null);
+}
+
+Future testJunctionTypeDelete() {
+  return Directory.systemTemp
+      .createTemp('dart_windows_file_system_async_links')
+      .then((temp) {
+    var x = '${temp.path}${Platform.pathSeparator}x';
+    var y = '${temp.path}${Platform.pathSeparator}y';
+    return new Directory(x)
+        .create()
+        .then((_) => new Link(y).create(x))
+        .then((_) => FutureExpect.isTrue(new Directory(y).exists()))
+        .then((_) => FutureExpect.isTrue(new Directory(x).exists()))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isDirectory(y)))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isDirectory(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.directory, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+
+        // Test Junction pointing to a missing directory.
+        .then((_) => new Directory(x).delete())
+        .then((_) => FutureExpect.isTrue(new Link(y).exists()))
+        .then((_) => FutureExpect.isFalse(new Directory(x).exists()))
+        .then((_) => FutureExpect.isTrue(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(x)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isDirectory(y)))
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isDirectory(x)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.link, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.notFound,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+
+        // Delete Junction pointing to a missing directory.
+        .then((_) => new Link(y).delete())
+        .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(y)))
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.throws(new Link(y).target()))
+        .then((_) => new Directory(x).create())
+        .then((_) => new Link(y).create(x))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.link,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.directory,
+            FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.equals(x, new Link(y).target()))
+
+        // Delete Junction pointing to an existing directory.
+        .then((_) => new Directory(y).delete())
+        .then((_) => FutureExpect.equals(
+            FileSystemEntityType.notFound, FileSystemEntity.type(y)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.notFound,
+            FileSystemEntity.type(y, followLinks: false)))
+        .then((_) =>
+            FutureExpect.equals(FileSystemEntityType.directory, FileSystemEntity.type(x)))
+        .then((_) => FutureExpect.equals(FileSystemEntityType.directory, FileSystemEntity.type(x, followLinks: false)))
+        .then((_) => FutureExpect.throws(new Link(y).target()))
+        .then((_) => temp.delete(recursive: true));
+  });
+}
+
+main() {
+  // Links on other platforms are tested by file_system_[async_]links_test.
+  if (Platform.operatingSystem == 'windows') {
+    asyncStart();
+    testJunctionTypeDelete().then((_) => asyncEnd());
+  }
+}
diff --git a/tests/standalone/io/windows_file_system_links_test.dart b/tests/standalone/io/windows_file_system_links_test.dart
new file mode 100644
index 0000000..ccf38e5
--- /dev/null
+++ b/tests/standalone/io/windows_file_system_links_test.dart
@@ -0,0 +1,83 @@
+// 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 "dart:io";
+import "dart:isolate";
+
+testJunctionTypeDelete() {
+  var temp =
+      Directory.systemTemp.createTempSync('dart_windows_file_system_links');
+  var x = '${temp.path}${Platform.pathSeparator}x';
+  var y = '${temp.path}${Platform.pathSeparator}y';
+
+  new Directory(x).createSync();
+  new Link(y).create(x).then((_) {
+    Expect.isTrue(new Directory(y).existsSync());
+    Expect.isTrue(new Directory(x).existsSync());
+    Expect.isTrue(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(y));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(x));
+    Expect.equals(FileSystemEntityType.directory, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.directory, FileSystemEntity.typeSync(x));
+    Expect.equals(FileSystemEntityType.link,
+        FileSystemEntity.typeSync(y, followLinks: false));
+    Expect.equals(FileSystemEntityType.directory,
+        FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
+    // Test Junction pointing to a missing directory.
+    new Directory(x).deleteSync();
+    Expect.isTrue(new Link(y).existsSync());
+    Expect.isFalse(new Directory(x).existsSync());
+    Expect.isTrue(FileSystemEntity.isLinkSync(y));
+    Expect.isFalse(FileSystemEntity.isLinkSync(x));
+    Expect.isFalse(FileSystemEntity.isDirectorySync(y));
+    Expect.isFalse(FileSystemEntity.isDirectorySync(x));
+    Expect.equals(FileSystemEntityType.link, FileSystemEntity.typeSync(y));
+    Expect.equals(FileSystemEntityType.notFound, FileSystemEntity.typeSync(x));
+    Expect.equals(FileSystemEntityType.link,
+        FileSystemEntity.typeSync(y, followLinks: false));
+    Expect.equals(FileSystemEntityType.notFound,
+        FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
+    // Delete Junction pointing to a missing directory.
+    new Link(y).deleteSync();
+    Expect.isFalse(FileSystemEntity.isLinkSync(y));
+    Expect.equals(FileSystemEntityType.notFound, FileSystemEntity.typeSync(y));
+    Expect.throws(() => new Link(y).targetSync());
+
+    new Directory(x).createSync();
+    new Link(y).create(x).then((_) {
+      Expect.equals(FileSystemEntityType.link,
+          FileSystemEntity.typeSync(y, followLinks: false));
+      Expect.equals(FileSystemEntityType.directory,
+          FileSystemEntity.typeSync(x, followLinks: false));
+      Expect.equals(x, new Link(y).targetSync());
+
+      // Delete Junction pointing to an existing directory.
+      new Directory(y).deleteSync();
+      Expect.equals(
+          FileSystemEntityType.notFound, FileSystemEntity.typeSync(y));
+      Expect.equals(FileSystemEntityType.notFound,
+          FileSystemEntity.typeSync(y, followLinks: false));
+      Expect.equals(
+          FileSystemEntityType.directory, FileSystemEntity.typeSync(x));
+      Expect.equals(FileSystemEntityType.directory,
+          FileSystemEntity.typeSync(x, followLinks: false));
+      Expect.throws(() => new Link(y).targetSync());
+
+      temp.deleteSync(recursive: true);
+    });
+  });
+}
+
+main() {
+  // Links on other platforms are tested by file_system_[async_]links_test.
+  if (Platform.operatingSystem == 'windows') {
+    testJunctionTypeDelete();
+  }
+}
diff --git a/tests/standalone/io/zlib_test.dart b/tests/standalone/io/zlib_test.dart
new file mode 100644
index 0000000..8af461d
--- /dev/null
+++ b/tests/standalone/io/zlib_test.dart
@@ -0,0 +1,291 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void testZLibDeflateEmpty() {
+  asyncStart();
+  var controller = new StreamController(sync: true);
+  controller.stream
+      .transform(new ZLibEncoder(gzip: false, level: 6))
+      .fold<List<int>>([], (buffer, data) {
+    buffer.addAll(data);
+    return buffer;
+  }).then((data) {
+    Expect.listEquals([120, 156, 3, 0, 0, 0, 0, 1], data);
+    asyncEnd();
+  });
+  controller.close();
+}
+
+void testZLibDeflateEmptyGzip() {
+  asyncStart();
+  var controller = new StreamController(sync: true);
+  controller.stream
+      .transform(new ZLibEncoder(gzip: true, level: 6))
+      .fold<List<int>>(<int>[], (buffer, data) {
+    buffer.addAll(data);
+    return buffer;
+  }).then((data) {
+    Expect.isTrue(data.length > 0);
+    Expect.listEquals([], new ZLibDecoder().convert(data));
+    asyncEnd();
+  });
+  controller.close();
+}
+
+void testZLibDeflate(List<int> data) {
+  asyncStart();
+  var controller = new StreamController(sync: true);
+  controller.stream
+      .transform(new ZLibEncoder(gzip: false, level: 6))
+      .fold<List<int>>([], (buffer, data) {
+    buffer.addAll(data);
+    return buffer;
+  }).then((data) {
+    Expect.listEquals([
+      120,
+      156,
+      99,
+      96,
+      100,
+      98,
+      102,
+      97,
+      101,
+      99,
+      231,
+      224,
+      4,
+      0,
+      0,
+      175,
+      0,
+      46
+    ], data);
+    asyncEnd();
+  });
+  controller.add(data);
+  controller.close();
+}
+
+void testZLibDeflateGZip(List<int> data) {
+  asyncStart();
+  var controller = new StreamController(sync: true);
+  controller.stream.transform(new ZLibEncoder(gzip: true)).fold<List<int>>([],
+      (buffer, data) {
+    buffer.addAll(data);
+    return buffer;
+  }).then((data) {
+    Expect.equals(30, data.length);
+    Expect.listEquals(
+        [
+          99,
+          96,
+          100,
+          98,
+          102,
+          97,
+          101,
+          99,
+          231,
+          224,
+          4,
+          0,
+          70,
+          215,
+          108,
+          69,
+          10,
+          0,
+          0,
+          0
+        ],
+        // Skip header, as it can change.
+        data.sublist(10));
+    asyncEnd();
+  });
+  controller.add(data);
+  controller.close();
+}
+
+void testZLibDeflateRaw(List<int> data) {
+  asyncStart();
+  var controller = new StreamController(sync: true);
+  controller.stream
+      .transform(new ZLibEncoder(raw: true, level: 6))
+      .fold<List<int>>([], (buffer, data) {
+    buffer.addAll(data);
+    return buffer;
+  }).then((data) {
+    Expect.listEquals(
+        [99, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0], data);
+    asyncEnd();
+  });
+  controller.add(data);
+  controller.close();
+}
+
+void testZLibDeflateInvalidLevel() {
+  test2(gzip, level) {
+    [true, false].forEach((gzip) {
+      [-2, -20, 10, 42].forEach((level) {
+        Expect.throwsArgumentError(
+            () => new ZLibEncoder(gzip: gzip, level: level),
+            "'level' must be in range -1..9");
+      });
+    });
+  }
+}
+
+void testZLibInflate(List<int> data) {
+  [true, false].forEach((gzip) {
+    [
+      ZLibOption.strategyFiltered,
+      ZLibOption.strategyHuffmanOnly,
+      ZLibOption.strategyRle,
+      ZLibOption.strategyFixed,
+      ZLibOption.strategyDefault,
+    ].forEach((strategy) {
+      [3, 6, 9].forEach((level) {
+        asyncStart();
+        var controller = new StreamController(sync: true);
+        controller.stream
+            .transform(
+                new ZLibEncoder(gzip: gzip, level: level, strategy: strategy))
+            .transform(new ZLibDecoder())
+            .fold<List<int>>([], (buffer, data) {
+          buffer.addAll(data);
+          return buffer;
+        }).then((inflated) {
+          Expect.listEquals(data, inflated);
+          asyncEnd();
+        });
+        controller.add(data);
+        controller.close();
+      });
+    });
+  });
+}
+
+void testZLibInflateRaw(List<int> data) {
+  [3, 6, 9].forEach((level) {
+    asyncStart();
+    var controller = new StreamController(sync: true);
+    controller.stream
+        .transform(new ZLibEncoder(raw: true, level: level))
+        .transform(new ZLibDecoder(raw: true))
+        .fold<List<int>>([], (buffer, data) {
+      buffer.addAll(data);
+      return buffer;
+    }).then((inflated) {
+      Expect.listEquals(data, inflated);
+      asyncEnd();
+    });
+    controller.add(data);
+    controller.close();
+  });
+}
+
+void testZLibInflateSync(List<int> data) {
+  [true, false].forEach((gzip) {
+    [3, 6, 9].forEach((level) {
+      var encoded = new ZLibEncoder(gzip: gzip, level: level).convert(data);
+      var decoded = new ZLibDecoder().convert(encoded);
+      Expect.listEquals(data, decoded);
+    });
+  });
+}
+
+void testZlibInflateThrowsWithSmallerWindow() {
+  var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+  var encoder = new ZLibEncoder(windowBits: 10);
+  var encodedData = encoder.convert(data);
+  var decoder = new ZLibDecoder(windowBits: 8);
+  Expect.throws(() => decoder.convert(encodedData));
+}
+
+void testZlibInflateWithLargerWindow() {
+  var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+  [true, false].forEach((gzip) {
+    [3, 6, 9].forEach((level) {
+      asyncStart();
+      var controller = new StreamController(sync: true);
+      controller.stream
+          .transform(new ZLibEncoder(gzip: gzip, level: level, windowBits: 8))
+          .transform(new ZLibDecoder(windowBits: 10))
+          .fold<List<int>>([], (buffer, data) {
+        buffer.addAll(data);
+        return buffer;
+      }).then((inflated) {
+        Expect.listEquals(data, inflated);
+        asyncEnd();
+      });
+      controller.add(data);
+      controller.close();
+    });
+  });
+}
+
+void testZlibWithDictionary() {
+  var dict = [102, 111, 111, 98, 97, 114];
+  var data = [98, 97, 114, 102, 111, 111];
+
+  [3, 6, 9].forEach((level) {
+    var encoded = new ZLibEncoder(level: level, dictionary: dict).convert(data);
+    var decoded = new ZLibDecoder(dictionary: dict).convert(encoded);
+    Expect.listEquals(data, decoded);
+  });
+}
+
+var generateListTypes = [
+  (list) => list,
+  (list) => new Uint8List.fromList(list),
+  (list) => new Int8List.fromList(list),
+  (list) => new Uint16List.fromList(list),
+  (list) => new Int16List.fromList(list),
+  (list) => new Uint32List.fromList(list),
+  (list) => new Int32List.fromList(list),
+];
+
+var generateViewTypes = [
+  (list) => new Uint8List.view((new Uint8List.fromList(list)).buffer, 1, 8),
+  (list) => new Int8List.view((new Int8List.fromList(list)).buffer, 1, 8),
+  (list) => new Uint16List.view((new Uint16List.fromList(list)).buffer, 2, 6),
+  (list) => new Int16List.view((new Int16List.fromList(list)).buffer, 2, 6),
+  (list) => new Uint32List.view((new Uint32List.fromList(list)).buffer, 4, 4),
+  (list) => new Int32List.view((new Int32List.fromList(list)).buffer, 4, 4),
+];
+
+void main() {
+  asyncStart();
+  testZLibDeflateEmpty();
+  testZLibDeflateEmptyGzip();
+  testZLibDeflateInvalidLevel();
+  generateListTypes.forEach((f) {
+    var data = f([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+    testZLibDeflate(data);
+    testZLibDeflateGZip(data);
+    testZLibDeflateRaw(data);
+    testZLibInflate(data);
+    testZLibInflateSync(data);
+    testZLibInflateRaw(data);
+  });
+  generateViewTypes.forEach((f) {
+    var data = f([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+    testZLibInflate(data);
+    testZLibInflateSync(data);
+    testZLibInflateRaw(data);
+  });
+  testZlibInflateThrowsWithSmallerWindow();
+  testZlibInflateWithLargerWindow();
+  testZlibWithDictionary();
+  asyncEnd();
+}
diff --git a/tests/standalone_2/dwarf_stack_trace_dedup_test.dart b/tests/standalone_2/dwarf_stack_trace_dedup_test.dart
new file mode 100644
index 0000000..9c715b3
--- /dev/null
+++ b/tests/standalone_2/dwarf_stack_trace_dedup_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// VMOptions=--dwarf-stack-traces --save-debugging-info=dwarf_dedup.so --dedup-instructions
+
+import 'dart:io';
+
+import 'package:native_stack_traces/native_stack_traces.dart';
+import 'package:path/path.dart' as path;
+
+import 'dwarf_stack_trace_test.dart' as base;
+
+@pragma("vm:prefer-inline")
+bar() {
+  // Keep the 'throw' and its argument on separate lines.
+  throw // force linebreak with dartfmt
+      "Hello, Dwarf!";
+}
+
+@pragma("vm:never-inline")
+foo() {
+  bar();
+}
+
+Future<void> main() async {
+  String rawStack;
+  try {
+    foo();
+  } catch (e, st) {
+    rawStack = st.toString();
+  }
+
+  if (path.basenameWithoutExtension(Platform.executable) !=
+      "dart_precompiled_runtime") {
+    return; // Not running from an AOT compiled snapshot.
+  }
+
+  if (Platform.isAndroid) {
+    return; // Generated dwarf.so not available on the test device.
+  }
+
+  final dwarf = Dwarf.fromFile("dwarf_dedup.so");
+
+  await base.checkStackTrace(rawStack, dwarf, expectedCallsInfo);
+}
+
+final expectedCallsInfo = <List<CallInfo>>[
+  // The first frame should correspond to the throw in bar, which was inlined
+  // into foo (so we'll get information for two calls for that PC address).
+  [
+    CallInfo(
+        function: "bar",
+        filename: "dwarf_stack_trace_dedup_test.dart",
+        line: 17,
+        inlined: true),
+    CallInfo(
+        function: "foo",
+        filename: "dwarf_stack_trace_dedup_test.dart",
+        line: 23,
+        inlined: false)
+  ],
+  // The second frame corresponds to call to foo in main.
+  [
+    CallInfo(
+        function: "main",
+        filename: "dwarf_stack_trace_dedup_test.dart",
+        line: 29,
+        inlined: false)
+  ],
+  // Don't assume anything about any of the frames below the call to foo
+  // in main, as this makes the test too brittle.
+];
diff --git a/tools/VERSION b/tools/VERSION
index d082e04..ff3d2ab 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 8
 PATCH 0
-PRERELEASE 8
+PRERELEASE 9
 PRERELEASE_PATCH 0
 ABI_VERSION 28
 OLDEST_SUPPORTED_ABI_VERSION 28
diff --git a/tools/addlatexhash.dart b/tools/addlatexhash.dart
index c1cbddc..2354668 100755
--- a/tools/addlatexhash.dart
+++ b/tools/addlatexhash.dart
@@ -242,8 +242,11 @@
 extractHashLabel(line) {
   var startMatch = hashLabelStartRE.firstMatch(line);
   var endMatch = hashLabelEndRE.firstMatch(line);
-  assert(startMatch != null && endMatch != null);
-  return line.substring(startMatch.end, endMatch.start);
+  if (startMatch != null && endMatch != null) {
+    return line.substring(startMatch.end, endMatch.start);
+  } else {
+    throw "Assertion failure (so this file is both valid nnbd and not)";
+  }
 }
 
 // Event classes: Keep track of relevant information about the LaTeX
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 17a1c39..2961df6 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -29,6 +29,7 @@
       "samples-dev/",
       "samples/",
       "sdk/",
+      "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
       "tests/co19_2/co19_2-co19.status",
@@ -68,6 +69,7 @@
       "samples-dev/",
       "samples/",
       "sdk_nnbd/",
+      "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
       "tests/co19_2/co19_2-co19.status",
@@ -113,6 +115,7 @@
       "samples-dev/",
       "samples/",
       "sdk/",
+      "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
       "tests/co19_2/co19_2-co19.status",
@@ -154,6 +157,7 @@
       "samples/",
       "sdk/",
       "sdk_nnbd/",
+      "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
       "tests/co19_2/co19_2-co19.status",
@@ -191,6 +195,7 @@
       "samples/",
       "sdk/",
       "sdk_nnbd/",
+      "tests/.dart_tool/package_config.json",
       "tests/angular/",
       "tests/co19_2/co19_2-analyzer.status",
       "tests/co19_2/co19_2-co19.status",
@@ -292,6 +297,7 @@
       "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",
       "tests/co19_2/co19_2-co19.status",
@@ -2288,7 +2294,7 @@
         {
           "name": "dart2js nnbd weak tests",
           "arguments": [
-            "-ndart2js-hostasserts-weak-linux-x64-d8",
+            "-ndart2js-weak-linux-x64-d8",
             "--dart2js-batch",
             "language_2",
             "corelib_2",
@@ -2296,7 +2302,7 @@
             "dart2js_native"
           ],
           "shards": 6,
-          "fileset": "dart2js_hostasserts_nnbd"
+          "fileset": "dart2js_nnbd"
         }
       ]
     },
diff --git a/tools/build.py b/tools/build.py
index 274374c..17ee88d 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -16,10 +16,7 @@
 HOST_CPUS = utils.GuessCpus()
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-AVAILABLE_ARCHS = [
-    'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', 'simarm64',
-    'arm64', 'simarm_x64'
-]
+AVAILABLE_ARCHS = utils.ARCH_FAMILY.keys()
 
 usage = """\
 usage: %%prog [options] [targets]
@@ -107,8 +104,13 @@
         if not mode in ['debug', 'release', 'product']:
             print("Unknown mode %s" % mode)
             return False
-    for arch in options.arch:
+    for i, arch in enumerate(options.arch):
         if not arch in AVAILABLE_ARCHS:
+            # Normalise to lower case form to make it less case-picky.
+            arch_lower = arch.lower()
+            if arch_lower in AVAILABLE_ARCHS:
+                options.arch[i] = arch_lower
+                continue
             print("Unknown arch %s" % arch)
             return False
     options.os = [ProcessOsOption(os_name) for os_name in options.os]
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 0a6cbd5..150f727 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -557,6 +557,17 @@
 
 };
 
+// Make sure HTMLFormControlsCollection matches HTMLCollection.
+[DartSupplemental]
+interface HTMLFormControlsCollection : HTMLCollection  {
+
+    // FIXME: The index argument should not be optional.
+    getter Node? item([Default=Undefined] optional unsigned long index);
+
+    [DartSuppress, ImplementedAs=item] getter Node (unsigned long index);
+
+};
+
 [DartSupplemental]
 interface Performance {
     [DartSuppress] void webkitClearResourceTimings();
@@ -593,6 +604,21 @@
 };
 
 [DartSupplemental]
+interface UIEvent : Event {
+
+    // None of these are optional anymore.
+    [DartSuppress] void initUIEvent([Default=Undefined] optional DOMString type,
+                                    [Default=Undefined] optional boolean bubbles,
+                                    [Default=Undefined] optional boolean cancelable,
+                                    [Default=Undefined] optional Window? view,
+                                    [Default=Undefined] optional long detail);
+
+    void initUIEvent(DOMString type, boolean bubbles, boolean cancelable,
+                     Window? view, long detail);
+
+};
+
+[DartSupplemental]
 interface EventTarget {
     [DartSuppress] void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options);
     [DartSuppress] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options);
diff --git a/tools/dom/nnbd_src/AttributeMap.dart b/tools/dom/nnbd_src/AttributeMap.dart
index 7c57d7d..fad3c44 100644
--- a/tools/dom/nnbd_src/AttributeMap.dart
+++ b/tools/dom/nnbd_src/AttributeMap.dart
@@ -100,7 +100,7 @@
   }
 
   String? operator [](Object? key) {
-    return _element.getAttribute(key as String?);
+    return _element.getAttribute(key as String);
   }
 
   void operator []=(String key, String value) {
@@ -148,7 +148,7 @@
   }
 
   String? operator [](Object? key) {
-    return _element.getAttributeNS(_namespace, key as String?);
+    return _element.getAttributeNS(_namespace, key as String);
   }
 
   void operator []=(String key, String value) {
diff --git a/tools/dom/scripts/css_code_generator.py b/tools/dom/scripts/css_code_generator.py
index 19676e6..9e71e69 100644
--- a/tools/dom/scripts/css_code_generator.py
+++ b/tools/dom/scripts/css_code_generator.py
@@ -151,7 +151,8 @@
   }
 
 
-  void setProperty(String propertyName, String value, [String priority]) {
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]) {
     return _setPropertyHelper(_browserPropertyName(propertyName),
       value, priority);
   }
@@ -229,7 +230,7 @@
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
   final Iterable<Element> _elementIterable;
-  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+  Iterable<CssStyleDeclaration>$NULLABLE _elementCssStyleDeclarationSetIterable;
 
   _CssStyleDeclarationSet(this._elementIterable) {
     _elementCssStyleDeclarationSetIterable = new List.from(
@@ -237,11 +238,12 @@
   }
 
   String getPropertyValue(String propertyName) =>
-      _elementCssStyleDeclarationSetIterable.first.getPropertyValue(
+      _elementCssStyleDeclarationSetIterable$NULLASSERT.first.getPropertyValue(
           propertyName);
 
-  void setProperty(String propertyName, String value, [String priority]) {
-    _elementCssStyleDeclarationSetIterable.forEach((e) =>
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]) {
+    _elementCssStyleDeclarationSetIterable$NULLASSERT.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
 
@@ -276,7 +278,8 @@
 
 abstract class CssStyleDeclarationBase {
   String getPropertyValue(String propertyName);
-  void setProperty(String propertyName, String value, [String priority]);
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]);
 """)
 
     class_lines = []
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 7227f3f..211004f 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -166,7 +166,8 @@
         template_loader = TemplateLoader(template_dir, template_paths, {
             'DARTIUM': False,
             'DART2JS': True,
-            'JSINTEROP': False
+            'JSINTEROP': False,
+            'NNBD': nnbd
         })
         backend_options = GeneratorOptions(template_loader, webkit_database,
                                            type_registry, renamer, metadata,
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index a24a711..3231d7f 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -459,13 +459,17 @@
 # Given a list of overloaded arguments, render dart arguments.
 def _BuildArguments(args, interface, constructor=False):
 
+    # TODO(srujzs): Determine if this should really be turning false instead of
+    # argument.optional as the default. For NNBD, we'll derive parameter
+    # nullability from argument.optional but leave optionality otherwise alone.
     def IsOptional(argument):
         if 'Callback' in argument.ext_attrs:
-            # Optional callbacks arguments are treated as optional arguments.
+            # Optional callbacks arguments are treated as optional
+            # arguments.
             return argument.optional
         if constructor:
-            # FIXME: Optional constructors arguments should not be treated as
-            # optional arguments.
+            # FIXME: Optional constructors arguments should not be treated
+            # as optional arguments.
             return argument.optional
         if 'DartForceOptional' in argument.ext_attrs:
             return True
@@ -505,6 +509,7 @@
     result = []
 
     is_optional = False
+
     # Process overloaded arguments across a set of overloaded operations.
     # Each tuple in args corresponds to overloaded arguments with the same name.
     for arg_tuple in map(lambda *x: x, *args):
@@ -514,10 +519,20 @@
         filtered = filter(None, arg_tuple)
         (type_id, is_nullable) = OverloadedType(filtered)
         name = OverloadedName(filtered)
-        default = OverloadedDefault(filtered)
+        (default_value, default_value_is_null) = OverloadedDefault(filtered)
+
+        # For nullability determination, we'll use the arguments' optionality
+        # instead of the IsOptional method above.
+        optional_argument = any(arg is None or arg.optional or
+            'DartForceOptional' in arg.ext_attrs for arg in arg_tuple)
+
+        if optional_argument and (default_value == 'Undefined' or
+                default_value == None or default_value_is_null):
+            is_nullable = True
+
         result.append(
-            ParamInfo(name, type_id, is_optional, is_nullable, default[0],
-                      default[1]))
+            ParamInfo(name, type_id, is_optional, is_nullable, default_value,
+                      default_value_is_null))
 
     return result
 
@@ -535,6 +550,15 @@
     return argument.optional and (not(HasSuppressedOptionalDefault(argument))) \
            or 'DartForceOptional' in argument.ext_attrs
 
+def OperationTypeIsNullable(operation):
+    if hasattr(operation.type, 'nullable'):
+        if operation.type.nullable:
+            return True
+    if operation.type.id == 'any':
+        # any is assumed to be nullable
+        return True
+
+    return False
 
 def AnalyzeOperation(interface, operations):
     """Makes operation calling convention decision for a set of overloads.
@@ -550,7 +574,6 @@
                 new_operation.arguments = new_operation.arguments[:i]
                 split_operations.append(new_operation)
         split_operations.append(operation)
-
     # Zip together arguments from each overload by position, then convert
     # to a dart argument.
     info = OperationInfo()
@@ -561,6 +584,7 @@
     info.constructor_name = None
     info.js_name = info.declared_name
     info.type_name = operations[0].type.id  # TODO: widen.
+    info.type_nullable = OperationTypeIsNullable(operations[0])
     info.param_infos = _BuildArguments(
         [op.arguments for op in split_operations], interface)
     full_name = '%s.%s' % (interface.id, info.declared_name)
@@ -692,6 +716,7 @@
     constructor_name: A string, the name of the constructor iff the constructor
        is named, e.g. 'fromList' in  Int8Array.fromList(list).
     type_name: A string, the name of the return type of the operation.
+    type_nullable: Whether or not the return type is nullable.
     param_infos: A list of ParamInfo.
     factory_parameters: A list of parameters used for custom designed Factory
         calls.
@@ -699,6 +724,7 @@
 
     def __init__(self):
         self.factory_parameters = None
+        self.type_nullable = False
 
     def ParametersAsDecVarLists(self, rename_type, force_optional=False):
         """ Returns a tuple (required, optional, named), where:
@@ -954,17 +980,17 @@
 class Conversion(object):
     """Represents a way of converting between types."""
 
-    def __init__(self, name, input_type, output_type):
+    def __init__(self, name, input_type, output_type, nullable_input=False,
+                 nullable_output=False):
         # input_type is the type of the API input (and the argument type of the
         # conversion function)
         # output_type is the type of the API output (and the result type of the
         # conversion function)
-        # nullsafe_output flags whether the output_type has been converted yet
-        # to a null-safe type i.e. <type>? if nullable and <type> if not
         self.function_name = name
         self.input_type = input_type
         self.output_type = output_type
-        self.nullsafe_output = False
+        self.nullable_input = nullable_input or input_type == 'dynamic'
+        self.nullable_output = nullable_output or output_type == 'dynamic'
 
 
 #  "TYPE DIRECTION INTERFACE.MEMBER" -> conversion
@@ -995,24 +1021,28 @@
         # as well.  Note, there are no functions that take a non-local Window
         # as a parameter / setter.
         'Window get':
-        Conversion('_convertNativeToDart_Window', 'dynamic', 'WindowBase'),
+        Conversion('_convertNativeToDart_Window', 'dynamic', 'WindowBase',
+                   nullable_output=True),
         'EventTarget get':
         Conversion('_convertNativeToDart_EventTarget', 'dynamic',
-                   'EventTarget'),
+                   'EventTarget', nullable_output=True),
         'EventTarget set':
         Conversion('_convertDartToNative_EventTarget', 'EventTarget',
-                   'dynamic'),
+                   'dynamic', nullable_input=True),
         'WebGLContextAttributes get':
         Conversion('convertNativeToDart_ContextAttributes', 'dynamic',
                    'ContextAttributes'),
         'ImageData get':
         Conversion('convertNativeToDart_ImageData', 'dynamic', 'ImageData'),
         'ImageData set':
-        Conversion('convertDartToNative_ImageData', 'ImageData', 'dynamic'),
+        Conversion('convertDartToNative_ImageData', 'ImageData', 'dynamic',
+                   nullable_input=True),
         'Dictionary get':
-        Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map'),
+        Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map',
+                   nullable_output=True),
         'Dictionary set':
-        Conversion('convertDartToNative_Dictionary', 'Map', 'dynamic'),
+        Conversion('convertDartToNative_Dictionary', 'Map', 'dynamic',
+                   nullable_input=True),
         'sequence<DOMString> set':
         Conversion('convertDartToNative_StringArray', 'List<String>', 'List'),
         'any set IDBObjectStore.add':
@@ -1022,7 +1052,8 @@
         'any set IDBCursor.update':
         _serialize_SSV,
         'any get SQLResultSetRowList.item':
-        Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map'),
+        Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map',
+                   nullable_output=True),
 
         # postMessage
         'SerializedScriptValue set':
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 1a5387d..a2e1586 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -314,9 +314,14 @@
         # We don't yet handle inconsistent renames of the getter and setter yet.
         assert (not html_setter_name or attr_name == html_setter_name)
 
+        # any is assumed to be nullable
+        if attribute.type.id == 'any':
+            attribute.type.nullable = True
+
         if declare_only:
             self.DeclareAttribute(attribute,
-                                  self.SecureOutputType(attribute.type.id),
+                                  self.SecureOutputType(attribute.type.id,
+                                    nullable=attribute.type.nullable),
                                   attr_name, read_only)
         else:
             self.EmitAttribute(attribute, attr_name, read_only)
@@ -345,7 +350,9 @@
             return
 
         if declare_only:
-            self.DeclareOperation(info, self.SecureOutputType(info.type_name),
+            self.DeclareOperation(info,
+                                  self.SecureOutputType(info.type_name,
+                                      nullable=info.type_nullable),
                                   method_name)
         else:
             self.EmitOperation(info, method_name, dart_js_interop)
@@ -512,6 +519,9 @@
         if self._interface_type_info.list_item_type():
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
+            if self._nnbd and \
+                    self._interface_type_info.list_item_type_nullable():
+                item_type += '?'
             implements.append('List<%s>' % item_type)
         return implements
 
@@ -520,6 +530,9 @@
         if self._interface_type_info.list_item_type():
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
+            if self._nnbd and \
+                    self._interface_type_info.list_item_type_nullable():
+                item_type += '?'
             mixins.append('ListMixin<%s>' % item_type)
             mixins.append('ImmutableListMixin<%s>' % item_type)
 
@@ -768,7 +781,8 @@
         if '_RenamingAnnotation' in dir(self):
             metadata = (
                 self._RenamingAnnotation(info.declared_name, html_name) +
-                self._Metadata(info.type_name, info.declared_name, None))
+                self._Metadata(info.type_name, info.declared_name, None,
+                    info.type_nullable))
         self._members_emitter.Emit(
             '\n'
             '  $METADATA$MODIFIERS$TYPE$FUTURE_GENERIC $NAME($PARAMS) {\n'
@@ -783,7 +797,8 @@
             '  }\n',
             METADATA=metadata,
             MODIFIERS='static ' if info.IsStatic() else '',
-            TYPE=self.SecureOutputType(info.type_name),
+            TYPE=self.SecureOutputType(info.type_name,
+                nullable=info.type_nullable),
             NAME=html_name[1:],
             PARAMS=info.
             ParametersAsDeclaration(self._NarrowInputType if '_NarrowInputType'
@@ -891,6 +906,8 @@
             })
         if nullable:
             element_js = element_name + "|Null"
+            if self._nnbd:
+                element_name += '?'
         else:
             element_js = element_name
         self._members_emitter.Emit(
@@ -919,9 +936,12 @@
         # returned in generated code.
         assert (dart_name != 'HistoryBase' and dart_name != 'LocationBase')
         if dart_name == 'Window':
-            return _secure_base_types[dart_name]
-        if self._nnbd and nullable:
-            dart_name = dart_name + '?'
+            dart_name = _secure_base_types[dart_name]
+        if self._nnbd:
+            if type_name == 'any':
+                dart_name = 'Object'
+            if nullable and dart_name != 'dynamic':
+                dart_name = dart_name + '?'
         return dart_name
 
     def SecureBaseName(self, type_name):
@@ -975,14 +995,17 @@
                 temp_version[0] += 1
                 temp_name = '%s_%s' % (param_name, temp_version[0])
                 temp_type = conversion.output_type
+                null_assert_needed = info.param_infos[position].is_nullable \
+                    and not conversion.nullable_input
                 stmts_emitter.Emit(
-                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG);\n'
+                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG$NULLASSERT);\n'
                     if callBackInfo is None else
-                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG, $ARITY);\n',
+                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG$NULLASSERT, $ARITY);\n',
                     TYPE=TypeOrVar(temp_type),
                     NAME=temp_name,
                     CONVERT=conversion.function_name,
                     ARG=info.param_infos[position].name,
+                    NULLASSERT='!' if null_assert_needed and self._nnbd else '',
                     ARITY=callBackInfo)
                 converted_arguments.append(temp_name)
                 param_type = temp_type
@@ -1006,8 +1029,16 @@
                                 'Object'
                         ]:
                             param_type = 'dynamic'
+            arg_is_nullable = arg.type.nullable
+            # If the parameter is either nullable or optional with no non-null
+            # default value, it is nullable.
+            if (info.param_infos[position].is_optional and
+                (info.param_infos[position].default_value_is_null == True or
+                 info.param_infos[position].default_value == None)
+               ) or info.param_infos[position].is_nullable:
+                arg_is_nullable = True
             target_parameters.append(
-                '%s%s' % (TypeOrNothing(param_type, nullable=arg.type.nullable),
+                '%s%s' % (TypeOrNothing(param_type, nullable=arg_is_nullable),
                           param_name))
             calling_parameters.append(',%s ' % param_name)
 
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 600ac3a..6b3750c2 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -602,9 +602,10 @@
         self._type_registry = options.type_registry
         self._options = options
         # TODO(srujzs): This sets the nnbd option globally inside generator.py
-        # since there is no options object there.  This should should be cleaned
+        # since there is no options object there. This should should be cleaned
         # up and passed as an option instead.
         global_options_hack.nnbd = options.nnbd
+        self._nnbd = options.nnbd
         self._library_emitter = library_emitter
         self._event_generator = event_generator
         self._interface = interface
@@ -818,7 +819,8 @@
             KEYTYPE=maplikeKeyType,
             VALUETYPE=maplikeValueType,
             NULLABLE='?' if self._options.nnbd else '',
-            NULLSAFECAST=True if self._options.nnbd else False)
+            NULLSAFECAST=True if self._options.nnbd else False,
+            NULLASSERT='!' if self._options.nnbd else '')
         stream_getter_signatures_emitter = None
         element_stream_getters_emitter = None
         if type(implementation_members_emitter) == tuple:
@@ -1189,6 +1191,9 @@
         ):
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
+            if self._nnbd and \
+                    self._interface_type_info.list_item_type_nullable():
+                item_type += '?'
             implements.append('JavaScriptIndexingBehavior<%s>' % item_type)
         return implements
 
@@ -1331,16 +1336,24 @@
 
         has_indexed_getter = self.HasIndexedGetter()
 
+        indexed_getter = False
+        indexed_getter_nullable = nullable
         if has_indexed_getter:
             indexed_getter = ('JS("%s%s", "#[#]", this, index)' %
                               (self.SecureOutputType(element_type),
                                "|Null" if nullable else ""))
-        elif any(op.id == 'getItem' for op in self._interface.operations):
-            indexed_getter = 'this.getItem(index)'
-        elif any(op.id == 'item' for op in self._interface.operations):
-            indexed_getter = 'this.item(index)'
         else:
-            indexed_getter = False
+            for op in self._interface.operations:
+                if op.id == 'getItem':
+                    indexed_getter = 'this.getItem(index)'
+                    indexed_getter_nullable = OperationTypeIsNullable(op)
+                    break
+            if not indexed_getter:
+                for op in self._interface.operations:
+                    if op.id == 'item':
+                        indexed_getter = 'this.item(index)'
+                        indexed_getter_nullable = OperationTypeIsNullable(op)
+                        break
 
         if indexed_getter:
             self._members_emitter.Emit(
@@ -1349,17 +1362,25 @@
                 '    if (JS("bool", "# >>> 0 !== # || # >= #", index,\n'
                 '        index, index, length))\n'
                 '      throw new RangeError.index(index, this);\n'
-                '    return $INDEXED_GETTER;\n'
+                '    return $INDEXED_GETTER$NULLASSERT;\n'
                 '  }',
                 INDEXED_GETTER=indexed_getter,
-                TYPE=self.SecureOutputType(element_type, False, True))
+                TYPE=self.SecureOutputType(element_type,
+                                           is_dart_type=False,
+                                           can_narrow_type=True,
+                                           nullable=nullable),
+                # If the type of the operation is not nullable but the getter
+                # is, we must assert non-null.
+                NULLASSERT='!' if self._nnbd and not nullable and \
+                    indexed_getter_nullable else '')
 
         if 'CustomIndexedSetter' in self._interface.ext_attrs:
             self._members_emitter.Emit(
                 '\n'
-                '  void operator[]=(int index, $TYPE value) {'
+                '  void operator[]=(int index, $TYPE$NULLABLE value) {'
                 ' JS("void", "#[#] = #", this, index, value); }',
-                TYPE=self._NarrowInputType(element_type))
+                TYPE=self._NarrowInputType(element_type),
+                NULLABLE='?' if self._nnbd and nullable else '')
         else:
             theType = self._NarrowInputType(element_type)
             if theType == 'DomRectList':
@@ -1367,10 +1388,11 @@
 
             self._members_emitter.Emit(
                 '\n'
-                '  void operator[]=(int index, $TYPE value) {\n'
+                '  void operator[]=(int index, $TYPE$NULLABLE value) {\n'
                 '    throw new UnsupportedError("Cannot assign element of immutable List.");\n'
                 '  }\n',
-                TYPE=theType)
+                TYPE=theType,
+                NULLABLE='?' if self._nnbd and nullable else '')
 
         self.EmitListMixin(self._DartType(element_type), nullable)
 
@@ -1407,8 +1429,9 @@
                         '  // final $TYPE $NAME;\n',
                         SUPER=super_attribute_interface,
                         NAME=html_name,
-                        TYPE=self.SecureOutputType(attribute.type.id, False,
-                                                   read_only))
+                        TYPE=self.SecureOutputType(attribute.type.id,
+                            can_narrow_type=read_only,
+                            nullable=attribute.type.nullable))
                     return
             self._members_emitter.Emit('\n  // Shadowing definition.')
             self._AddAttributeUsingProperties(attribute, html_name, read_only)
@@ -1434,19 +1457,20 @@
 
         rename = self._RenamingAnnotation(attribute.id, html_name)
         output_type = self.SecureOutputType(attribute.type.id,
-                                            is_dart_type=False,
                                             can_narrow_type=read_only,
                                             nullable=attribute.type.nullable)
-        metadata = self._Metadata(attribute.type.id, attribute.id, output_type)
-
-        if self._nnbd and not attribute.type.nullable:
-          self._AddAttributeUsingProperties(attribute, html_name, read_only,
-                                            rename, metadata)
-          return
+        metadata = self._Metadata(attribute.type.id, attribute.id, output_type,
+            attribute.type.nullable)
 
         input_type = self._NarrowInputType(attribute.type.id)
+        if self._nnbd and attribute.type.nullable:
+            input_type += '?'
         static_attribute = 'static' if attribute.is_static else ''
         if not read_only:
+            if self._nnbd and not attribute.type.nullable:
+              self._AddAttributeUsingProperties(attribute, html_name, read_only,
+                                                rename, metadata)
+              return
             if attribute.type.id == 'Promise':
                 _logger.warn('R/W member is a Promise: %s.%s' %
                              (self._interface.id, html_name))
@@ -1459,7 +1483,6 @@
                 NAME=html_name,
                 TYPE=output_type)
         else:
-            template = '\n  $RENAME$(ANNOTATIONS)final $TYPE $NAME;\n'
             if attribute.type.id == 'Promise':
                 lookupOp = "%s.%s" % (self._interface.id, html_name)
                 promiseFound = _GetPromiseAttributeType(lookupOp)
@@ -1472,12 +1495,20 @@
                     elif promiseFound['type'] == 'dictionary':
                         # It's a dictionary so return as a Map.
                         promiseCall = 'promiseToFutureAsMap'
-                        promiseType = 'Future<Map<String, dynamic>>'
+                        output_conversion = self._OutputConversion("Dictionary",
+                                                                   None)
+                        nullability = '?' if self._nnbd and \
+                            output_conversion.nullable_output else ''
+                        promiseType = 'Future<Map<String, dynamic>' + \
+                            nullability + '>'
                     else:
                         paramType = promiseFound['type']
                         promiseCall = 'promiseToFuture<%s>' % paramType
                         promiseType = 'Future<%s>' % paramType
 
+                if self._nnbd and attribute.type.nullable:
+                    promiseType += '?'
+
                 template = '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
 
                 self._members_emitter.Emit(
@@ -1489,17 +1520,19 @@
                     NAME=html_name)
             else:
                 template = '\n  $RENAME$(ANNOTATIONS)$STATIC final $TYPE $NAME;\n'
-                # Need to use a getter for list.length properties so we can add a
-                # setter which throws an exception, satisfying List API.
-                if self._interface_type_info.list_item_type(
-                ) and html_name == 'length':
-                    template = ('\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
-                                'JS("$TYPE", "#.$NAME", this);\n')
-                output_type_without_nullability = self.SecureOutputType(
-                    attribute.type.id,
-                    is_dart_type=False,
-                    can_narrow_type=read_only,
-                    nullable=False)
+                # Need to use a getter for list.length properties so we can
+                # add a setter which throws an exception, satisfying List
+                # API.
+                if self._interface_type_info.list_item_type() and \
+                    html_name == 'length':
+                    template = (
+                        '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
+                        'JS("$TYPE", "#.$NAME", this);\n')
+                elif self._nnbd:
+                    # Finals need to be transformed to getters/setters.
+                    self._AddAttributeUsingProperties(attribute, html_name,
+                        read_only, rename, metadata)
+                    return
                 self._members_emitter.Emit(
                     template,
                     RENAME=rename,
@@ -1507,36 +1540,33 @@
                     STATIC=static_attribute,
                     NAME=html_name,
                     TYPE=input_type
-                    if output_type_without_nullability == 'double' else
-                    output_type)
+                    if output_type == 'double' else output_type)
 
     def _AddAttributeUsingProperties(self, attribute, html_name, read_only,
                                      rename=None, metadata=None):
         self._AddRenamingGetter(attribute, html_name, rename, metadata)
         if not read_only:
-            self._AddRenamingSetter(attribute, html_name, rename, metadata)
+            # No metadata for setters.
+            self._AddRenamingSetter(attribute, html_name, rename)
 
     def _AddInterfaceAttribute(self, attribute, html_name, read_only):
-        self._members_emitter.Emit(
-            '\n  $QUALIFIER$TYPE $NAME;'
-            '\n',
-            QUALIFIER='final ' if read_only else '',
-            NAME=html_name,
-            TYPE=self.SecureOutputType(attribute.type.id))
-
-    def _AddNullSafetyToConversion(self, attr, conversion):
-        if conversion.nullsafe_output == False:
-            # Convert output type to one that recognizes nullability
-            if (self._nnbd and attr.type.nullable):
-                conversion.output_type += '?'
-            conversion.nullsafe_output = True
+        if read_only and self._nnbd:
+            self._AddAttributeUsingProperties(attribute, html_name, read_only)
+        else:
+            self._members_emitter.Emit(
+                '\n  $QUALIFIER$TYPE $NAME;'
+                '\n',
+                QUALIFIER='final ' if read_only else '',
+                NAME=html_name,
+                TYPE=self.SecureOutputType(attribute.type.id,
+                    nullable=attribute.type.nullable))
 
     def _AddRenamingGetter(self, attr, html_name, rename, metadata):
         conversion = self._OutputConversion(attr.type.id, attr.id)
         if conversion:
-            self._AddNullSafetyToConversion(attr, conversion)
             return self._AddConvertingGetter(attr, html_name, conversion)
-        return_type = self.SecureOutputType(attr.type.id)
+        return_type = self.SecureOutputType(attr.type.id,
+            nullable=attr.type.nullable)
         native_type = self._NarrowToImplementationType(attr.type.id)
         self._members_emitter.Emit(
             # TODO(sra): Use metadata to provide native name.
@@ -1551,49 +1581,73 @@
             TYPE=return_type,
             NATIVE_TYPE=native_type)
 
-    def _AddRenamingSetter(self, attr, html_name, rename, metadata):
+    def _AddRenamingSetter(self, attr, html_name, rename):
         conversion = self._InputConversion(attr.type.id, attr.id)
         if conversion:
-            self._AddNullSafetyToConversion(attr, conversion)
             return self._AddConvertingSetter(attr, html_name, conversion)
+        nullable_type = attr.type.nullable
+        # 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.
+        conversion = self._OutputConversion(attr.type.id, attr.id)
+        if conversion and conversion.nullable_output:
+            nullable_type = True
         self._members_emitter.Emit(
             # TODO(sra): Use metadata to provide native name.
             '\n  $RENAME'
-            '\n  $METADATA'
             '\n  set $HTML_NAME($TYPE value) {'
             '\n    JS("void", "#.$NAME = #", this, value);'
             '\n  }'
             '\n',
             RENAME=rename if rename else '',
-            METADATA=metadata if metadata else '',
             HTML_NAME=html_name,
             NAME=attr.id,
-            TYPE=self._NarrowInputType(attr.type.id))
+            TYPE=self.SecureOutputType(attr.type.id, nullable=nullable_type))
 
     def _AddConvertingGetter(self, attr, html_name, conversion):
+        getter = '\n  $(JS_METADATA)final $NATIVE_TYPE _get_$HTML_NAME;'
+        if self._nnbd:
+            # TODO(srujzs): Should the inline call have the value type or should
+            # it be inferred?
+            getter = '\n  $(JS_METADATA)$NATIVE_TYPE$NULLABLE_IN get _get_$HTML_NAME => JS("", "#.$NAME", this);'
+        nullable_out = conversion.nullable_output and \
+            not conversion.output_type == 'dynamic'
+        # If the attribute is nullable, the getter should be nullable.
+        nullable_in = attr.type.nullable and \
+            not conversion.input_type == 'dynamic'
         self._members_emitter.Emit(
-            '\n  $(METADATA)$RETURN_TYPE get $HTML_NAME => '
-            '$CONVERT(this._get_$(HTML_NAME));'
-            "\n  @JSName('$NAME')"
-            '\n  $(JS_METADATA)final $NATIVE_TYPE _get_$HTML_NAME;'
+            '\n  $(METADATA)$RETURN_TYPE$NULLABLE_OUT get $HTML_NAME => '
+            '$CONVERT(this._get_$(HTML_NAME)$NULLASSERT);'
+            "\n  @JSName('$NAME')" +
+            getter +
             '\n',
             METADATA=self._metadata.GetFormattedMetadata(
                 self._library_name, self._interface, html_name, '  '),
             JS_METADATA=self._Metadata(attr.type.id, html_name,
-                                       conversion.input_type),
+                                       conversion.input_type,
+                                       conversion.nullable_output),
             CONVERT=conversion.function_name,
             HTML_NAME=html_name,
             NAME=attr.id,
             RETURN_TYPE=conversion.output_type,
-            NATIVE_TYPE=conversion.input_type)
+            NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
+            NATIVE_TYPE=conversion.input_type,
+            NULLABLE_IN='?' if nullable_in and self._nnbd else '',
+            NULLASSERT='!' if nullable_in and \
+                not conversion.nullable_input and self._nnbd else '')
 
     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_out = conversion.nullable_output and \
+            not conversion.output_type == 'dynamic'
         self._members_emitter.Emit(
             # TODO(sra): Use metadata to provide native name.
-            '\n  set $HTML_NAME($INPUT_TYPE value) {'
-            '\n    this._set_$HTML_NAME = $CONVERT(value);'
+            '\n  set $HTML_NAME($INPUT_TYPE$NULLABLE_IN value) {'
+            '\n    this._set_$HTML_NAME = $CONVERT(value$NULLASSERT);'
             '\n  }'
-            '\n  set _set_$HTML_NAME(/*$NATIVE_TYPE*/ value) {'
+            '\n  set _set_$HTML_NAME(/*$NATIVE_TYPE$NULLABLE_OUT*/ value) {'
             '\n    JS("void", "#.$NAME = #", this, value);'
             '\n  }'
             '\n',
@@ -1601,7 +1655,11 @@
             HTML_NAME=html_name,
             NAME=attr.id,
             INPUT_TYPE=conversion.input_type,
-            NATIVE_TYPE=conversion.output_type)
+            NULLABLE_IN='?' if nullable_in and self._nnbd else '',
+            NATIVE_TYPE=conversion.output_type,
+            NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
+            NULLASSERT='!' if nullable_in and \
+                not conversion.nullable_input and self._nnbd else '')
 
     def AmendIndexer(self, element_type):
         pass
@@ -1743,7 +1801,12 @@
                 elif paramType == 'dictionary':
                     # It's a dictionary so return as a Map.
                     promiseCall = 'promiseToFutureAsMap'
-                    promiseType = 'Future<Map<String, dynamic>>'
+                    output_conversion = self._OutputConversion("Dictionary",
+                                                               None)
+                    nullability = '?' if self._nnbd and \
+                        output_conversion.nullable_output else ''
+                    promiseType = 'Future<Map<String, dynamic>' + \
+                        nullability + '>'
                 else:
                     promiseCall = 'promiseToFuture<%s>' % paramType
                     promiseType = 'Future<%s>' % paramType
@@ -1752,11 +1815,15 @@
             dictionary_argument = info.dictionaryArgumentName()
             codeTemplate = self._promiseToFutureCode(argsNames,
                                                      dictionary_argument)
+            if self._nnbd and info.type_nullable:
+                promiseType += '?'
             self._members_emitter.Emit(
                 codeTemplate,
                 RENAME=self._RenamingAnnotation(info.declared_name, html_name),
                 METADATA=self._Metadata(info.type_name, info.declared_name,
-                                        self.SecureOutputType(info.type_name)),
+                                        self.SecureOutputType(info.type_name,
+                                            nullable=info.type_nullable),
+                                        info.type_nullable),
                 MODIFIERS='static ' if info.IsStatic() else '',
                 TYPE=promiseType,
                 PROMISE_CALL=promiseCall,
@@ -1769,9 +1836,13 @@
                 '  $RENAME$METADATA$MODIFIERS$TYPE $NAME($PARAMS) native;\n',
                 RENAME=self._RenamingAnnotation(info.declared_name, html_name),
                 METADATA=self._Metadata(info.type_name, info.declared_name,
-                                        self.SecureOutputType(info.type_name)),
+                                        self.SecureOutputType(info.type_name,
+                                            nullable=info.type_nullable),
+                                        info.type_nullable),
                 MODIFIERS='static ' if info.IsStatic() else '',
-                TYPE=self.SecureOutputType(resultType, False, True),
+                TYPE=self.SecureOutputType(resultType,
+                                           can_narrow_type=True,
+                                           nullable=info.type_nullable),
                 NAME=html_name,
                 PARAMS=info.ParametersAsDeclaration(self._NarrowInputType,
                                                     force_optional))
@@ -1818,6 +1889,11 @@
 
             if output_conversion:
                 call = '%s(%s)' % (output_conversion.function_name, call)
+                if self._nnbd and output_conversion.nullable_output and \
+                        not info.type_nullable:
+                    # Return type of operation is not nullable while conversion
+                    # is, so we need to assert non-null.
+                    call += '!'
 
             call_emitter.Emit(call)
 
@@ -1838,9 +1914,10 @@
                     '      promiseToFuture(JS("", "#.$JSNAME($HASH_STR)", this$CALLING_PARAMS));\n',
                     RENAME=self._RenamingAnnotation(info.declared_name, target),
                     METADATA=self._Metadata(info.type_name, info.declared_name,
-                                            None),
+                                            None, info.type_nullable),
                     MODIFIERS='static ' if info.IsStatic() else '',
-                    TYPE=TypeOrNothing(native_return_type),
+                    TYPE=TypeOrNothing(native_return_type,
+                        nullable=info.type_nullable),
                     TARGET=target,
                     PARAMS=', '.join(target_parameters),
                     JSNAME=operation.id,
@@ -1851,9 +1928,10 @@
                     '  $RENAME$METADATA$MODIFIERS$TYPE$TARGET($PARAMS) native;\n',
                     RENAME=self._RenamingAnnotation(info.declared_name, target),
                     METADATA=self._Metadata(info.type_name, info.declared_name,
-                                            None),
+                                            None, info.type_nullable),
                     MODIFIERS='static ' if info.IsStatic() else '',
-                    TYPE=TypeOrNothing(native_return_type),
+                    TYPE=TypeOrNothing(native_return_type,
+                        nullable=info.type_nullable),
                     TARGET=target,
                     PARAMS=', '.join(target_parameters))
 
@@ -1862,10 +1940,15 @@
         force_optional = False if hasNamedFormals(full_name) and not (
             html_name.startswith('_')) else True
 
+        nullsafe_return_type = return_type;
+        if self._nnbd and info.type_nullable:
+            nullsafe_return_type += '?'
+
         declaration = '%s%s%s %s(%s)' % (
-            self._Metadata(info.type_name, info.declared_name, return_type),
-            'static ' if info.IsStatic() else '', return_type, html_name,
-            info.ParametersAsDeclaration(InputType, force_optional))
+            self._Metadata(info.type_name, info.declared_name, return_type,
+                info.type_nullable),
+            'static ' if info.IsStatic() else '', nullsafe_return_type,
+            html_name, info.ParametersAsDeclaration(InputType, force_optional))
         self._GenerateDispatcherBody(
             info,
             operations,
@@ -1878,7 +1961,8 @@
         self._members_emitter.Emit(
             '\n'
             '  $TYPE $NAME($PARAMS);\n',
-            TYPE=self.SecureOutputType(info.type_name, False, True),
+            TYPE=self.SecureOutputType(info.type_name, can_narrow_type=True,
+                nullable=info.type_nullable),
             NAME=html_name,
             PARAMS=info.ParametersAsDeclaration(self._NarrowInputType))
 
@@ -1917,7 +2001,8 @@
             return "@JSName('%s')\n  " % idl_name
         return ''
 
-    def _Metadata(self, idl_type, idl_member_name, dart_type, indent='  '):
+    def _Metadata(self, idl_type, idl_member_name, dart_type, nullable,
+            indent='  '):
         anns = self._metadata.GetDart2JSMetadata(
             idl_type, self._library_name, self._interface, idl_member_name)
 
@@ -1926,12 +2011,18 @@
             return_type = self.SecureOutputType(idl_type)
             native_type = self._NarrowToImplementationType(idl_type)
 
+            null_union = '' if self._nnbd and not nullable else '|Null'
             if native_type != return_type:
                 anns = anns + [
-                    "@Returns('%s|Null')" % native_type,
+                    "@Returns('%s%s')" % (native_type, null_union),
                     "@Creates('%s')" % native_type,
                 ]
-        if dart_type == 'dynamic' or dart_type == 'Object':
+        if dart_type == 'dynamic' or \
+            (not self._nnbd and dart_type == 'Object') or \
+            (self._nnbd and dart_type == 'Object?'):
+            # If we're generating nnbd code, we emit non-nullable Object
+            # annotations but exclude nullable Object annotations since that's
+            # the default.
 
             def js_type_annotation(ann):
                 return re.search('^@.*Returns', ann) or re.search(
@@ -2045,7 +2136,9 @@
         library_file_dir = os.path.dirname(self._dart_path)
         auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir)
         emitters = library_emitter.Emit(
-            self._template, AUXILIARY_DIR=massage_path(auxiliary_dir))
+            self._template,
+            AUXILIARY_DIR=massage_path(auxiliary_dir),
+            NULLABLE='?' if global_options_hack.nnbd else '')
         if isinstance(emitters, tuple):
             imports_emitter, map_emitter = emitters
         else:
diff --git a/tools/dom/templates/dart2js_maplike_impl.darttemplate b/tools/dom/templates/dart2js_maplike_impl.darttemplate
index 05af119..b67307f 100644
--- a/tools/dom/templates/dart2js_maplike_impl.darttemplate
+++ b/tools/dom/templates/dart2js_maplike_impl.darttemplate
@@ -7,7 +7,7 @@
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS {
 $!MEMBERS
 
-  Map _getItem($KEYTYPE key) =>
+  Map$NULLABLE _getItem($KEYTYPE key) =>
       convertNativeToDart_Dictionary(JS('', '#.get(#)', this, key));
 
   void addAll(Map<$KEYTYPE, $VALUETYPE> other) {
@@ -18,7 +18,7 @@
 
   bool containsKey($VALUETYPE key) => _getItem(key) != null;
 
-  Map operator []($VALUETYPE key) => _getItem(key);
+  Map$NULLABLE operator []($VALUETYPE key) => _getItem(key);
 
   void forEach(void f($KEYTYPE key, $VALUETYPE value)) {
     var entries = JS('', '#.entries()', this);
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 28a7164..3d86ede 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -115,7 +115,7 @@
 /// On a successful result the native JS result will be converted to a Dart Map.
 /// See [convertNativeToDart_Dictionary]. On a rejected promise the error is
 /// forwarded without change.
-Future<Map<String, dynamic>> promiseToFutureAsMap(jsPromise) =>
+Future<Map<String, dynamic>$NULLABLE> promiseToFutureAsMap(jsPromise) =>
   promiseToFuture(jsPromise).then(convertNativeToDart_Dictionary);
 
 // Workaround for tags like <cite> that lack their own Element subclass --
@@ -132,7 +132,16 @@
   HtmlElement.created() : super.created();
 
   // From NoncedElement
+$if NNBD
+  String get nonce => JS("String", "#.nonce", this);
+
+  set nonce(String value) {
+    JS("void", "#.nonce = #", this, value);
+  }
+$else
   String nonce;
+$endif
+
 }
 
 /**
diff --git a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
index dbb094f6..e34ea4c 100644
--- a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
@@ -25,11 +25,11 @@
    * Event [KeyEvent].
    */
   factory $CLASSNAME(String type, {
-      Window view,
+      Window$NULLABLE view,
       bool canBubble: true,
       bool cancelable: true,
-      int location,
-      int keyLocation, // Legacy alias for location
+      int$NULLABLE location,
+      int$NULLABLE keyLocation, // Legacy alias for location
       bool ctrlKey: false,
       bool altKey: false,
       bool shiftKey: false,
@@ -38,15 +38,15 @@
       view = window;
     }
     location ??= keyLocation ?? 1;
-    KeyboardEvent e = document._createEvent("KeyboardEvent");
+    KeyboardEvent e = document._createEvent("KeyboardEvent") $#NULLSAFECAST(as KeyboardEvent);
     e._initKeyboardEvent(type, canBubble, cancelable, view, "",
         location, ctrlKey, altKey, shiftKey, metaKey);
     return e;
   }
 
   void _initKeyboardEvent(String type, bool canBubble, bool cancelable,
-      Window view, String keyIdentifier, int location, bool ctrlKey,
-      bool altKey, bool shiftKey, bool metaKey) {
+      Window$NULLABLE view, String keyIdentifier, int$NULLABLE location,
+      bool ctrlKey, bool altKey, bool shiftKey, bool metaKey) {
     if (JS('bool', 'typeof(#.initKeyEvent) == "function"', this)) {
       // initKeyEvent is only in Firefox (instead of initKeyboardEvent). It has
       // a slightly different signature, and allows you to specify keyCode and
diff --git a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
index f6c080a..d847db4 100644
--- a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
@@ -6,15 +6,16 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-      {Window view, int detail: 0, int screenX: 0, int screenY: 0,
+      {Window$NULLABLE view, int detail: 0, int screenX: 0, int screenY: 0,
       int clientX: 0, int clientY: 0, int button: 0, bool canBubble: true,
       bool cancelable: true, bool ctrlKey: false, bool altKey: false,
-      bool shiftKey: false, bool metaKey: false, EventTarget relatedTarget}) {
+      bool shiftKey: false, bool metaKey: false,
+      EventTarget$NULLABLE relatedTarget}) {
 
     if (view == null) {
       view = window;
     }
-    MouseEvent event = document._createEvent('MouseEvent');
+    MouseEvent event = document._createEvent('MouseEvent') $#NULLSAFECAST(as MouseEvent);
     event._initMouseEvent(type, canBubble, cancelable, view, detail,
         screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
         button, relatedTarget);
@@ -39,14 +40,14 @@
     if (JS('bool', '!!#.offsetX', this)) {
       var x = JS('int', '#.offsetX', this);
       var y = JS('int', '#.offsetY', this);
-      return new Point(x, y);
+      return new Point(x $#NULLSAFECAST(as num), y $#NULLSAFECAST(as num));
     } else {
       // Firefox does not support offsetX.
       if (!(this.target is Element)) {
         throw new UnsupportedError(
             'offsetX is only supported on elements');
       }
-      Element target = this.target;
+      Element target = this.target $#NULLSAFECAST(as Element);
       var point = (this.client - target.getBoundingClientRect().topLeft);
       return new Point(point.x.toInt(), point.y.toInt());
     }
diff --git a/tools/dom/templates/html/dart2js/impl_PaymentRequest.darttemplate b/tools/dom/templates/html/dart2js/impl_PaymentRequest.darttemplate
index 96e0513..06290b4 100644
--- a/tools/dom/templates/html/dart2js/impl_PaymentRequest.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_PaymentRequest.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS {
   factory PaymentRequest(List<Map> methodData, Map details,
-      [Map options]) {
+      [Map$NULLABLE options]) {
     var methodData_1 = [];
     for (var i in methodData) {
       methodData_1.add(convertDartToNative_Dictionary(i));
diff --git a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
index b006d56..267eae2 100644
--- a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
@@ -22,7 +22,7 @@
 import 'dart:html';
 import 'dart:html_common';
 import 'dart:_js_helper' show applyExtension, convertDartClosureToJS, Creates,
-    JSName, Native, JavaScriptIndexingBehavior;
+    JSName, Native, JavaScriptIndexingBehavior, Returns;
 import 'dart:_foreign_helper' show JS;
 import 'dart:_interceptors' show Interceptor;
 
diff --git a/tools/dom/templates/html/impl/impl_AudioContext.darttemplate b/tools/dom/templates/html/impl/impl_AudioContext.darttemplate
index 70ac3c7..d716afd 100644
--- a/tools/dom/templates/html/impl/impl_AudioContext.darttemplate
+++ b/tools/dom/templates/html/impl/impl_AudioContext.darttemplate
@@ -42,9 +42,9 @@
   }
 
   @JSName('decodeAudioData')
-  Future _decodeAudioData(ByteBuffer audioData,
-      [DecodeSuccessCallback successCallback,
-      DecodeErrorCallback errorCallback]) native;
+  Future$#NULLSAFECAST(<AudioBuffer>) _decodeAudioData(ByteBuffer audioData,
+      [DecodeSuccessCallback$NULLABLE successCallback,
+      DecodeErrorCallback$NULLABLE errorCallback]) native;
 
   Future<AudioBuffer> decodeAudioData(ByteBuffer audioData,
       [DecodeSuccessCallback$NULLABLE successCallback,
diff --git a/tools/dom/templates/html/impl/impl_Blob.darttemplate b/tools/dom/templates/html/impl/impl_Blob.darttemplate
index 856b557..fed5fa9 100644
--- a/tools/dom/templates/html/impl/impl_Blob.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Blob.darttemplate
@@ -6,7 +6,8 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 $!MEMBERS
-  factory Blob(List blobParts, [String type, String endings]) {
+  factory Blob(List blobParts, [String$NULLABLE type,
+      String$NULLABLE endings]) {
     // TODO: validate that blobParts is a JS Array and convert if not.
     // TODO: any coercions on the elements of blobParts, e.g. coerce a typed
     // array to ArrayBuffer if it is a total view.
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index be015e6..6edac30 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -53,7 +53,8 @@
   }
 
 
-  void setProperty(String propertyName, String value, [String priority]) {
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]) {
     return _setPropertyHelper(_browserPropertyName(propertyName),
       value, priority);
   }
@@ -1103,7 +1104,7 @@
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
   final Iterable<Element> _elementIterable;
-  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+  Iterable<CssStyleDeclaration>$NULLABLE _elementCssStyleDeclarationSetIterable;
 
   _CssStyleDeclarationSet(this._elementIterable) {
     _elementCssStyleDeclarationSetIterable = new List.from(
@@ -1111,11 +1112,12 @@
   }
 
   String getPropertyValue(String propertyName) =>
-      _elementCssStyleDeclarationSetIterable.first.getPropertyValue(
+      _elementCssStyleDeclarationSetIterable$NULLASSERT.first.getPropertyValue(
           propertyName);
 
-  void setProperty(String propertyName, String value, [String priority]) {
-    _elementCssStyleDeclarationSetIterable.forEach((e) =>
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]) {
+    _elementCssStyleDeclarationSetIterable$NULLASSERT.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
 
@@ -1587,7 +1589,8 @@
 
 abstract class CssStyleDeclarationBase {
   String getPropertyValue(String propertyName);
-  void setProperty(String propertyName, String value, [String priority]);
+  void setProperty(String propertyName, String value,
+      [String$NULLABLE priority]);
 
   /** Gets the value of "align-content" */
   String get alignContent =>
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index ac9403d..7bd1134 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -101,7 +101,7 @@
    * from the WHATWG.
    */
   void drawImageToRect(CanvasImageSource source, Rectangle destRect,
-      {Rectangle sourceRect}) {
+      {Rectangle$NULLABLE sourceRect}) {
     if (sourceRect == null) {
       drawImageScaled(source,
           destRect.left,
@@ -249,7 +249,7 @@
       return JS('List<num>', '#.getLineDash()', this);
     } else if (JS('bool', '!!#.webkitLineDash', this)) {
       return JS('List<num>', '#.webkitLineDash', this);
-    } 
+    }
   }
 
   @SupportedBrowser(SupportedBrowser.CHROME)
@@ -281,7 +281,7 @@
    * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
    * drawn text.
    */
-  void fillText(String text, num x, num y, [num maxWidth]) {
+  void fillText(String text, num x, num y, [num$NULLABLE maxWidth]) {
     if (maxWidth != null) {
       JS('void', '#.fillText(#, #, #, #)', this, text, x, y, maxWidth);
     } else {
diff --git a/tools/dom/templates/html/impl/impl_Comment.darttemplate b/tools/dom/templates/html/impl/impl_Comment.darttemplate
index aebaf0b..ded20ac 100644
--- a/tools/dom/templates/html/impl/impl_Comment.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Comment.darttemplate
@@ -5,7 +5,7 @@
 part of $LIBRARYNAME;
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS {
-  factory Comment([String data]) {
+  factory Comment([String$NULLABLE data]) {
     return JS('returns:Comment;depends:none;effects:none;new:true',
         '#.createComment(#)', document, data == null ? "" : data);
   }
diff --git a/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate b/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
index f3da2db..f76cb37 100644
--- a/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CompositionEvent.darttemplate
@@ -8,12 +8,13 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-      {bool canBubble: false, bool cancelable: false, Window view,
-      String data, String locale}) {
+      {bool canBubble: false, bool cancelable: false, Window$NULLABLE view,
+      String$NULLABLE data, String$NULLABLE locale}) {
     if (view == null) {
       view = window;
     }
-    CompositionEvent e = document._createEvent("CompositionEvent");
+    CompositionEvent e =
+        document._createEvent("CompositionEvent") $#NULLSAFECAST(as CompositionEvent);
 
     if (Device.isFirefox) {
       // Firefox requires the locale parameter that isn't supported elsewhere.
diff --git a/tools/dom/templates/html/impl/impl_CustomEvent.darttemplate b/tools/dom/templates/html/impl/impl_CustomEvent.darttemplate
index 02a4f92..b1c0cc07 100644
--- a/tools/dom/templates/html/impl/impl_CustomEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CustomEvent.darttemplate
@@ -11,9 +11,9 @@
   var _dartDetail;
 
   factory $CLASSNAME(String type,
-      {bool canBubble: true, bool cancelable: true, Object detail}) {
+      {bool canBubble: true, bool cancelable: true, Object$NULLABLE detail}) {
 
-    final CustomEvent e = document._createEvent('CustomEvent');
+    final CustomEvent e = document._createEvent('CustomEvent') $#NULLSAFECAST(as CustomEvent);
 
     e._dartDetail = detail;
 
diff --git a/tools/dom/templates/html/impl/impl_DOMException.darttemplate b/tools/dom/templates/html/impl/impl_DOMException.darttemplate
index cf127fa..74afe2e 100644
--- a/tools/dom/templates/html/impl/impl_DOMException.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMException.darttemplate
@@ -47,7 +47,7 @@
     // Chrome release still uses old string, remove this line when Chrome stable
     // also prints out SyntaxError.
     if (Device.isWebKit && errorName == 'SYNTAX_ERR') return 'SyntaxError';
-    return errorName;
+    return errorName $#NULLSAFECAST(as String);
   }
 $!MEMBERS
   String toString() => JS('String', 'String(#)', this);
diff --git a/tools/dom/templates/html/impl/impl_DOMRect.darttemplate b/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
index a2b037d..861096c 100644
--- a/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
@@ -30,7 +30,7 @@
    * Returns the intersection of this and `other`, or null if they don't
    * intersect.
    */
-  Rectangle intersection(Rectangle other) {
+  Rectangle$NULLABLE intersection(Rectangle other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
diff --git a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
index 611db89..e1febe3 100644
--- a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
@@ -30,7 +30,7 @@
    * Returns the intersection of this and `other`, or null if they don't
    * intersect.
    */
-  Rectangle intersection(Rectangle other) {
+  Rectangle$NULLABLE intersection(Rectangle other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
diff --git a/tools/dom/templates/html/impl/impl_DataTransferItem.darttemplate b/tools/dom/templates/html/impl/impl_DataTransferItem.darttemplate
index 8294cc1..a74989b 100644
--- a/tools/dom/templates/html/impl/impl_DataTransferItem.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DataTransferItem.darttemplate
@@ -7,7 +7,7 @@
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
   Entry getAsEntry() {
-    Entry entry = _webkitGetAsEntry();
+    Entry entry = _webkitGetAsEntry() $#NULLSAFECAST(as Entry);
 
     if (entry.isFile)
       applyExtension('FileEntry', entry);
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index 193a66e..c6b0eff 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -37,12 +37,12 @@
   bool get supportsRegister => supportsRegisterElement;
 
   void registerElement(String tag, Type customElementClass,
-      {String extendsTag}) {
+      {String$NULLABLE extendsTag}) {
         registerElement2(tag, {'prototype': customElementClass, 'extends': extendsTag});
   }
 
   @pragma('dart2js:tryInline') // Almost all call sites have one argument.
-  Element createElement(String tagName, [String typeExtension]) {
+  Element createElement(String tagName, [String$NULLABLE typeExtension]) {
     return (typeExtension == null)
         ? _createElement_2(tagName)
         : _createElement(tagName, typeExtension);
@@ -58,19 +58,20 @@
   _createElementNS_2(String namespaceURI, String qualifiedName) =>
       JS('Element', '#.createElementNS(#, #)', this, namespaceURI, qualifiedName);
 
-  Element createElementNS(String namespaceURI, String qualifiedName, [String typeExtension]) {
+  Element createElementNS(String namespaceURI, String qualifiedName,
+      [String$NULLABLE typeExtension]) {
     return (typeExtension == null)
         ? _createElementNS_2(namespaceURI, qualifiedName)
         : _createElementNS(namespaceURI, qualifiedName, typeExtension);
   }
 
   NodeIterator _createNodeIterator(Node root,
-      [int whatToShow, NodeFilter filter])
+      [int$NULLABLE whatToShow, NodeFilter$NULLABLE filter])
       => JS('NodeIterator', '#.createNodeIterator(#, #, #, false)',
           this, root, whatToShow, filter);
 
   TreeWalker _createTreeWalker(Node root,
-      [int whatToShow, NodeFilter filter])
+      [int$NULLABLE whatToShow, NodeFilter$NULLABLE filter])
       => JS('TreeWalker', '#.createTreeWalker(#, #, #, false)',
           this, root, whatToShow, filter);
 
diff --git a/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate b/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
index 12f15b1..ea760be 100644
--- a/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DocumentFragment.darttemplate
@@ -8,14 +8,16 @@
   factory $CLASSNAME() => document.createDocumentFragment();
 
   factory $CLASSNAME.html(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
 
     return document.body.createFragment(html,
       validator: validator, treeSanitizer: treeSanitizer);
   }
 
   factory $CLASSNAME.svg(String svgContent,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
 
     return new svg.SvgSvgElement().createFragment(svgContent,
         validator: validator, treeSanitizer: treeSanitizer);
@@ -69,7 +71,8 @@
   }
 
   void setInnerHtml(String html,
-    {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+    {NodeValidator$NULLABLE validator,
+     NodeTreeSanitizer$NULLABLE treeSanitizer}) {
 
     this.nodes.clear();
     append(document.body.createFragment(
@@ -90,7 +93,8 @@
    * last child of this document fragment.
    */
   void appendHtml(String text,
-        {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+        {NodeValidator$NULLABLE validator,
+         NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     this.append(new DocumentFragment.html(text, validator: validator,
         treeSanitizer: treeSanitizer));
   }
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 67917c5..80d1928 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -11,7 +11,7 @@
   final HtmlCollection _childElements;
 
   _ChildrenElementList._wrap(Element element)
-    : _childElements = element._children,
+    : _childElements = element._children $#NULLSAFECAST(as HtmlCollection),
       _element = element;
 
   bool contains(Object$NULLABLE element) => _childElements.contains(element);
@@ -26,7 +26,7 @@
   }
 
   Element operator [](int index) {
-    return _childElements[index];
+    return _childElements[index] $#NULLSAFECAST(as Element);
   }
 
   void operator []=(int index, Element value) {
@@ -145,14 +145,14 @@
   }
 
   Element get first {
-    Element result = _element._firstElementChild;
+    Element$NULLABLE result = _element._firstElementChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
 
 
   Element get last {
-    Element result = _element._lastElementChild;
+    Element$NULLABLE result = _element._lastElementChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
@@ -270,7 +270,7 @@
 
   int get length => _nodeList.length;
 
-  E operator [](int index) => _nodeList[index];
+  E operator [](int index) => _nodeList[index] $#NULLSAFECAST(as E);
 
   void operator []=(int index, E value) {
     throw new UnsupportedError('Cannot modify list');
@@ -288,11 +288,11 @@
     throw new UnsupportedError('Cannot shuffle list');
   }
 
-  E get first => _nodeList.first;
+  E get first => _nodeList.first $#NULLSAFECAST(as E);
 
-  E get last => _nodeList.last;
+  E get last => _nodeList.last $#NULLSAFECAST(as E);
 
-  E get single => _nodeList.single;
+  E get single => _nodeList.single $#NULLSAFECAST(as E);
 
   CssClassSet get classes => new _MultiElementCssClassSet(this);
 
@@ -346,11 +346,12 @@
    *
    */
   factory Element.html(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     var fragment = document.body.createFragment(html, validator: validator,
         treeSanitizer: treeSanitizer);
 
-    return fragment.nodes.where((e) => e is Element).single;
+    return fragment.nodes.where((e) => e is Element).single $#NULLSAFECAST(as Element);
   }
 
   /**
@@ -395,8 +396,8 @@
    *
    * * [isTagSupported]
    */
-  factory $CLASSNAME.tag(String tag, [String typeExtention]) =>
-      _$(CLASSNAME)FactoryProvider.createElement_tag(tag, typeExtention);
+  factory $CLASSNAME.tag(String tag, [String$NULLABLE typeExtension]) =>
+      _$(CLASSNAME)FactoryProvider.createElement_tag(tag, typeExtension);
 
   /// Creates a new `<a>` element.
   ///
@@ -559,67 +560,91 @@
     Map<String, String> attributes = this.attributes;
     attributes.clear();
     for (String key in value.keys) {
-      attributes[key] = value[key];
+      attributes[key] = value[key]$NULLASSERT;
     }
   }
 
   @pragma('dart2js:tryInline')
-  String getAttribute(String name) {
+  String$NULLABLE getAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     return _getAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  String getAttributeNS(String namespaceURI, String name) {
+  String$NULLABLE getAttributeNS(String$NULLABLE namespaceURI, String name) {
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     return _getAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   bool hasAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     return _hasAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  bool hasAttributeNS(String namespaceURI, String name) {
+  bool hasAttributeNS(String$NULLABLE namespaceURI, String name) {
     // Protect [name] against string conversion to "null" or "undefined".
     // [namespaceURI] does not need protecting, both `null` and `undefined` map to `null`.
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     return _hasAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   void removeAttribute(String name) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     _removeAttribute(name);
   }
 
   @pragma('dart2js:tryInline')
-  void removeAttributeNS(String namespaceURI, String name) {
+  void removeAttributeNS(String$NULLABLE namespaceURI, String name) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
+$endif
     _removeAttributeNS(namespaceURI, name);
   }
 
   @pragma('dart2js:tryInline')
   void setAttribute(String name, String value) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
+$endif
     _setAttribute(name, value);
   }
 
   @pragma('dart2js:tryInline')
-  void setAttributeNS(String namespaceURI, String name, String value) {
+  void setAttributeNS(String$NULLABLE namespaceURI, String name, String value) {
     // Protect [name] against string conversion to "null" or "undefined".
+$if NNBD
+$else
     assert(name != null, 'Attribute name cannot be null');
     // TODO(sra): assert(value != null, 'Attribute value cannot be null.');
+$endif
     _setAttributeNS(namespaceURI, name, value);
   }
 
@@ -732,7 +757,7 @@
     final data = this.dataset;
     data.clear();
     for (String key in value.keys) {
-      data[key] = value[key];
+      data[key] = value[key]$NULLASSERT;
     }
   }
 
@@ -795,8 +820,8 @@
    * Parses the specified text as HTML and adds the resulting node after the
    * last child of this element.
    */
-  void appendHtml(String text, {NodeValidator validator,
-      NodeTreeSanitizer treeSanitizer}) {
+  void appendHtml(String text, {NodeValidator$NULLABLE validator,
+      NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     this.insertAdjacentHtml('beforeend', text, validator: validator,
         treeSanitizer: treeSanitizer);
   }
@@ -920,7 +945,7 @@
    * * [Node.namespaceURI](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSname)
    *   from W3C.
    */
-  String get namespaceUri => _namespaceUri;
+  String$NULLABLE get namespaceUri => _namespaceUri;
 
   /**
    * The string representation of this element.
@@ -948,7 +973,7 @@
    * * [scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
    *   from MDN.
    */
-  void scrollIntoView([ScrollAlignment alignment]) {
+  void scrollIntoView([ScrollAlignment$NULLABLE alignment]) {
     var hasScrollIntoViewIfNeeded = true;
     hasScrollIntoViewIfNeeded =
         JS('bool', '!!(#.scrollIntoViewIfNeeded)', this);
@@ -1042,8 +1067,9 @@
    * * [insertAdjacentText]
    * * [insertAdjacentElement]
    */
-  void insertAdjacentHtml(String where, String html, {NodeValidator validator,
-      NodeTreeSanitizer treeSanitizer}) {
+  void insertAdjacentHtml(String where, String html,
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
       if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
         _insertAdjacentHtml(where, html);
       } else {
@@ -1081,7 +1107,7 @@
   void _insertAdjacentNode(String where, Node node) {
     switch (where.toLowerCase()) {
       case 'beforebegin':
-        this.parentNode.insertBefore(node, this);
+        this.parentNode$NULLASSERT.insertBefore(node, this);
         break;
       case 'afterbegin':
         var first = this.nodes.length > 0 ? this.nodes[0] : null;
@@ -1091,7 +1117,7 @@
         this.append(node);
         break;
       case 'afterend':
-        this.parentNode.insertBefore(node, this.nextNode);
+        this.parentNode$NULLASSERT.insertBefore(node, this.nextNode);
         break;
       default:
         throw new ArgumentError("Invalid position ${where}");
@@ -1119,9 +1145,9 @@
 
   /** Checks if this element or any of its parents match the CSS selectors. */
   bool matchesWithAncestors(String selectors) {
-    var elem = this;
+    var elem = this $#NULLSAFECAST(as Element$NULLABLE);
     do {
-      if (elem.matches(selectors)) return true;
+      if (elem$NULLASSERT.matches(selectors)) return true;
       elem = elem.parent;
     } while(elem != null);
     return false;
@@ -1234,7 +1260,7 @@
    * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
-  Point get documentOffset => offsetTo(document.documentElement);
+  Point get documentOffset => offsetTo(document.documentElement$NULLASSERT);
 
   /**
    * Provides the offset of this element's [borderEdge] relative to the
@@ -1268,10 +1294,10 @@
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
 
-  static HtmlDocument _parseDocument;
-  static Range _parseRange;
-  static NodeValidatorBuilder _defaultValidator;
-  static _ValidatingTreeSanitizer _defaultSanitizer;
+  static HtmlDocument$NULLABLE _parseDocument;
+  static Range$NULLABLE _parseRange;
+  static NodeValidatorBuilder$NULLABLE _defaultValidator;
+  static _ValidatingTreeSanitizer$NULLABLE _defaultSanitizer;
 
   /**
    * Create a DocumentFragment from the HTML fragment and ensure that it follows
@@ -1294,7 +1320,8 @@
    * * [NodeTreeSanitizer]
    */
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     if (treeSanitizer == null) {
       if (validator == null) {
         if (_defaultValidator == null) {
@@ -1303,9 +1330,9 @@
         validator = _defaultValidator;
       }
       if (_defaultSanitizer == null) {
-        _defaultSanitizer = new _ValidatingTreeSanitizer(validator);
+        _defaultSanitizer = new _ValidatingTreeSanitizer(validator$NULLASSERT);
       } else {
-        _defaultSanitizer.validator = validator;
+        _defaultSanitizer$NULLASSERT.validator = validator$NULLASSERT;
       }
       treeSanitizer = _defaultSanitizer;
     } else if (validator != null) {
@@ -1315,45 +1342,47 @@
 
     if (_parseDocument == null) {
       _parseDocument = document.implementation.createHtmlDocument('');
-      _parseRange = _parseDocument.createRange();
+      _parseRange = _parseDocument$NULLASSERT.createRange();
 
       // Workaround for Safari bug. Was also previously Chrome bug 229142
       // - URIs are not resolved in new doc.
-      BaseElement base = _parseDocument.createElement('base') $#NULLSAFECAST(as BaseElement);
+      BaseElement base =
+          _parseDocument$NULLASSERT.createElement('base') $#NULLSAFECAST(as BaseElement);
       base.href = document.baseUri;
-      _parseDocument.head.append(base);
+      _parseDocument$NULLASSERT.head$NULLASSERT.append(base);
     }
 
     // TODO(terry): Fixes Chromium 50 change no body after createHtmlDocument()
-    if (_parseDocument.body == null) {
-      _parseDocument.body = _parseDocument.createElement("body");
+    if (_parseDocument$NULLASSERT.body == null) {
+      _parseDocument$NULLASSERT.body =
+          _parseDocument$NULLASSERT.createElement("body") $#NULLSAFECAST(as BodyElement);
     }
 
     var contextElement;
     if (this is BodyElement) {
-      contextElement = _parseDocument.body;
+      contextElement = _parseDocument$NULLASSERT.body;
     } else {
-      contextElement = _parseDocument.createElement(tagName);
-      _parseDocument.body.append(contextElement);
+      contextElement = _parseDocument$NULLASSERT.createElement(tagName);
+      _parseDocument$NULLASSERT.body.append(contextElement);
     }
     var fragment;
     if (Range.supportsCreateContextualFragment &&
         _canBeUsedToCreateContextualFragment) {
-      _parseRange.selectNodeContents(contextElement);
-      fragment = _parseRange.createContextualFragment(html);
+      _parseRange$NULLASSERT.selectNodeContents(contextElement);
+      fragment = _parseRange$NULLASSERT.createContextualFragment(html);
     } else {
       contextElement._innerHtml = html;
 
-      fragment = _parseDocument.createDocumentFragment();
+      fragment = _parseDocument$NULLASSERT.createDocumentFragment();
       while (contextElement.firstChild != null) {
         fragment.append(contextElement.firstChild);
       }
     }
-    if (contextElement != _parseDocument.body) {
+    if (contextElement != _parseDocument$NULLASSERT.body) {
       contextElement.remove();
     }
 
-    treeSanitizer.sanitizeTree(fragment);
+    treeSanitizer$NULLASSERT.sanitizeTree(fragment);
     // Copy the fragment over to the main document (fix for 14184)
     document.adoptNode(fragment);
 
@@ -1410,7 +1439,8 @@
    * * [NodeTreeSanitizer]
    */
   void setInnerHtml(String html,
-    {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+    {NodeValidator$NULLABLE validator,
+     NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     text = null;
     if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
       _innerHtml = html;
@@ -1422,7 +1452,7 @@
   String get innerHtml => _innerHtml;
 
   @JSName('innerText')
-  String innerText;
+  String$NULLABLE innerText;
 
   /**
    * This is an ease-of-use accessor for event streams which should only be
@@ -1490,7 +1520,11 @@
     return result;
   }
 
+$if NNBD
+  Element get offsetParent => JS("Element", "#.offsetParent", this);
+$else
   final Element offsetParent;
+$endif
 
   int get offsetHeight => JS<num>('num', '#.offsetHeight', this).round();
 
@@ -1523,7 +1557,7 @@
 
   // Optimization to improve performance until the dart2js compiler inlines this
   // method.
-  static dynamic createElement_tag(String tag, String typeExtension) {
+  static dynamic createElement_tag(String tag, String$NULLABLE typeExtension) {
     // Firefox may return a JS function for some types (Embed, Object).
     if (typeExtension != null) {
       return JS('Element|=Object', 'document.createElement(#, #)',
diff --git a/tools/dom/templates/html/impl/impl_Event.darttemplate b/tools/dom/templates/html/impl/impl_Event.darttemplate
index 45a00d5..7a4d92e 100644
--- a/tools/dom/templates/html/impl/impl_Event.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Event.darttemplate
@@ -35,7 +35,7 @@
   }
 
   /** The CSS selector involved with event delegation. */
-  String _selector;
+  String$NULLABLE _selector;
 
   /**
    * A pointer to the element whose CSS selector matched within which an event
@@ -47,18 +47,18 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    Element currentTarget = this.currentTarget;
-    Element target = this.target;
+    Element$NULLABLE currentTarget = this.currentTarget $#NULLSAFECAST(as Element$NULLABLE);
+    Element$NULLABLE target = this.target $#NULLSAFECAST(as Element$NULLABLE);
     var matchedTarget;
     do {
-      if (target.matches(_selector)) return target;
+      if (target$NULLASSERT.matches(_selector$NULLASSERT)) return target;
       target = target.parent;
-    } while (target != null && target != currentTarget.parent);
+    } while (target != null && target != currentTarget$NULLASSERT.parent);
     throw new StateError('No selector matched for populating matchedTarget.');
   }
 
   List<EventTarget> get path =>
-    JS('bool', '!!#.composedPath', this) ? composedPath() : [];
+    JS<bool>('bool', '!!#.composedPath', this) ? composedPath() : [];
 
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
index e23040c..2026d53 100644
--- a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
+++ b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
@@ -99,7 +99,8 @@
    */
   Events get on => new Events(this);
 
-  void addEventListener(String type, EventListener listener, [bool useCapture]) {
+  void addEventListener(String type, EventListener$NULLABLE listener,
+      [bool$NULLABLE useCapture]) {
     // TODO(leafp): This check is avoid a bug in our dispatch code when
     // listener is null.  The browser treats this call as a no-op in this
     // case, so it's fine to short-circuit it, but we should not have to.
@@ -108,7 +109,8 @@
     }
   }
 
-  void removeEventListener(String type, EventListener listener, [bool useCapture]) {
+  void removeEventListener(String type, EventListener$NULLABLE listener,
+      [bool$NULLABLE useCapture]) {
     // TODO(leafp): This check is avoid a bug in our dispatch code when
     // listener is null.  The browser treats this call as a no-op in this
     // case, so it's fine to short-circuit it, but we should not have to.
diff --git a/tools/dom/templates/html/impl/impl_FileReader.darttemplate b/tools/dom/templates/html/impl/impl_FileReader.darttemplate
index 366774b..a438f58 100644
--- a/tools/dom/templates/html/impl/impl_FileReader.darttemplate
+++ b/tools/dom/templates/html/impl/impl_FileReader.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
-  Object get result {
+  Object$NULLABLE get result {
     var res = JS('Null|String|NativeByteBuffer', '#.result', this);
     if (res is ByteBuffer) {
       return new Uint8List.view(res);
diff --git a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
index a908f1d..db6fbbf 100644
--- a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
@@ -48,27 +48,25 @@
       options['maximumAge'] = maximumAge.inMilliseconds;
     }
 
-    int watchId;
-    // TODO(jacobr): it seems like a bug that we have to specifiy the static
-    // type here for controller.stream to have the right type.
-    // dartbug.com/26278
-    StreamController<Geoposition> controller;
-    controller = new StreamController<Geoposition>(sync: true,
-      onListen: () {
-        assert(watchId == null);
-        watchId = _watchPosition(
-            (position) {
-              controller.add(_ensurePosition(position));
-            },
-            (error) {
-              controller.addError(error);
-            },
-            options);
-      },
-      onCancel: () {
-        assert(watchId != null);
-        _clearWatch(watchId);
-      });
+    int$NULLABLE watchId;
+    StreamController<Geoposition> controller =
+      new StreamController<Geoposition>(sync: true,
+        onCancel: () {
+          assert(watchId != null);
+          _clearWatch(watchId$NULLASSERT);
+        }
+      );
+    controller.onListen = () {
+      assert(watchId == null);
+      watchId = _watchPosition(
+          (position) {
+            controller.add(_ensurePosition(position));
+          },
+          (error) {
+            controller.addError(error);
+          },
+          options);
+    };
 
     return controller.stream;
   }
diff --git a/tools/dom/templates/html/impl/impl_GlobalEventHandlers.darttemplate b/tools/dom/templates/html/impl/impl_GlobalEventHandlers.darttemplate
index 7ce924f..bd3f24f 100644
--- a/tools/dom/templates/html/impl/impl_GlobalEventHandlers.darttemplate
+++ b/tools/dom/templates/html/impl/impl_GlobalEventHandlers.darttemplate
@@ -9,9 +9,11 @@
 // get generated require `this` to be an EventTarget.
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME implements EventTarget {
 
-  void addEventListener(String type, dynamic listener(Event event), [bool useCapture]);
+  void addEventListener(String type, dynamic listener(Event event)$NULLABLE,
+      [bool$NULLABLE useCapture]);
   bool dispatchEvent(Event event);
-  void removeEventListener(String type, dynamic listener(Event event), [bool useCapture]);
+  void removeEventListener(String type, dynamic listener(Event event)$NULLABLE,
+      [bool$NULLABLE useCapture]);
   Events get on;
 
 $!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_HTMLAudioElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLAudioElement.darttemplate
index be9517a..1d630d4 100644
--- a/tools/dom/templates/html/impl/impl_HTMLAudioElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLAudioElement.darttemplate
@@ -6,5 +6,5 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 $!MEMBERS
-  factory AudioElement([String src]) => new AudioElement._(src);
+  factory AudioElement([String$NULLABLE src]) => new AudioElement._(src);
 }
diff --git a/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
index 409055d..17f74e8 100644
--- a/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLCanvasElement.darttemplate
@@ -36,7 +36,7 @@
     if (context == null) {
       context = getContext('experimental-webgl', options);
     }
-    return context;
+    return context $#NULLSAFECAST(as gl.RenderingContext);
   }
 
   /**
@@ -80,7 +80,7 @@
    *
    * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.
    */
-  String toDataUrl([String type = 'image/png', num quality]) =>
+  String toDataUrl([String type = 'image/png', num$NULLABLE quality]) =>
       _toDataUrl(type, quality);
 
   @JSName('toBlob')
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 5c9f937..5e0af0b 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -17,20 +17,20 @@
     return _caretRangeFromPoint(x, y);
   }
 
-  Element elementFromPoint(int x, int y) {
+  Element$NULLABLE elementFromPoint(int x, int y) {
     return _elementFromPoint(x, y);
   }
 
-  HeadElement get head => _head;
+  HeadElement$NULLABLE get head => _head;
 
   String get lastModified => _lastModified;
 
-  String get preferredStylesheetSet => _preferredStylesheetSet;
+  String$NULLABLE get preferredStylesheetSet => _preferredStylesheetSet;
 
   String get referrer => _referrer;
 
-  String get selectedStylesheetSet => _selectedStylesheetSet;
-  set selectedStylesheetSet(String value) {
+  String$NULLABLE get selectedStylesheetSet => _selectedStylesheetSet;
+  set selectedStylesheetSet(String$NULLABLE value) {
     _selectedStylesheetSet = value;
   }
 
@@ -102,13 +102,14 @@
    * `<input is="x-bar"></input>`
    *
    */
-  Function registerElement2(String tag, [Map options]) {
+  Function registerElement2(String tag, [Map$NULLABLE options]) {
     return _registerCustomElement(JS('', 'window'), this, tag, options);
   }
 
   /** *Deprecated*: use [registerElement] instead. */
   @deprecated
-  void register(String tag, Type customElementClass, {String extendsTag}) {
+  void register(String tag, Type customElementClass,
+      {String$NULLABLE extendsTag}) {
     return registerElement(tag, customElementClass, extendsTag: extendsTag);
   }
 
@@ -153,7 +154,8 @@
   ///
   /// If the type is not a direct subclass of HtmlElement then the extendsTag
   /// parameter must be provided.
-  ElementUpgrader createElementUpgrader(Type type, {String extendsTag}) {
+  ElementUpgrader createElementUpgrader(Type type,
+      {String$NULLABLE extendsTag}) {
     return new _JSElementUpgrader(this, type, extendsTag);
   }
 }
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index 9f2cb3f..fb81a0a 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -28,7 +28,7 @@
     ButtonInputElement {
 
   factory InputElement({String$NULLABLE type}) {
-    InputElement e = document.createElement("input");
+    InputElement e = document.createElement("input") $#NULLSAFECAST(as InputElement);
     if (type != null) {
       try {
         // IE throws an exception for unknown types.
@@ -50,6 +50,27 @@
  * Exposes the functionality common between all InputElement types.
  */
 abstract class InputElementBase implements Element {
+$if NNBD
+  // These fields here and below are overridden by generated code and therefore
+  // can't be nullable. Opted to translate these fields to getters/setters.
+  bool get autofocus;
+  set autofocus(bool value);
+
+  bool get disabled;
+  set disabled(bool value);
+
+  bool get incremental;
+  set incremental(bool value);
+
+  bool get indeterminate;
+  set indeterminate(bool value);
+
+  String get name;
+  set name(String value);
+
+  String get value;
+  set value(String value);
+$else
   bool autofocus;
 
   bool disabled;
@@ -58,16 +79,17 @@
 
   bool indeterminate;
 
-  List<Node> get labels;
-
   String name;
 
+  String value;
+$endif
+
+  List<Node> get labels;
+
   String get validationMessage;
 
   ValidityState get validity;
 
-  String value;
-
   bool get willValidate;
 
   bool checkValidity();
@@ -87,6 +109,28 @@
  * Base interface for all inputs which involve text editing.
  */
 abstract class TextInputElementBase implements InputElementBase {
+$if NNBD
+  String get autocomplete;
+  set autocomplete(String value);
+
+  int get maxLength;
+  set maxLength(int value);
+
+  String get pattern;
+  set pattern(String value);
+
+  String get placeholder;
+  set placeholder(String value);
+
+  bool get readOnly;
+  set readOnly(bool value);
+
+  bool get required;
+  set required(bool value);
+
+  int get size;
+  set size(int value);
+$else
   String autocomplete;
 
   int maxLength;
@@ -100,16 +144,17 @@
   bool required;
 
   int size;
+$endif
 
   void select();
 
-  String selectionDirection;
+  String$NULLABLE selectionDirection;
 
-  int selectionEnd;
+  int$NULLABLE selectionEnd;
 
-  int selectionStart;
+  int$NULLABLE selectionStart;
 
-  void setSelectionRange(int start, int end, [String direction]);
+  void setSelectionRange(int start, int end, [String$NULLABLE direction]);
 }
 
 /**
@@ -241,6 +286,19 @@
 
   Element$NULLABLE get list;
 
+$if NNBD
+  String get max;
+  set max(String value);
+
+  String get min;
+  set min(String value);
+
+  String get step;
+  set step(String value);
+
+  num get valueAsNumber;
+  set valueAsNumber(num value);
+$else
   String max;
 
   String min;
@@ -248,10 +306,11 @@
   String step;
 
   num valueAsNumber;
+$endif
 
-  void stepDown([int n]);
+  void stepDown([int$NULLABLE n]);
 
-  void stepUp([int n]);
+  void stepUp([int$NULLABLE n]);
 }
 
 /**
@@ -443,7 +502,7 @@
 
   bool required;
 
-  List<File> files;
+  List<File>$NULLABLE files;
 }
 
 /**
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
index 6f71be6..d53310c 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
@@ -28,14 +28,15 @@
     }
     var tbody = new Element.tag('tbody');
     this.children.add(tbody);
-    return tbody;
+    return tbody $#NULLSAFECAST(as TableSectionElement);
   }
 
   @JSName('createTBody')
   TableSectionElement _nativeCreateTBody() native;
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(
           html, validator: validator, treeSanitizer: treeSanitizer);
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
index 0b119f4..5d689c7 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
@@ -13,10 +13,12 @@
     return insertCell(-1);
   }
 
-  TableCellElement insertCell(int index) => _insertCell(index);
+  TableCellElement insertCell(int index) =>
+      _insertCell(index) $#NULLSAFECAST(as TableCellElement);
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(
           html, validator: validator, treeSanitizer: treeSanitizer);
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
index b7a08a6..0b3b665 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
@@ -13,10 +13,11 @@
     return insertRow(-1);
   }
 
-  TableRowElement insertRow(int index) => _insertRow(index);
+  TableRowElement insertRow(int index) => _insertRow(index) $#NULLSAFECAST(as TableRowElement);
 
   DocumentFragment createFragment(String html,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     if (Range.supportsCreateContextualFragment) {
       return super.createFragment(
           html, validator: validator, treeSanitizer: treeSanitizer);
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index 7fb61fe..ea670cc 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -17,7 +17,8 @@
    * * <https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin>
    */
   void setInnerHtml(String html,
-    {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+    {NodeValidator$NULLABLE validator,
+     NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     text = null;
     content.nodes.clear();
     var fragment = createFragment(
diff --git a/tools/dom/templates/html/impl/impl_HashChangeEvent.darttemplate b/tools/dom/templates/html/impl/impl_HashChangeEvent.darttemplate
index 34fb9f4..1a45ef3 100644
--- a/tools/dom/templates/html/impl/impl_HashChangeEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HashChangeEvent.darttemplate
@@ -7,8 +7,8 @@
 part of $LIBRARYNAME;
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-      {bool canBubble: true, bool cancelable: true, String oldUrl,
-      String newUrl}) {
+      {bool canBubble: true, bool cancelable: true, String$NULLABLE oldUrl,
+      String$NULLABLE newUrl}) {
     var options = {
       'canBubble' : canBubble,
       'cancelable' : cancelable,
diff --git a/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
index 4154659..e50db5d 100644
--- a/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
@@ -22,7 +22,7 @@
   }
 
   @JSName('continue')
-  void next([Object key]) {
+  void next([Object$NULLABLE key]) {
     if (key == null) {
       JS('void', '#.continue()', this);
     } else {
diff --git a/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
index 7a12b6c..25f431c 100644
--- a/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   ObjectStore createObjectStore(String name,
-      {keyPath, bool autoIncrement}) {
+      {keyPath, bool$NULLABLE autoIncrement}) {
     var options = {};
     if (keyPath != null) {
       options['keyPath'] = keyPath;
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 4fd732e..8a49bc8 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -16,8 +16,9 @@
   }
 
   Future<Database> open(String name,
-      {int version, void onUpgradeNeeded(VersionChangeEvent event),
-      void onBlocked(Event event)}) {
+      {int$NULLABLE version,
+      void onUpgradeNeeded(VersionChangeEvent event)$NULLABLE,
+      void onBlocked(Event event)$NULLABLE}) {
     if ((version == null) != (onUpgradeNeeded == null)) {
       return new Future.error(new ArgumentError(
           'version and onUpgradeNeeded must be specified together'));
@@ -43,7 +44,7 @@
   }
 
   Future<IdbFactory> deleteDatabase(String name,
-      {void onBlocked(Event e)}) {
+      {void onBlocked(Event e)$NULLABLE}) {
     try {
       var request = _deleteDatabase(name);
 
diff --git a/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
index 608f1bc..060b699 100644
--- a/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
@@ -41,8 +41,8 @@
    *
    * * [ObjectStore.openCursor]
    */
-  Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
-      bool autoAdvance}) {
+  Stream<CursorWithValue> openCursor({key, KeyRange$NULLABLE range,
+      String$NULLABLE direction, bool$NULLABLE autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
@@ -69,8 +69,8 @@
    *
    * * [ObjectStore.openCursor]
    */
-  Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
-      bool autoAdvance}) {
+  Stream<Cursor> openKeyCursor({key, KeyRange$NULLABLE range,
+      String$NULLABLE direction, bool$NULLABLE autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index 704d16e..638e458 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -90,8 +90,8 @@
    * must be done synchronously unless they are additional async requests to
    * the current transaction.
    */
-  Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
-      bool autoAdvance}) {
+  Stream<CursorWithValue> openCursor({key, KeyRange$NULLABLE range,
+      String$NULLABLE direction, bool$NULLABLE autoAdvance}) {
     var key_OR_range = null;
     if (key != null) {
       if (range != null) {
@@ -112,7 +112,8 @@
     return _cursorStreamFromResult(request, autoAdvance);
   }
 
-  Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+  Index createIndex(String name, keyPath, {bool$NULLABLE unique,
+      bool$NULLABLE multiEntry}) {
     var options = {};
     if (unique != null) {
       options['unique'] = unique;
@@ -130,7 +131,7 @@
    * Helper for iterating over cursors in a request.
    */
   static Stream<T> _cursorStreamFromResult<T extends Cursor>(Request request,
-      bool autoAdvance) {
+      bool$NULLABLE autoAdvance) {
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
diff --git a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
index 571ab6d2..3c690ac 100644
--- a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
@@ -8,9 +8,10 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-      {bool canBubble: false, bool cancelable: false, Object data,
-      String origin, String lastEventId,
-      Window source, List<MessagePort> messagePorts: const []}) {
+      {bool canBubble: false, bool cancelable: false, Object$NULLABLE data,
+      String$NULLABLE origin, String$NULLABLE lastEventId,
+      Window$NULLABLE source,
+      List<MessagePort> messagePorts: const []}) {
     if (source == null) {
       source = window;
     }
@@ -20,7 +21,7 @@
           type, canBubble, cancelable, data, origin, lastEventId, source,
           messagePorts);
     }
-    MessageEvent event = document._createEvent("MessageEvent");
+    MessageEvent event = document._createEvent("MessageEvent") $#NULLSAFECAST(as MessageEvent);
     event._initMessageEvent(type, canBubble, cancelable, data, origin,
         lastEventId, source, messagePorts);
     return event;
diff --git a/tools/dom/templates/html/impl/impl_MessagePort.darttemplate b/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
index 0dbf89b..7cfa87a 100644
--- a/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
@@ -8,8 +8,8 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
-  void addEventListener(String type, EventListener listener,
-      [bool useCapture]) {
+  void addEventListener(String type, EventListener$NULLABLE listener,
+      [bool$NULLABLE useCapture]) {
     // Messages posted to ports are initially paused, allowing listeners to be
     // setup, start() needs to be explicitly invoked to begin handling messages.
     if (type == 'message') {
diff --git a/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate b/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
index 46a1562..aa7fee1 100644
--- a/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
@@ -26,12 +26,12 @@
    * * If characterDataOldValue is true then characterData must be true.
    */
   void observe(Node target,
-               {bool childList,
-                bool attributes,
-                bool characterData,
-                bool subtree,
-                bool attributeOldValue,
-                bool characterDataOldValue,
+               {bool$NULLABLE childList,
+                bool$NULLABLE attributes,
+                bool$NULLABLE characterData,
+                bool$NULLABLE subtree,
+                bool$NULLABLE attributeOldValue,
+                bool$NULLABLE characterDataOldValue,
                 List<String>$NULLABLE attributeFilter}) {
 
     // Parse options into map of known type.
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index cfef9ae..8a4c1ce 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -42,7 +42,7 @@
       if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
         for (var i = 0, len = otherList.length; i < len; ++i) {
-          _this.append(otherList._this.firstChild);
+          _this.append(otherList._this.firstChild$NULLASSERT);
         }
       }
       return;
@@ -104,9 +104,9 @@
     // This implementation of removeWhere/retainWhere is more efficient
     // than the default in ListBase. Child nodes can be removed in constant
     // time.
-    Node child = _this.firstChild;
+    Node$NULLABLE child = _this.firstChild;
     while (child != null) {
-      Node nextChild = child.nextNode;
+      Node$NULLABLE nextChild = child.nextNode;
       if (test(child) == removeMatching) {
         _this._removeChild(child);
       }
@@ -203,8 +203,8 @@
     // TODO(jacobr): should we throw an exception if parent is already null?
     // TODO(vsm): Use the native remove when available.
     if (this.parentNode != null) {
-      final Node parent = this.parentNode;
-      parentNode._removeChild(this);
+      final Node parent = this.parentNode$NULLASSERT;
+      parent._removeChild(this);
     }
   }
 
@@ -213,11 +213,9 @@
    */
   Node replaceWith(Node otherNode) {
     try {
-      final Node parent = this.parentNode;
+      final Node parent = this.parentNode$NULLASSERT;
       parent._replaceChild(otherNode, this);
-    } catch (e) {
-
-    };
+    } catch (e) {}
     return this;
   }
 
@@ -237,7 +235,7 @@
 
       // Optimized route for copying between nodes.
       for (var i = 0, len = otherList.length; i < len; ++i) {
-        this.insertBefore(otherList._this.firstChild, refChild);
+        this.insertBefore(otherList._this.firstChild$NULLASSERT, refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -248,7 +246,7 @@
 
   void _clearChildren() {
     while (firstChild != null) {
-      _removeChild(firstChild);
+      _removeChild(firstChild$NULLASSERT);
     }
   }
 
@@ -256,7 +254,7 @@
    * Print out a String representation of this Node.
    */
   String toString() {
-    String value = nodeValue;  // Fetch DOM Node property once.
+    String$NULLABLE value = nodeValue;  // Fetch DOM Node property once.
     return value == null ? super.toString() : value;
   }
 
@@ -270,7 +268,11 @@
    */
   @Returns('NodeList')
   @Creates('NodeList')
+$if NNBD
+  List<Node> get childNodes => JS("NodeList", "#.childNodes", this);
+$else
   final List<Node> childNodes;
+$endif
 
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_Notification.darttemplate b/tools/dom/templates/html/impl/impl_Notification.darttemplate
index 5a3a5e1..d6e21cf 100644
--- a/tools/dom/templates/html/impl/impl_Notification.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Notification.darttemplate
@@ -6,8 +6,8 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
-  factory $CLASSNAME(String title, {String dir: null, String body: null,
-      String lang: null, String tag: null, String icon: null}) {
+  factory $CLASSNAME(String title, {String$NULLABLE dir, String$NULLABLE body,
+      String$NULLABLE lang, String$NULLABLE tag, String$NULLABLE icon}) {
 
     var parsedOptions = {};
     if (dir != null) parsedOptions['dir'] = dir;
diff --git a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
index 4af23ea..d89b44f 100644
--- a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
+++ b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
@@ -5,7 +5,7 @@
 part of $LIBRARYNAME;
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
-  factory $CLASSNAME(Map rtcIceServers, [Map mediaConstraints]) {
+  factory $CLASSNAME(Map rtcIceServers, [Map$NULLABLE mediaConstraints]) {
     var constructorName =
         JS('RtcPeerConnection', 'window[#]', 'RTCPeerConnection');
     if (mediaConstraints != null) {
@@ -39,7 +39,8 @@
   * Temporarily exposes _getStats and old getStats as getLegacyStats until Chrome fully supports
   * new getStats API.
   */
-  Future<RtcStatsResponse> getLegacyStats([MediaStreamTrack selector]) {
+  Future<RtcStatsResponse>
+      getLegacyStats([MediaStreamTrack$NULLABLE selector]) {
     var completer = new Completer<RtcStatsResponse>();
     _getStats((value) {
       completer.complete(value);
@@ -48,7 +49,8 @@
   }
   @JSName('getStats')
   Future _getStats(
-      [RtcStatsCallback successCallback, MediaStreamTrack selector]) native;
+      [RtcStatsCallback$NULLABLE successCallback,
+       MediaStreamTrack$NULLABLE selector]) native;
 
   static Future generateCertificate(/*AlgorithmIdentifier*/ keygenAlgorithm) =>
       JS('dynamic', 'generateCertificate(#)', keygenAlgorithm);
diff --git a/tools/dom/templates/html/impl/impl_Range.darttemplate b/tools/dom/templates/html/impl/impl_Range.darttemplate
index f420027..73d8d45 100644
--- a/tools/dom/templates/html/impl/impl_Range.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Range.darttemplate
@@ -10,7 +10,7 @@
   factory $CLASSNAME() => document.createRange();
 
   factory $CLASSNAME.fromPoint(Point point) =>
-      document._caretRangeFromPoint(point.x, point.y);
+      document._caretRangeFromPoint(point.x.toInt(), point.y.toInt());
 $!MEMBERS
 
   List<Rectangle> getClientRects() {
diff --git a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
index 2c4cd6a..9934ddb 100644
--- a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
@@ -37,9 +37,10 @@
   static final _START_TAG_REGEXP = new RegExp('<(\\w+)');
 
   factory $CLASSNAME.tag(String tag) =>
-      document.createElementNS("http://www.w3.org/2000/svg", tag);
+      document.createElementNS("http://www.w3.org/2000/svg", tag) $#NULLSAFECAST(as $CLASSNAME);
   factory $CLASSNAME.svg(String svg,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
 
     if (validator == null && treeSanitizer == null) {
       validator = new NodeValidatorBuilder.common()..allowSvg();
@@ -47,7 +48,7 @@
 
     final match = _START_TAG_REGEXP.firstMatch(svg);
     var parentElement;
-    if (match != null && match.group(1).toLowerCase() == 'svg') {
+    if (match != null && match.group(1)$NULLASSERT.toLowerCase() == 'svg') {
       parentElement = document.body;
     } else {
       parentElement = new SvgSvgElement();
@@ -69,14 +70,14 @@
 
   String get outerHtml {
     final container = new DivElement();
-    final SvgElement cloned = this.clone(true);
+    final SvgElement cloned = this.clone(true) $#NULLSAFECAST(as SvgElement);
     container.children.add(cloned);
     return container.innerHtml;
   }
 
   String get innerHtml {
     final container = new DivElement();
-    final SvgElement cloned = this.clone(true);
+    final SvgElement cloned = this.clone(true) $#NULLSAFECAST(as SvgElement);
     container.children.addAll(cloned.children);
     return container.innerHtml;
   }
@@ -86,7 +87,8 @@
   }
 
   DocumentFragment createFragment(String svg,
-      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
 
     if (treeSanitizer == null) {
       if (validator == null) {
@@ -105,7 +107,7 @@
     // The root is the <svg/> element, need to pull out the contents.
     var root = fragment.nodes.single;
     while (root.firstChild != null) {
-      svgFragment.append(root.firstChild);
+      svgFragment.append(root.firstChild$NULLASSERT);
     }
     return svgFragment;
   }
@@ -116,8 +118,9 @@
     throw new UnsupportedError("Cannot invoke insertAdjacentText on SVG.");
   }
 
-  void insertAdjacentHtml(String where, String text, {NodeValidator validator,
-      NodeTreeSanitizer treeSanitizer}) {
+  void insertAdjacentHtml(String where, String text,
+      {NodeValidator$NULLABLE validator,
+       NodeTreeSanitizer$NULLABLE treeSanitizer}) {
     throw new UnsupportedError("Cannot invoke insertAdjacentHtml on SVG.");
   }
 
diff --git a/tools/dom/templates/html/impl/impl_SVGSVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGSVGElement.darttemplate
index 6279a7e..8dbe6d6 100644
--- a/tools/dom/templates/html/impl/impl_SVGSVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGSVGElement.darttemplate
@@ -9,7 +9,7 @@
     final el = new SvgElement.tag("svg");
     // The SVG spec requires the version attribute to match the spec version
     el.attributes['version'] = "1.1";
-    return el;
+    return el $#NULLSAFECAST(as $CLASSNAME);
   }
 
 $!MEMBERS
diff --git a/tools/dom/templates/html/impl/impl_Storage.darttemplate b/tools/dom/templates/html/impl/impl_Storage.darttemplate
index ba1bf8b..fa0787a 100644
--- a/tools/dom/templates/html/impl/impl_Storage.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Storage.darttemplate
@@ -39,7 +39,8 @@
   // TODO(nweiz): update this when maps support lazy iteration
   bool containsValue(Object$NULLABLE value) => values.any((e) => e == value);
 
-  bool containsKey(Object$NULLABLE key) => _getItem(key) != null;
+  bool containsKey(Object$NULLABLE key) =>
+    _getItem(key $#NULLSAFECAST(as String)) != null;
 
   String$NULLABLE operator [](Object$NULLABLE key) => _getItem(key $#NULLSAFECAST(as String));
 
@@ -47,12 +48,12 @@
 
   String putIfAbsent(String key, String ifAbsent()) {
     if (!containsKey(key)) this[key] = ifAbsent();
-    return this[key];
+    return this[key] $#NULLSAFECAST(as String);
   }
 
   String$NULLABLE remove(Object$NULLABLE key) {
     final value = this[key];
-    _removeItem(key);
+    _removeItem(key $#NULLSAFECAST(as String));
     return value;
   }
 
@@ -63,7 +64,7 @@
       final key = _key(i);
       if (key == null) return;
 
-      f(key, this[key]);
+      f(key, this[key]$NULLASSERT);
     }
   }
 
diff --git a/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate b/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
index 551e2c7..64feb63 100644
--- a/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_StorageEvent.darttemplate
@@ -8,12 +8,13 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-    {bool canBubble: false, bool cancelable: false, String key, String oldValue,
-    String newValue, String url, Storage storageArea}) {
+    {bool canBubble: false, bool cancelable: false, String$NULLABLE key,
+    String$NULLABLE oldValue, String$NULLABLE newValue, String$NULLABLE url,
+    Storage$NULLABLE storageArea}) {
 
-    StorageEvent e = document._createEvent("StorageEvent");
-    e._initStorageEvent(type, canBubble, cancelable, key, oldValue,
-        newValue, url, storageArea);
+    StorageEvent e = document._createEvent("StorageEvent") $#NULLSAFECAST(as StorageEvent);
+    e._initStorageEvent(type, canBubble, cancelable, key, oldValue, newValue,
+        url, storageArea);
     return e;
   }
 $!MEMBERS
diff --git a/tools/dom/templates/html/impl/impl_TextEvent.darttemplate b/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
index 148c718..17889b4 100644
--- a/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TextEvent.darttemplate
@@ -8,11 +8,12 @@
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
   factory $CLASSNAME(String type,
-    {bool canBubble: false, bool cancelable: false, Window view, String data}) {
+    {bool canBubble: false, bool cancelable: false, Window$NULLABLE view,
+     String$NULLABLE data}) {
     if (view == null) {
       view = window;
     }
-    TextEvent e = document._createEvent("TextEvent");
+    TextEvent e = document._createEvent("TextEvent") $#NULLSAFECAST(as TextEvent);
     e._initTextEvent(type, canBubble, cancelable, view, data);
     return e;
   }
diff --git a/tools/dom/templates/html/impl/impl_TouchList.darttemplate b/tools/dom/templates/html/impl/impl_TouchList.darttemplate
index 56bcf1e..0005a6e 100644
--- a/tools/dom/templates/html/impl/impl_TouchList.darttemplate
+++ b/tools/dom/templates/html/impl/impl_TouchList.darttemplate
@@ -2,15 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 part of $LIBRARYNAME;
 
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$MIXINS$IMPLEMENTS {
-  /// NB: This constructor likely does not work as you might expect it to! This
-  /// constructor will simply fail (returning null) if you are not on a device
-  /// with touch enabled. See dartbug.com/8314.
-  // TODO(5760): createTouchList now uses varargs.
-  factory $CLASSNAME() => null;//document._createTouchList();
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
index 405d06d..ad5f47a 100644
--- a/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_UIEvent.darttemplate
@@ -14,12 +14,12 @@
   // Contrary to JS, we default canBubble and cancelable to true, since that's
   // what people want most of the time anyway.
   factory $CLASSNAME(String type,
-      {Window view, int detail: 0, bool canBubble: true,
+      {Window$NULLABLE view, int detail: 0, bool canBubble: true,
       bool cancelable: true}) {
     if (view == null) {
       view = window;
     }
-    UIEvent e = document._createEvent("UIEvent");
+    UIEvent e = document._createEvent("UIEvent") $#NULLSAFECAST(as UIEvent);
     e._initUIEvent(type, canBubble, cancelable, view, detail);
     return e;
   }
diff --git a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
index 0768608..43b0062 100644
--- a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
@@ -7,12 +7,13 @@
 $(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
 
   factory WheelEvent(String type,
-      {Window view, num deltaX: 0, num deltaY: 0, num deltaZ: 0,
+      {Window$NULLABLE view, num deltaX: 0, num deltaY: 0, num deltaZ: 0,
       int deltaMode: 0,
       int detail: 0, int screenX: 0, int screenY: 0, int clientX: 0,
       int clientY: 0, int button: 0, bool canBubble: true,
       bool cancelable: true, bool ctrlKey: false, bool altKey: false,
-      bool shiftKey: false, bool metaKey: false, EventTarget relatedTarget}) {
+      bool shiftKey: false, bool metaKey: false,
+      EventTarget$NULLABLE relatedTarget}) {
 
     var options = {
       'view': view,
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 9553f4a..5898c0c 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -55,7 +55,7 @@
    * * [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window.open)
    *   from MDN.
    */
-  WindowBase open(String url, String name, [String options]) {
+  WindowBase open(String url, String name, [String$NULLABLE options]) {
     if (options == null) {
       return _DOMWindowCrossFrame._createSafe(_open2(url, name));
     } else {
@@ -219,7 +219,7 @@
    *   from W3C.
    */
   void moveTo(Point p) {
-    _moveTo(p.x, p.y);
+    _moveTo(p.x.toInt(), p.y.toInt());
   }
 
   @JSName('openDatabase')
@@ -228,7 +228,7 @@
   @Creates('SqlDatabase')
   SqlDatabase openDatabase(
       String name, String version, String displayName, int estimatedSize,
-      [DatabaseCallback creationCallback]) {
+      [DatabaseCallback$NULLABLE creationCallback]) {
     var db;
     if (creationCallback == null)
       db = _openDatabase(name, version, displayName, estimatedSize);
@@ -257,7 +257,7 @@
    */
   int get scrollX => JS<bool>('bool', '("scrollX" in #)', this) ?
       JS<num>('num', '#.scrollX', this).round() :
-      document.documentElement.scrollLeft;
+      document.documentElement$NULLASSERT.scrollLeft;
 
   /**
    * The distance this window has been scrolled vertically.
@@ -271,13 +271,19 @@
    */
   int get scrollY => JS<bool>('bool', '("scrollY" in #)', this) ?
       JS<num>('num', '#.scrollY', this).round() :
-      document.documentElement.scrollTop;
+      document.documentElement$NULLASSERT.scrollTop;
 }
 
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
   String _returnValue;
 
-  _BeforeUnloadEvent(Event base): super(base);
+$if NNBD
+  _BeforeUnloadEvent(Event base)
+    : _returnValue = '',
+      super(base);
+$else
+  _BeforeUnloadEvent(Event base) : super(base);
+$endif
 
   String get returnValue => _returnValue;
 
@@ -297,7 +303,7 @@
 
   const _BeforeUnloadEventStreamProvider(this._eventType);
 
-  Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
+  Stream<BeforeUnloadEvent> forTarget(EventTarget$NULLABLE e, {bool useCapture: false}) {
     // Specify the generic type for EventStream only in dart2js.
     var stream = new _EventStream<BeforeUnloadEvent>(e, _eventType, useCapture);
     var controller = new StreamController<BeforeUnloadEvent>(sync: true);
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 97932b2..eab360a 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -104,9 +104,9 @@
    * * [request]
    */
   static Future<HttpRequest> postFormData(String url, Map<String, String> data,
-      {bool withCredentials, String responseType,
-      Map<String, String> requestHeaders,
-      void onProgress(ProgressEvent e)}) {
+      {bool$NULLABLE withCredentials, String$NULLABLE responseType,
+      Map<String, String>$NULLABLE requestHeaders,
+      void onProgress(ProgressEvent e)$NULLABLE}) {
 
     var parts = [];
     data.forEach((key, value) {
@@ -182,9 +182,10 @@
    * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access_authentication).
    */
   static Future<HttpRequest> request(String url,
-      {String method, bool withCredentials, String responseType,
-      String mimeType, Map<String, String> requestHeaders, sendData,
-      void onProgress(ProgressEvent e)}) {
+      {String$NULLABLE method, bool$NULLABLE withCredentials,
+      String$NULLABLE responseType, String$NULLABLE mimeType,
+      Map<String, String>$NULLABLE requestHeaders, sendData,
+      void onProgress(ProgressEvent e)$NULLABLE}) {
     var completer = new Completer<HttpRequest>();
 
     var xhr = new HttpRequest();
@@ -288,7 +289,7 @@
    * cross-origin support is not required then [request] should be used instead.
    */
   static Future<String> requestCrossOrigin(String url,
-      {String method, String sendData}) {
+      {String$NULLABLE method, String$NULLABLE sendData}) {
     if (supportsCrossOrigin) {
       return request(url, method: method, sendData: sendData).then((xhr) {
         return xhr.responseText;
@@ -302,7 +303,7 @@
     JS('', '#.open(#, #)', xhr, method, url);
     JS('', '#.onload = #', xhr, convertDartClosureToJS((e) {
       var response = JS('String', '#.responseText', xhr);
-      completer.complete(response);
+      completer.complete(response $#NULLSAFECAST(as FutureOr<String>$NULLABLE));
     }, 1));
     JS('', '#.onerror = #', xhr, convertDartClosureToJS((e) {
       completer.completeError(e);
@@ -375,7 +376,8 @@
    * `open` method is intended only for more complex HTTP requests where
    * finer-grained control is needed.
    */
-  void open(String method, String url, {bool async, String user, String password}) native;
+  void open(String method, String url, {bool$NULLABLE async,
+      String$NULLABLE user, String$NULLABLE password}) native;
 
 $!MEMBERS
 }
diff --git a/tools/utils.py b/tools/utils.py
index b624e0d..7fa9d73 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -272,12 +272,14 @@
     'macos': os.path.join('xcodebuild'),
 }
 
+# Note: gn expects these to be lower case.
 ARCH_FAMILY = {
     'ia32': 'ia32',
     'x64': 'ia32',
     'arm': 'arm',
     'armv6': 'arm',
     'arm64': 'arm',
+    'arm_x64': 'arm',
     'simarm': 'ia32',
     'simarmv6': 'ia32',
     'simarm64': 'ia32',
diff --git a/utils/pub/BUILD.gn b/utils/pub/BUILD.gn
index b2f724c..6459f59 100644
--- a/utils/pub/BUILD.gn
+++ b/utils/pub/BUILD.gn
@@ -6,5 +6,10 @@
 
 application_snapshot("pub") {
   main_dart = "../../third_party/pkg/pub/bin/pub.dart"
-  training_args = [ "--help" ]
+
+  # TODO (40486) : Remove the trace option once this issue is fixed.
+  training_args = [
+    "--trace",
+    "--help",
+  ]
 }