Version 2.14.0-341.0.dev

Merge commit 'be212c94ae5b7b0999650a29a83f4be3d6a8c6d1' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 546ad7a..c3b657c 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -797,7 +797,7 @@
       "name": "webkit_inspection_protocol",
       "rootUri": "../third_party/pkg/webkit_inspection_protocol",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "yaml",
diff --git a/DEPS b/DEPS
index a11c660..f498427 100644
--- a/DEPS
+++ b/DEPS
@@ -73,7 +73,7 @@
 
   # Revisions of /third_party/* dependencies.
   "args_rev": "d8fea36c10ef96797be02e3d132d572445cd86f4",
-  "async_rev": "8193eac211905cf33ae1f514022fdbd843836be5",
+  "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
   "bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
   "benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
   "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
@@ -103,7 +103,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
+  "dart_style_rev": "06bfd19593ed84dd288f67e02c6a753e6516288a",
 
   "dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
   "devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
@@ -146,7 +146,7 @@
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
-  "shelf_static_rev": "fb6b7d0ee4ad936a84e503ae6b3703cc99e61d52",
+  "shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
   "shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
   "shelf_proxy_tag": "v1.0.0",
   "shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
@@ -174,7 +174,7 @@
   "web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
   "webdev_rev": "b0aae7b6944d484722e6af164abedd864a2a0afa",
-  "webkit_inspection_protocol_rev": "6b15729292d030f2e5c5861022da4c5a4c11961c",
+  "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
   "yaml_rev": "b4c4411631bda556ce9a45af1ab0eecaf9f3ac53",
   "zlib_rev": "bf44340d1b6be1af8950bbdf664fec0cf5a831cc",
   "crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
diff --git a/build/fuchsia/dart.cmx b/build/fuchsia/dart.cmx
index d57d9ac..0bd0e668 100644
--- a/build/fuchsia/dart.cmx
+++ b/build/fuchsia/dart.cmx
@@ -1,27 +1,28 @@
 {
-  "program": {
-    "binary": "exe.stripped/dart"
-  },
-  "sandbox": {
-    "features": [
-      "config-data",
-      "deprecated-ambient-replace-as-executable",
-      "root-ssl-certificates",
-      "isolated-cache-storage",
-      "isolated-persistent-storage",
-      "isolated-temp"
-    ],
-    "services": [
-      "fuchsia.deprecatedtimezone.Timezone",
-      "fuchsia.device.NameProvider",
-      "fuchsia.feedback.CrashReporter",
-      "fuchsia.intl.PropertyProvider",
-      "fuchsia.logger.LogSink",
-      "fuchsia.net.NameLookup",
-      "fuchsia.posix.socket.Provider",
-      "fuchsia.sysmem.Allocator",
-      "fuchsia.timezone.Timezone",
-      "fuchsia.tracing.provider.Registry"
-    ]
-  }
+    "program": {
+        "binary": "exe.stripped/dart"
+    },
+    "sandbox": {
+        "features": [
+            "config-data",
+            "deprecated-ambient-replace-as-executable",
+            "isolated-cache-storage",
+            "isolated-persistent-storage",
+            "isolated-temp",
+            "root-ssl-certificates"
+        ],
+        "services": [
+            "fuchsia.deprecatedtimezone.Timezone",
+            "fuchsia.device.NameProvider",
+            "fuchsia.feedback.CrashReporter",
+            "fuchsia.intl.PropertyProvider",
+            "fuchsia.logger.LogSink",
+            "fuchsia.net.NameLookup",
+            "fuchsia.net.name.Lookup",
+            "fuchsia.posix.socket.Provider",
+            "fuchsia.sysmem.Allocator",
+            "fuchsia.timezone.Timezone",
+            "fuchsia.tracing.provider.Registry"
+        ]
+    }
 }
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ea1b32..71e8148 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.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:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/source/line_info.dart';
@@ -17,6 +19,14 @@
   CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
 }
 
+class CheckNameResponse {
+  final LineInfo lineInfo;
+  final RefactoringStatus status;
+  final String oldName;
+
+  CheckNameResponse(this.lineInfo, this.status, this.oldName);
+}
+
 class CiderRenameComputer {
   final FileResolver _fileResolver;
 
@@ -51,6 +61,32 @@
     return null;
   }
 
+  CheckNameResponse? checkNewName(String filePath, int line, int column, String name) {
+    var resolvedUnit = _fileResolver.resolve(path: filePath);
+    var lineInfo = resolvedUnit.lineInfo;
+    var offset = lineInfo.getOffsetOfLine(line) + column;
+
+    var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+    var element = getElementOfNode(node);
+
+    if (node == null || element == null) {
+      return null;
+    }
+
+    RefactoringStatus? status;
+    if (element is LocalVariableElement) {
+      status = validateVariableName(name);
+    } else if (element is ParameterElement) {
+      status = validateParameterName(name);
+    } else if (element is FunctionElement) {
+      status = validateFunctionName(name);
+    }
+    if (status == null){
+      return null;
+    }
+    return CheckNameResponse(lineInfo, status, element.displayName);
+  }
+
   bool _canRenameElement(Element element) {
     if (element is PropertyAccessorElement) {
       element = element.variable;
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 31c96d5..028aaea 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -107,6 +107,65 @@
     expect(refactor.refactoringElement.offset, _correctionContext.offset);
   }
 
+  void test_checkName_function() {
+    var result = _checkName(r'''
+int ^foo() => 2;
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'foo');
+  }
+
+  void test_checkName_local() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_local_invalid() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'Aa');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 1);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_parameter() {
+    var result = _checkName(r'''
+void foo(String ^a) {
+  var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  CheckNameResponse? _checkName(String content, String newName) {
+    _updateFile(content);
+
+    return CiderRenameComputer(
+      fileResolver,
+    ).checkNewName(
+      convertPath(testPath),
+      _correctionContext.line,
+      _correctionContext.character,
+      newName,
+    );
+  }
+
   CanRenameResponse? _compute(String content) {
     _updateFile(content);
 
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 771756b..57ecf0f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.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.
 
+// @dart=2.12
+
 library dart2js.cmdline.options;
 
 /// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index dc97091..5859d8e 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.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.
 
+// @dart=2.12
+
 // TODO(johnniwinther): Add a test that ensure that this library doesn't depend
 // on the dart2js internals.
 library compiler.src.kernel.dart2js_target;
@@ -78,9 +80,7 @@
   @override
   final String name;
 
-  final CompilerOptions options;
-
-  Map<String, ir.Class> _nativeClasses;
+  final CompilerOptions? options;
 
   Dart2jsTarget(this.name, this.flags, {this.options});
 
@@ -89,7 +89,7 @@
 
   @override
   int get enabledLateLowerings =>
-      (options != null && options.experimentLateInstanceVariables)
+      (options != null && options!.experimentLateInstanceVariables)
           ? LateLowering.none
           : _enabledLateLowerings;
 
@@ -111,7 +111,7 @@
   int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
 
   @override
-  List<String> get extraRequiredLibraries => _requiredLibraries[name];
+  List<String> get extraRequiredLibraries => _requiredLibraries[name]!;
 
   @override
   List<String> get extraIndexedLibraries => const [
@@ -151,12 +151,12 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<ir.Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void logger(String msg),
-      ChangedStructureNotifier changedStructureNotifier}) {
-    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
+    var nativeClasses = JsInteropChecks.getNativeClasses(component);
     var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
     for (var library in libraries) {
       // TODO (rileyporter): Merge js_util optimizations with other lowerings
@@ -165,7 +165,7 @@
       JsInteropChecks(
               coreTypes,
               diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
-              _nativeClasses)
+              nativeClasses)
           .visitLibrary(library);
     }
     lowering.transformLibraries(libraries, coreTypes, hierarchy, options);
@@ -192,7 +192,7 @@
     }
     return new ir.StaticInvocation(
         coreTypes.index
-            .getTopLevelMember('dart:core', '_createInvocationMirror'),
+            .getTopLevelProcedure('dart:core', '_createInvocationMirror'),
         new ir.Arguments(<ir.Expression>[
           new ir.StringLiteral(name)..fileOffset = offset,
           new ir.ListLiteral(
@@ -282,7 +282,7 @@
   @override
   final bool supportsUnevaluatedConstants;
 
-  const Dart2jsConstantsBackend({this.supportsUnevaluatedConstants});
+  const Dart2jsConstantsBackend({required this.supportsUnevaluatedConstants});
 
   @override
   NumberSemantics get numberSemantics => NumberSemantics.js;
diff --git a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
index 246429e..1d24a30 100644
--- a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
+++ b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.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.
 
+// @dart=2.12
+
 const int invocationMirrorMethodKind = 0;
 const int invocationMirrorGetterKind = 1;
 const int invocationMirrorSetterKind = 2;
diff --git a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
index ebc00ae..87ad9f3 100644
--- a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.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.
 
+// @dart=2.12
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart';
@@ -26,10 +28,6 @@
   TreeNode transformStaticInvocation(
       StaticInvocation invocation, Member contextMember) {
     final target = invocation.target;
-    if (target == null) {
-      return invocation;
-    }
-
     final transformer = transformers[target];
     if (transformer != null) {
       return transformer(invocation, contextMember);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
index 210bbcb..212aac6 100644
--- a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.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.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/type_algebra.dart';
@@ -11,9 +13,9 @@
 class _Reader {
   final Procedure _procedure;
   final FunctionType _type;
-  FunctionType _typeWithoutTypeParameters;
+  late final FunctionType _typeWithoutTypeParameters;
 
-  _Reader(this._procedure) : _type = _procedure.getterType {
+  _Reader(this._procedure) : _type = _procedure.getterType as FunctionType {
     _typeWithoutTypeParameters = _type.withoutTypeParameters;
   }
 }
@@ -31,7 +33,8 @@
 
   // Each map contains the mapping from late local variables to cells for a
   // given function scope. All late local variables are lowered to cells.
-  final List<Map<VariableDeclaration, VariableDeclaration>> _variableCells = [];
+  final List<Map<VariableDeclaration, VariableDeclaration>?> _variableCells =
+      [];
 
   // Uninitialized late static fields are lowered to cells.
   final Map<Field, Field> _fieldCells = {};
@@ -44,9 +47,9 @@
   // [Reference] to its [Field].
   final Map<Procedure, Field> _getterToField = {};
 
-  Member _contextMember;
+  Member? _contextMember;
 
-  LateLowering(this._coreTypes, CompilerOptions _options)
+  LateLowering(this._coreTypes, CompilerOptions? _options)
       : _omitLateNames = _options?.omitLateNames ?? false,
         _lowerInstanceVariables =
             _options?.experimentLateInstanceVariables ?? false,
@@ -55,7 +58,7 @@
         _readInitialized = _Reader(_coreTypes.initializedCellRead),
         _readInitializedFinal = _Reader(_coreTypes.initializedCellReadFinal);
 
-  Nullability get nonNullable => _contextMember.enclosingLibrary.nonNullable;
+  Nullability get nonNullable => _contextMember!.enclosingLibrary.nonNullable;
 
   bool _shouldLowerVariable(VariableDeclaration variable) => variable.isLate;
 
@@ -73,7 +76,7 @@
 
   String _mangleFieldName(Field field) {
     assert(_shouldLowerInstanceField(field));
-    Class cls = field.parent;
+    Class cls = field.enclosingClass!;
     return '_#${cls.name}#${field.name.text}';
   }
 
@@ -81,7 +84,7 @@
     List<Reference> additionalExports = library.additionalExports;
     Set<Reference> newExports = {};
     additionalExports.removeWhere((Reference reference) {
-      Field cell = _fieldCells[reference.node];
+      Field? cell = _fieldCells[reference.node];
       if (cell == null) return false;
       newExports.add(cell.getterReference);
       return true;
@@ -123,7 +126,7 @@
           Arguments([name, initializer])..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
 
-  StringLiteral _nameLiteral(String name, int fileOffset) =>
+  StringLiteral _nameLiteral(String? name, int fileOffset) =>
       StringLiteral(name ?? '')..fileOffset = fileOffset;
 
   InstanceInvocation _callReader(
@@ -138,7 +141,8 @@
         interfaceTarget: procedure,
         functionType:
             Substitution.fromPairs(reader._type.typeParameters, typeArguments)
-                .substituteType(reader._typeWithoutTypeParameters))
+                    .substituteType(reader._typeWithoutTypeParameters)
+                as FunctionType)
       ..fileOffset = fileOffset;
   }
 
@@ -161,7 +165,7 @@
     _variableCells.removeLast();
   }
 
-  VariableDeclaration _lookupVariableCell(VariableDeclaration variable) {
+  VariableDeclaration? _lookupVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerVariable(variable));
     for (final scope in _variableCells) {
       if (scope == null) continue;
@@ -190,7 +194,7 @@
   VariableDeclaration _uninitializedVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerUninitializedVariable(variable));
     int fileOffset = variable.fileOffset;
-    String name = variable.name;
+    String? name = variable.name;
     final cell = VariableDeclaration(name,
         initializer:
             _callCellConstructor(_nameLiteral(name, fileOffset), fileOffset),
@@ -213,11 +217,11 @@
   VariableDeclaration _initializedVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerInitializedVariable(variable));
     int fileOffset = variable.fileOffset;
-    String name = variable.name;
+    String? name = variable.name;
     final cell = VariableDeclaration(name,
         initializer: _callInitializedCellConstructor(
             _nameLiteral(name, fileOffset),
-            _initializerClosure(variable.initializer, variable.type),
+            _initializerClosure(variable.initializer!, variable.type),
             fileOffset),
         type: InterfaceType(_coreTypes.initializedCellClass, nonNullable),
         isFinal: true)
@@ -226,7 +230,7 @@
   }
 
   TreeNode transformVariableDeclaration(
-      VariableDeclaration variable, Member contextMember) {
+      VariableDeclaration variable, Member? contextMember) {
     _contextMember = contextMember;
 
     if (!_shouldLowerVariable(variable)) return variable;
@@ -309,8 +313,8 @@
     Name name = field.name;
     String nameText = name.text;
     DartType type = field.type;
-    Expression initializer = field.initializer;
-    Class enclosingClass = field.enclosingClass;
+    Expression? initializer = field.initializer;
+    Class enclosingClass = field.enclosingClass!;
 
     Name mangledName = Name(_mangleFieldName(field), field.enclosingLibrary);
     Field backingField = Field.mutable(mangledName,
@@ -436,7 +440,7 @@
     VariableGet setterValueRead() =>
         VariableGet(setterValue)..fileOffset = fileOffset;
 
-    Statement setterBody() {
+    Statement? setterBody() {
       if (!field.isFinal) {
         // The lowered setter for `late T field;` and `late T field = e;` is
         //
@@ -470,7 +474,7 @@
       }
     }
 
-    Statement body = setterBody();
+    Statement? body = setterBody();
     if (body != null) {
       Procedure setter = Procedure(
           name,
@@ -506,17 +510,14 @@
     // getter for the backing field.
     // TODO(fishythefish): Clean this up when [FieldInitializer] maintains a
     // correct [Reference] to its [Field].
-    NamedNode node = initializer.fieldReference.node;
-    assert(node != null);
+    NamedNode node = initializer.fieldReference.node!;
     Field backingField;
     if (node is Field) {
       if (!_shouldLowerInstanceField(node)) return initializer;
       backingField = _backingInstanceField(node);
     } else {
-      backingField = _getterToField[node];
+      backingField = _getterToField[node]!;
     }
-    assert(backingField != null);
-
     return FieldInitializer(backingField, initializer.value)
       ..fileOffset = initializer.fileOffset;
   }
diff --git a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
index c315199..7df3d66 100644
--- a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.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.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
@@ -26,11 +28,11 @@
 
   ListFactorySpecializer(this.coreTypes, this.hierarchy)
       : _listGenerateFactory =
-            coreTypes.index.getMember('dart:core', 'List', 'generate'),
+            coreTypes.index.getProcedure('dart:core', 'List', 'generate'),
         _arrayAllocateFixedFactory = coreTypes.index
-            .getMember('dart:_interceptors', 'JSArray', 'allocateFixed'),
+            .getProcedure('dart:_interceptors', 'JSArray', 'allocateFixed'),
         _arrayAllocateGrowableFactory = coreTypes.index
-            .getMember('dart:_interceptors', 'JSArray', 'allocateGrowable'),
+            .getProcedure('dart:_interceptors', 'JSArray', 'allocateGrowable'),
         _jsArrayClass =
             coreTypes.index.getClass('dart:_interceptors', 'JSArray'),
         _intClass = coreTypes.index.getClass('dart:core', 'int') {
@@ -42,17 +44,14 @@
     });
   }
 
-  Procedure _intPlus;
-  Procedure get intPlus =>
-      _intPlus ??= hierarchy.getInterfaceMember(_intClass, Name('+'));
+  late final Procedure intPlus =
+      hierarchy.getInterfaceMember(_intClass, Name('+')) as Procedure;
 
-  Procedure _intLess;
-  Procedure get intLess =>
-      _intLess ??= hierarchy.getInterfaceMember(_intClass, Name('<'));
+  late final Procedure intLess =
+      hierarchy.getInterfaceMember(_intClass, Name('<')) as Procedure;
 
-  Procedure _jsArrayIndexSet;
-  Procedure get jsArrayIndexSet => _jsArrayIndexSet ??=
-      hierarchy.getInterfaceMember(_jsArrayClass, Name('[]='));
+  late final Procedure jsArrayIndexSet =
+      hierarchy.getInterfaceMember(_jsArrayClass, Name('[]=')) as Procedure;
 
   /// Replace calls to `List.generate(length, (i) => e)` with an expansion
   ///
@@ -74,7 +73,7 @@
     assert(args.positional.length == 2);
     final length = args.positional[0];
     final generator = args.positional[1];
-    final bool growable =
+    final bool? growable =
         _getConstantNamedOptionalArgument(args, 'growable', true);
     if (growable == null) return node;
 
@@ -90,18 +89,18 @@
 
     // If the length is a constant, use the constant directly so that the
     // inferrer can see the constant length.
-    int /*?*/ lengthConstant = _getLengthArgument(args);
-    VariableDeclaration lengthVariable;
+    int? lengthConstant = _getLengthArgument(args);
+    VariableDeclaration? lengthVariable;
 
     Expression getLength() {
       if (lengthConstant != null) return IntLiteral(lengthConstant);
       lengthVariable ??= VariableDeclaration('_length',
           initializer: length, isFinal: true, type: intType)
         ..fileOffset = node.fileOffset;
-      return VariableGet(lengthVariable)..fileOffset = node.fileOffset;
+      return VariableGet(lengthVariable!)..fileOffset = node.fileOffset;
     }
 
-    TreeNode allocation = StaticInvocation(
+    Expression allocation = StaticInvocation(
         growable ? _arrayAllocateGrowableFactory : _arrayAllocateFixedFactory,
         Arguments(
           [getLength()],
@@ -122,11 +121,8 @@
       initializer: IntLiteral(0),
       type: intType,
     )..fileOffset = node.fileOffset;
-    indexVariable.fileOffset = (generator as FunctionExpression)
-        .function
-        .positionalParameters
-        .first
-        .fileOffset;
+    indexVariable.fileOffset =
+        generator.function.positionalParameters.first.fileOffset;
 
     final loop = ForStatement(
       // initializers: _i = 0
@@ -138,7 +134,7 @@
         Name('<'),
         Arguments([getLength()]),
         interfaceTarget: intLess,
-        functionType: intLess.getterType,
+        functionType: intLess.getterType as FunctionType,
       ),
       // updates: _i++
       [
@@ -164,7 +160,7 @@
 
     return BlockExpression(
       Block([
-        if (lengthVariable != null) lengthVariable,
+        if (lengthVariable != null) lengthVariable!,
         listVariable,
         loop,
       ]),
@@ -185,7 +181,7 @@
 
   /// Returns constant value of the first argument in [args], or null if it is
   /// not a constant.
-  int /*?*/ _getLengthArgument(Arguments args) {
+  int? _getLengthArgument(Arguments args) {
     if (args.positional.length < 1) return null;
     final value = args.positional.first;
     if (value is IntLiteral) {
@@ -202,7 +198,7 @@
   /// Returns constant value of the only named optional argument in [args], or
   /// null if it is not a bool constant. Returns [defaultValue] if optional
   /// argument is not passed. Argument is asserted to have the given [name].
-  bool /*?*/ _getConstantNamedOptionalArgument(
+  bool? _getConstantNamedOptionalArgument(
       Arguments args, String name, bool defaultValue) {
     if (args.named.isEmpty) {
       return defaultValue;
@@ -224,15 +220,15 @@
   /// Choose a name for the `_list` temporary. If the `List.generate` expression
   /// is an initializer for a variable, use that name so that dart2js can try to
   /// use one JavaScript variable with the source name for 'both' variables.
-  String _listNameFromContext(Expression node) {
-    TreeNode parent = node.parent;
+  String? _listNameFromContext(Expression node) {
+    TreeNode? parent = node.parent;
     if (parent is VariableDeclaration) return parent.name;
     return '_list';
   }
 
   String _indexNameFromContext(FunctionExpression generator) {
     final function = generator.function;
-    String /*?*/ candidate = function.positionalParameters.first.name;
+    String? candidate = function.positionalParameters.first.name;
     if (candidate == null || candidate == '' || candidate == '_') return '_i';
     return candidate;
   }
@@ -246,8 +242,8 @@
   final int constructorFileOffset;
   final VariableDeclaration listVariable;
   final FunctionNode function;
-  VariableDeclaration argument;
-  VariableDeclaration parameter;
+  late final VariableDeclaration argument;
+  late final VariableDeclaration parameter;
   int functionNestingLevel = 0;
 
   ListGenerateLoopBodyInliner(this.listFactorySpecializer,
@@ -298,7 +294,7 @@
   }
 
   Statement run() {
-    final body = cloneInContext(function.body);
+    Statement body = cloneInContext(function.body!);
     return Block([parameter, body]);
   }
 
@@ -335,9 +331,11 @@
             value,
           ]),
           interfaceTarget: listFactorySpecializer.jsArrayIndexSet,
-          functionType: Substitution.fromInterfaceType(listVariable.type)
-              .substituteType(
-                  listFactorySpecializer.jsArrayIndexSet.getterType))
+          functionType:
+              Substitution.fromInterfaceType(listVariable.type as InterfaceType)
+                      .substituteType(
+                          listFactorySpecializer.jsArrayIndexSet.getterType)
+                  as FunctionType)
         ..isInvariant = true
         ..isBoundsSafe = true
         ..fileOffset = constructorFileOffset,
@@ -355,7 +353,7 @@
 
   @override
   VariableDeclaration getVariableClone(VariableDeclaration variable) {
-    VariableDeclaration clone = super.getVariableClone(variable);
+    VariableDeclaration? clone = super.getVariableClone(variable);
     return clone ?? variable;
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index e9cad5b..e04314b 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.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.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -16,7 +18,7 @@
 /// Each transformation is applied locally to AST nodes of certain types after
 /// transforming children nodes.
 void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
-    ClassHierarchy hierarchy, CompilerOptions options) {
+    ClassHierarchy hierarchy, CompilerOptions? options) {
   final transformer = _Lowering(coreTypes, hierarchy, options);
   libraries.forEach(transformer.visitLibrary);
 
@@ -31,10 +33,10 @@
   final FactorySpecializer factorySpecializer;
   final LateLowering _lateLowering;
 
-  Member _currentMember;
+  Member? _currentMember;
 
   _Lowering(
-      CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions _options)
+      CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions? _options)
       : factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
         _lateLowering = LateLowering(coreTypes, _options);
 
@@ -51,7 +53,7 @@
   @override
   TreeNode visitStaticInvocation(StaticInvocation node) {
     node.transformChildren(this);
-    return factorySpecializer.transformStaticInvocation(node, _currentMember);
+    return factorySpecializer.transformStaticInvocation(node, _currentMember!);
   }
 
   @override
@@ -71,37 +73,37 @@
   @override
   TreeNode visitVariableGet(VariableGet node) {
     node.transformChildren(this);
-    return _lateLowering.transformVariableGet(node, _currentMember);
+    return _lateLowering.transformVariableGet(node, _currentMember!);
   }
 
   @override
   TreeNode visitVariableSet(VariableSet node) {
     node.transformChildren(this);
-    return _lateLowering.transformVariableSet(node, _currentMember);
+    return _lateLowering.transformVariableSet(node, _currentMember!);
   }
 
   @override
   TreeNode visitField(Field node) {
     _currentMember = node;
     node.transformChildren(this);
-    return _lateLowering.transformField(node, _currentMember);
+    return _lateLowering.transformField(node, _currentMember!);
   }
 
   @override
   TreeNode visitFieldInitializer(FieldInitializer node) {
     node.transformChildren(this);
-    return _lateLowering.transformFieldInitializer(node, _currentMember);
+    return _lateLowering.transformFieldInitializer(node, _currentMember!);
   }
 
   @override
   TreeNode visitStaticGet(StaticGet node) {
     node.transformChildren(this);
-    return _lateLowering.transformStaticGet(node, _currentMember);
+    return _lateLowering.transformStaticGet(node, _currentMember!);
   }
 
   @override
   TreeNode visitStaticSet(StaticSet node) {
     node.transformChildren(this);
-    return _lateLowering.transformStaticSet(node, _currentMember);
+    return _lateLowering.transformStaticSet(node, _currentMember!);
   }
 }
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c5288eb..a710db6 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.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.
 
+// @dart=2.12
+
 library dart2js.src.options;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
@@ -32,8 +34,8 @@
 class FeatureOption {
   final String flag;
   final bool isNegativeFlag;
-  bool _state;
-  bool get isEnabled => _state;
+  bool? _state;
+  bool get isEnabled => _state!;
   bool get isDisabled => !isEnabled;
   void set state(bool value) {
     assert(_state == null);
@@ -67,10 +69,10 @@
   FeatureOption newHolders = FeatureOption('new-holders');
 
   /// [FeatureOption]s which default to enabled.
-  List<FeatureOption> shipping;
+  late final List<FeatureOption> shipping = [legacyJavaScript];
 
   /// [FeatureOption]s which default to disabled.
-  List<FeatureOption> canary;
+  late final List<FeatureOption> canary = [newHolders];
 
   /// Forces canary feature on. This must run after [Option].parse.
   void forceCanary() {
@@ -79,12 +81,6 @@
     }
   }
 
-  // Initialize feature lists.
-  FeatureOptions() {
-    shipping = [legacyJavaScript];
-    canary = [newHolders];
-  }
-
   void parse(List<String> options) {
     _extractFeatures(options, shipping, FeatureStatus.shipping);
     _extractFeatures(options, canary, FeatureStatus.canary);
@@ -122,12 +118,12 @@
 /// as few as possible.
 class CompilerOptions implements DiagnosticOptions {
   /// The entry point of the application that is being compiled.
-  Uri entryPoint;
+  Uri? entryPoint;
 
   /// Location of the package configuration file.
   ///
   /// If not null then [packageRoot] should be null.
-  Uri packageConfig;
+  Uri? packageConfig;
 
   /// List of kernel files to load.
   ///
@@ -140,18 +136,18 @@
   /// At this time, this list points to full kernel files. In the future, we may
   /// use a list of outline files for modular compiles, and only use full kernel
   /// files for linking.
-  List<Uri> dillDependencies;
+  List<Uri>? dillDependencies;
 
   /// Location from which serialized inference data is read.
   ///
   /// If this is set, the [entryPoint] is expected to be a .dill file and the
   /// frontend work is skipped.
-  Uri readDataUri;
+  Uri? readDataUri;
 
   /// Location to which inference data is serialized.
   ///
   /// If this is set, the compilation stops after type inference.
-  Uri writeDataUri;
+  Uri? writeDataUri;
 
   /// Serialize data without the closed world.
   /// TODO(joshualitt) make this the default right after landing in Google3 and
@@ -162,22 +158,22 @@
   ///
   /// If this is set, the [entryPoint] is expected to be a .dill file and the
   /// frontend work is skipped.
-  Uri readClosedWorldUri;
+  Uri? readClosedWorldUri;
 
   /// Location to which inference data is serialized.
   ///
   /// If this is set, the compilation stops after computing the closed world.
-  Uri writeClosedWorldUri;
+  Uri? writeClosedWorldUri;
 
   /// Location from which codegen data is read.
   ///
   /// If this is set, the compilation starts at codegen enqueueing.
-  Uri readCodegenUri;
+  Uri? readCodegenUri;
 
   /// Location to which codegen data is serialized.
   ///
   /// If this is set, the compilation stops after code generation.
-  Uri writeCodegenUri;
+  Uri? writeCodegenUri;
 
   /// Whether to run only the CFE and emit the generated kernel file in
   /// [outputUri].
@@ -205,7 +201,7 @@
           explicitExperimentalFlags: explicitExperimentalFlags);
 
   /// A possibly null state object for kernel compilation.
-  fe.InitializedCompilerState kernelInitializedCompilerState;
+  fe.InitializedCompilerState? kernelInitializedCompilerState;
 
   /// Whether we allow mocking compilation of libraries such as dart:io and
   /// dart:html for unit testing purposes.
@@ -230,11 +226,11 @@
 
   /// Location where to generate a map containing details of how deferred
   /// libraries are subdivided.
-  Uri deferredMapUri;
+  Uri? deferredMapUri;
 
   /// Location where to generate an internal format representing the deferred
   /// graph.
-  Uri deferredGraphUri;
+  Uri? deferredGraphUri;
 
   /// The maximum number of deferred fragments to generate. If the number of
   /// fragments exceeds this amount, then they may be merged.
@@ -242,8 +238,8 @@
   /// will not merge fragments with unrelated dependencies and thus we may
   /// generate more fragments than the 'mergeFragmentsThreshold' under some
   /// situations.
-  int mergeFragmentsThreshold = null; // default value, no max.
-  int _mergeFragmentsThreshold;
+  int? mergeFragmentsThreshold = null; // default value, no max.
+  int? _mergeFragmentsThreshold;
 
   /// Whether to disable inlining during the backend optimizations.
   // TODO(sigmund): negate, so all flags are positive
@@ -276,7 +272,7 @@
   /// Diagnostic option: List of packages for which warnings and hints are
   /// reported. If `null`, no package warnings or hints are reported. If
   /// empty, all warnings and hints are reported.
-  List<String> shownPackageWarnings; // &&&&&
+  List<String>? shownPackageWarnings;
 
   /// Whether to disable global type inference.
   bool disableTypeInference = false;
@@ -304,7 +300,7 @@
 
   /// If set, SSA intermediate form is dumped for methods with names matching
   /// this RegExp pattern.
-  String dumpSsaPattern = null;
+  String? dumpSsaPattern = null;
 
   /// Whether we allow passing an extra argument to `assert`, containing a
   /// reason for why an assertion fails. (experimental)
@@ -354,19 +350,19 @@
   bool generateSourceMap = true;
 
   /// URI of the main output of the compiler.
-  Uri outputUri;
+  Uri? outputUri;
 
   /// Location of the libraries specification file.
-  Uri librariesSpecificationUri;
+  Uri? librariesSpecificationUri;
 
   /// Location of the kernel platform `.dill` files.
-  Uri platformBinaries;
+  Uri? platformBinaries;
 
   /// Whether to print legacy types as T* rather than T.
   bool printLegacyStars = false;
 
   /// URI where the compiler should generate the output source map file.
-  Uri sourceMapUri;
+  Uri? sourceMapUri;
 
   /// The compiler is run from the build bot.
   bool testMode = false;
@@ -387,29 +383,29 @@
   /// What should the compiler do with parameter type assertions.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultParameterCheckPolicy;
+  late CheckPolicy defaultParameterCheckPolicy;
 
   /// What should the compiler do with implicit downcasts.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultImplicitDowncastCheckPolicy;
+  late CheckPolicy defaultImplicitDowncastCheckPolicy;
 
   /// What the compiler should do with a boolean value in a condition context
   /// when the language specification says it is a runtime error for it to be
   /// null.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultConditionCheckPolicy;
+  late CheckPolicy defaultConditionCheckPolicy;
 
   /// What should the compiler do with explicit casts.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultExplicitCastCheckPolicy;
+  late CheckPolicy defaultExplicitCastCheckPolicy;
 
   /// What should the compiler do with List index bounds checks.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultIndexBoundsCheckPolicy;
+  late CheckPolicy defaultIndexBoundsCheckPolicy;
 
   /// Whether to generate code compliant with content security policy (CSP).
   bool useContentSecurityPolicy = false;
@@ -492,14 +488,14 @@
   }
 
   /// If specified, a bundle of optimizations to enable (or disable).
-  int optimizationLevel = null;
+  int? optimizationLevel = null;
 
   /// The shard to serialize when using [writeCodegenUri].
-  int codegenShard;
+  int? codegenShard;
 
   /// The number of shards to serialize when using [writeCodegenUri] or to
   /// deserialize when using [readCodegenUri].
-  int codegenShards;
+  int? codegenShards;
 
   /// Arguments passed to the front end about how it is invoked.
   ///
@@ -515,7 +511,7 @@
   /// Verbosity level used for filtering messages during compilation.
   fe.Verbosity verbosity = fe.Verbosity.all;
 
-  FeatureOptions features;
+  late FeatureOptions features;
 
   // -------------------------------------------------
   // Options for deprecated features
@@ -523,11 +519,11 @@
 
   /// Create an options object by parsing flags from [options].
   static CompilerOptions parse(List<String> options,
-      {FeatureOptions featureOptions,
-      Uri librariesSpecificationUri,
-      Uri platformBinaries,
-      void Function(String) onError,
-      void Function(String) onWarning}) {
+      {FeatureOptions? featureOptions,
+      Uri? librariesSpecificationUri,
+      Uri? platformBinaries,
+      void Function(String)? onError,
+      void Function(String)? onWarning}) {
     if (featureOptions == null) featureOptions = FeatureOptions();
     featureOptions.parse(options);
     Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags =
@@ -545,7 +541,7 @@
       ..benchmarkingExperiment =
           _hasOption(options, Flags.benchmarkingExperiment)
       ..buildId =
-          _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
+          _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)!
       ..compileForServer = _hasOption(options, Flags.serverMode)
       ..deferredMapUri = _extractUriOption(options, '--deferred-map=')
       ..deferredGraphUri =
@@ -638,11 +634,11 @@
       .._mergeFragmentsThreshold =
           _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
       ..cfeInvocationModes = fe.InvocationMode.parseArguments(
-          _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+          _extractStringOption(options, '${Flags.cfeInvocationModes}=', '')!,
           onError: onError)
       ..verbosity = fe.Verbosity.parseArgument(
           _extractStringOption(
-              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue)!,
           onError: onError)
       ..features = featureOptions;
   }
@@ -654,7 +650,7 @@
     if (librariesSpecificationUri == null) {
       throw new ArgumentError("[librariesSpecificationUri] is null.");
     }
-    if (librariesSpecificationUri.path.endsWith('/')) {
+    if (librariesSpecificationUri!.path.endsWith('/')) {
       throw new ArgumentError(
           "[librariesSpecificationUri] should be a file: $librariesSpecificationUri");
     }
@@ -697,12 +693,12 @@
         disableTypeInference = true;
         disableRtiOptimization = true;
       }
-      if (optimizationLevel >= 2) {
+      if (optimizationLevel! >= 2) {
         enableMinification = true;
         laxRuntimeTypeToString = true;
         omitLateNames = true;
       }
-      if (optimizationLevel >= 3) {
+      if (optimizationLevel! >= 3) {
         omitImplicitChecks = true;
       }
       if (optimizationLevel == 4) {
@@ -752,7 +748,7 @@
   /// Returns `true` if warnings and hints are shown for all packages.
   @override
   bool get showAllPackageWarnings {
-    return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
+    return shownPackageWarnings != null && shownPackageWarnings!.isEmpty;
   }
 
   /// Returns `true` if warnings and hints are hidden for all packages.
@@ -767,7 +763,7 @@
     }
     if (shownPackageWarnings != null) {
       return uri.scheme == 'package' &&
-          shownPackageWarnings.contains(uri.pathSegments.first);
+          shownPackageWarnings!.contains(uri.pathSegments.first);
     }
     return false;
   }
@@ -794,8 +790,8 @@
       'isEmitted=$isEmitted)';
 }
 
-String _extractStringOption(
-    List<String> options, String prefix, String defaultValue) {
+String? _extractStringOption(
+    List<String> options, String prefix, String? defaultValue) {
   for (String option in options) {
     if (option.startsWith(prefix)) {
       return option.substring(prefix.length);
@@ -804,13 +800,13 @@
   return defaultValue;
 }
 
-Uri _extractUriOption(List<String> options, String prefix) {
-  String option = _extractStringOption(options, prefix, null);
+Uri? _extractUriOption(List<String> options, String prefix) {
+  String? option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : Uri.parse(option);
 }
 
-int _extractIntOption(List<String> options, String prefix) {
-  String option = _extractStringOption(options, prefix, null);
+int? _extractIntOption(List<String> options, String prefix) {
+  String? option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : int.parse(option);
 }
 
@@ -821,7 +817,7 @@
 /// Extract list of comma separated values provided for [flag]. Returns an
 /// empty list if [option] contain [flag] without arguments. Returns `null` if
 /// [option] doesn't contain [flag] with or without arguments.
-List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+List<String>? _extractOptionalCsvOption(List<String> options, String flag) {
   String prefix = '$flag=';
   for (String option in options) {
     if (option == flag) {
@@ -837,15 +833,15 @@
 /// Extract list of comma separated Uris provided for [flag]. Returns an
 /// empty list if [option] contain [flag] without arguments. Returns `null` if
 /// [option] doesn't contain [flag] with or without arguments.
-List<Uri> _extractUriListOption(List<String> options, String flag) {
-  List<String> stringUris = _extractOptionalCsvOption(options, flag);
+List<Uri>? _extractUriListOption(List<String> options, String flag) {
+  List<String>? stringUris = _extractOptionalCsvOption(options, flag);
   if (stringUris == null) return null;
   return stringUris.map(Uri.parse).toList();
 }
 
 Map<fe.ExperimentalFlag, bool> _extractExperiments(List<String> options,
-    {void Function(String) onError, void Function(String) onWarning}) {
-  List<String> experiments =
+    {void Function(String)? onError, void Function(String)? onWarning}) {
+  List<String>? experiments =
       _extractOptionalCsvOption(options, Flags.enableLanguageExperiments);
   onError ??= (String error) => throw new ArgumentError(error);
   onWarning ??= (String warning) => print(warning);
diff --git a/pkg/compiler/lib/src/util/indentation.dart b/pkg/compiler/lib/src/util/indentation.dart
index fb7cc21..d792f2f 100644
--- a/pkg/compiler/lib/src/util/indentation.dart
+++ b/pkg/compiler/lib/src/util/indentation.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.
 
+// @dart=2.12
+
 part of dart2js.util;
 
 /// Indentation utility class. Should be used as a mixin in most cases.
@@ -64,7 +66,7 @@
   String popTag() {
     assert(!tagStack.isEmpty);
     String tag = tagStack.head;
-    tagStack = tagStack.tail;
+    tagStack = tagStack.tail!;
     indentLess();
     return tag;
   }
@@ -81,7 +83,7 @@
   /// The method "opens" the node, meaning that all output after calling
   /// this method and before calling closeNode() will represent contents
   /// of given node.
-  void openNode(N node, String type, [Map params]) {
+  void openNode(N node, String type, [Map? params]) {
     if (params == null) params = new Map();
     addCurrentIndent();
     sb.write("<");
@@ -92,7 +94,7 @@
   }
 
   /// Adds given node to result string.
-  void openAndCloseNode(N node, String type, [Map params]) {
+  void openAndCloseNode(N node, String type, [Map? params]) {
     if (params == null) params = {};
     addCurrentIndent();
     sb.write("<");
@@ -110,7 +112,7 @@
     sb.write(">\n");
   }
 
-  void addTypeWithParams(String type, [Map params]) {
+  void addTypeWithParams(String type, [Map? params]) {
     if (params == null) params = new Map();
     sb.write("${type}");
     params.forEach((k, v) {
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 3a9949d..703bf10 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.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.
 
+// @dart=2.12
+
 library dart2js.util;
 
 import 'package:front_end/src/api_unstable/dart2js.dart'
@@ -45,13 +47,13 @@
   }
 
   /// Mix the bits of `object.hashCode` with [existing].
-  static int objectHash(Object object, [int existing = 0]) {
+  static int objectHash(Object? object, [int existing = 0]) {
     return mixHashCodeBits(existing, object.hashCode);
   }
 
   /// Mix the bits of `.hashCode` all non-null objects.
-  static int objectsHash(Object obj1,
-      [Object obj2, Object obj3, Object obj4, Object obj5]) {
+  static int objectsHash(Object? obj1,
+      [Object? obj2, Object? obj3, Object? obj4, Object? obj5]) {
     int hash = 0;
     if (obj5 != null) hash = objectHash(obj5, hash);
     if (obj4 != null) hash = objectHash(obj4, hash);
@@ -61,7 +63,7 @@
   }
 
   /// Mix the bits of the element hash codes of [list] with [existing].
-  static int listHash(List list, [int existing = 0]) {
+  static int listHash(List? list, [int existing = 0]) {
     int h = existing;
     if (list != null) {
       int length = list.length;
@@ -73,7 +75,7 @@
   }
 
   /// Mix the bits of the element hash codes of [iterable] with [existing].
-  static int setHash<E>(Iterable<E> iterable, [int existing = 0]) {
+  static int setHash<E>(Iterable<E>? iterable, [int existing = 0]) {
     int h = existing;
     if (iterable != null) {
       for (E e in iterable) {
@@ -111,7 +113,7 @@
   }
 }
 
-bool identicalElements<E>(List<E> a, List<E> b) {
+bool identicalElements<E>(List<E>? a, List<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -123,7 +125,7 @@
   return true;
 }
 
-bool equalElements<E>(List<E> a, List<E> b) {
+bool equalElements<E>(List<E>? a, List<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -135,13 +137,13 @@
   return true;
 }
 
-bool equalSets<E>(Set<E> a, Set<E> b) {
+bool equalSets<E>(Set<E>? a, Set<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   return a.length == b.length && a.containsAll(b) && b.containsAll(a);
 }
 
-bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+bool equalMaps<K, V>(Map<K, V>? a, Map<K, V>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -153,7 +155,7 @@
 
 /// File name prefix used to shorten the file name in stack traces printed by
 /// [trace].
-String stackTraceFilePrefix = null;
+String? stackTraceFilePrefix = null;
 
 /// Writes the characters of [string] on [buffer].  The characters
 /// are escaped as suitable for JavaScript and JSON.  [buffer] is
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 82e68d2..568f3ce 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_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 'dart:convert';
 import 'dart:io';
 
 import 'package:test/test.dart';
@@ -98,4 +99,16 @@
         startsWith('No file or directory found at "$unknownFilePath".'));
     expect(result.stdout, startsWith('Formatted no files in '));
   });
+
+  test('formats from stdin and exits', () async {
+    p = project(mainSrc: 'int get foo => 1;\n');
+    var process = await p.start(['format']);
+    process.stdin.writeln('main(   ) { }');
+
+    var result = process.stdout.reduce((a, b) => a + b);
+
+    await process.stdin.close();
+    expect(await process.exitCode, 0);
+    expect(utf8.decode(await result), 'main() {}\n');
+  });
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 1e1f94d..40f3f36 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -420,7 +420,7 @@
       await driver.check(
           breakpointId: 'globalFunctionBP',
           expression: 'C._staticField',
-          expectedError: "Error: Getter not found: '_staticField'.");
+          expectedResult: '2');
     });
 
     test('access field', () async {
@@ -476,7 +476,7 @@
       await driver.check(
           breakpointId: 'globalFunctionBP',
           expression: 'C._staticField = 2',
-          expectedError: "Setter not found: '_staticField'.");
+          expectedResult: '2');
     });
 
     test('static field modification', () async {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index ac1c9ad..83c9a50 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -1553,6 +1553,8 @@
   TypeCheck explicitCast(AsExpression cast) =>
       summaryCollector.explicitCasts[cast];
 
+  TypeCheck isTest(IsExpression node) => summaryCollector.isTests[node];
+
   NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node];
 
   Type fieldType(Field field) => _fieldValues[field]?.value;
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index 1c9ae91..dcae2df 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -538,6 +538,7 @@
   final TreeNode node;
 
   final Type staticType;
+  final SubtypeTestKind kind;
 
   // 'isTestedOnlyOnCheckedEntryPoint' is whether or not this parameter's type-check will
   // occur on the "checked" entrypoint in the VM but will be skipped on
@@ -547,9 +548,10 @@
   VariableDeclaration get parameter =>
       node is VariableDeclaration ? node : null;
 
-  bool canAlwaysSkip = true;
+  bool alwaysPass = true;
+  bool alwaysFail = true;
 
-  TypeCheck(this.arg, this.type, this.node, this.staticType) {
+  TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind) {
     assert(node != null);
     isTestedOnlyOnCheckedEntryPoint =
         parameter != null && !parameter.isCovariant;
@@ -573,14 +575,14 @@
     // TODO(sjindel/tfa): Narrow the result if possible.
     assert(checkType is UnknownType || checkType is RuntimeType);
 
-    bool canSkip = true; // Can this check be skipped on this invocation.
+    bool pass = true; // Can this check be skipped on this invocation.
 
     if (checkType is UnknownType) {
       // If we don't know what the RHS of the check is going to be, we can't
       // guarantee that it will pass.
-      canSkip = false;
+      pass = false;
     } else if (checkType is RuntimeType) {
-      canSkip = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType);
+      pass = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType, kind);
       argType = argType.intersection(
           typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
           typeHierarchy);
@@ -591,8 +593,8 @@
     // If this check might be skipped on an
     // unchecked entry-point, we need to signal that the call-site must be
     // checked.
-    if (!canSkip) {
-      canAlwaysSkip = false;
+    if (!pass) {
+      alwaysPass = false;
       if (isTestedOnlyOnCheckedEntryPoint) {
         callHandler.typeCheckTriggered();
       }
@@ -601,7 +603,13 @@
       }
     }
 
-    argType = argType.intersection(staticType, typeHierarchy);
+    argType = argType
+        .intersection(staticType, typeHierarchy)
+        .specialize(typeHierarchy);
+
+    if (argType is! EmptyType) {
+      alwaysFail = false;
+    }
 
     return argType;
   }
@@ -782,7 +790,7 @@
     final params = <VariableDeclaration>[];
     for (Statement statement in _statements) {
       if (statement is TypeCheck &&
-          statement.canAlwaysSkip &&
+          statement.alwaysPass &&
           statement.parameter != null) {
         params.add(statement.parameter);
       }
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index b5b213f..cd78792 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -534,6 +534,7 @@
   final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
   final Map<AsExpression, TypeCheck> explicitCasts =
       <AsExpression, TypeCheck>{};
+  final Map<IsExpression, TypeCheck> isTests = <IsExpression, TypeCheck>{};
   final Map<TreeNode, NarrowNotNull> nullTests = <TreeNode, NarrowNotNull>{};
   final _FallthroughDetector _fallthroughDetector = new _FallthroughDetector();
   final Set<Name> _nullMethodsAndGetters = <Name>{};
@@ -1064,10 +1065,14 @@
     }
   }
 
-  TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node) {
+  TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node,
+      [SubtypeTestKind kind = SubtypeTestKind.Subtype]) {
     final TypeExpr runtimeType = _translator.translate(type);
-    final typeCheck = new TypeCheck(
-        value, runtimeType, node, _typesBuilder.fromStaticType(type, true));
+    final bool canBeNull = (kind == SubtypeTestKind.IsTest)
+        ? _canBeNullAfterSuccessfulIsCheck(type)
+        : true;
+    final typeCheck = new TypeCheck(value, runtimeType, node,
+        _typesBuilder.fromStaticType(type, canBeNull), kind);
     _summary.add(typeCheck);
     return typeCheck;
   }
@@ -1128,19 +1133,17 @@
     return narrow;
   }
 
-  // Narrow type of [arg] after successful 'is' test against [type].
-  TypeExpr _makeNarrowAfterSuccessfulIsCheck(TypeExpr arg, DartType type) {
+  bool _canBeNullAfterSuccessfulIsCheck(DartType type) {
     // 'x is type' can succeed for null if type is
     //  - a top type (dynamic, void, Object? or Object*)
     //  - nullable (including Null)
     //  - a type parameter (it can be instantiated with Null)
     //  - legacy Never
     final nullability = type.nullability;
-    final bool canBeNull = _environment.isTop(type) ||
+    return _environment.isTop(type) ||
         nullability == Nullability.nullable ||
         type is TypeParameterType ||
         (type is NeverType && nullability == Nullability.legacy);
-    return _makeNarrow(arg, _typesBuilder.fromStaticType(type, canBeNull));
   }
 
   TypeExpr _makeNarrowNotNull(TreeNode node, TypeExpr arg) {
@@ -1400,11 +1403,12 @@
     } else if (node is IsExpression && node.operand is VariableGet) {
       // Handle 'x is T', where x is a variable.
       final operand = node.operand as VariableGet;
-      _addUse(_visit(operand));
+      final TypeCheck typeCheck =
+          _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest);
+      isTests[node] = typeCheck;
       final int varIndex = _variablesInfo.varIndex[operand.variable];
       if (_variableCells[varIndex] == null) {
-        trueState[varIndex] =
-            _makeNarrowAfterSuccessfulIsCheck(_visit(operand), node.type);
+        trueState[varIndex] = typeCheck;
       }
       _variableValues = null;
       return;
@@ -1535,7 +1539,11 @@
 
   @override
   TypeExpr visitIsExpression(IsExpression node) {
-    _visit(node.operand);
+    final operandNode = node.operand;
+    final TypeExpr operand = _visit(operandNode);
+    final TypeCheck typeCheck =
+        _typeCheck(operand, node.type, node, SubtypeTestKind.IsTest);
+    isTests[node] = typeCheck;
     return _boolType;
   }
 
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 5fb8cc5..feb185d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1049,7 +1049,11 @@
     final List<ast.Statement> statements = <ast.Statement>[];
     for (var arg in args) {
       if (mayHaveSideEffects(arg)) {
-        statements.add(ExpressionStatement(arg));
+        if (arg is BlockExpression && !mayHaveSideEffects(arg.value)) {
+          statements.add(arg.body);
+        } else {
+          statements.add(ExpressionStatement(arg));
+        }
       }
     }
     if (statements.isEmpty) {
@@ -1245,8 +1249,8 @@
     }
     final nullTest = _getNullTest(node);
     if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) {
-      return _evaluateArguments(
-          [node.expression], BoolLiteral(nullTest.isAlwaysNull));
+      return _evaluateArguments([node.expression],
+          BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset);
     }
     return node;
   }
@@ -1502,11 +1506,138 @@
     return _visitAssertNode(node, removalSentinel);
   }
 
+  // Expression is an extended bool literal if it is
+  //  - a BoolLiteral
+  //  - a BlockExpression with a BoolLiteral value.
+  bool _isExtendedBoolLiteral(Expression expr) =>
+      expr is BoolLiteral ||
+      (expr is BlockExpression && expr.value is BoolLiteral);
+
+  // Returns value of an extended bool literal.
+  bool _getExtendedBoolLiteralValue(Expression expr) => (expr is BoolLiteral)
+      ? expr.value
+      : ((expr as BlockExpression).value as BoolLiteral).value;
+
+  // Returns Block corresponding to the given extended bool literal,
+  // or null if the expression is a simple bool literal.
+  Block _getExtendedBoolLiteralBlock(Expression expr) =>
+      (expr is BoolLiteral) ? null : (expr as BlockExpression).body;
+
+  @override
+  TreeNode visitIfStatement(IfStatement node, TreeNode removalSentinel) {
+    final condition = transform(node.condition);
+    if (_isExtendedBoolLiteral(condition)) {
+      final bool conditionValue = _getExtendedBoolLiteralValue(condition);
+      final Block conditionBlock = _getExtendedBoolLiteralBlock(condition);
+      ast.Statement body;
+      if (conditionValue) {
+        body = transform(node.then);
+      } else {
+        if (node.otherwise != null) {
+          body = transformOrRemoveStatement(node.otherwise);
+        }
+      }
+      if (conditionBlock != null) {
+        if (body != null) {
+          conditionBlock.addStatement(body);
+        }
+        return conditionBlock;
+      } else {
+        return body ?? EmptyStatement();
+      }
+    }
+    node.condition = condition..parent = node;
+    node.then = transform(node.then)..parent = node;
+    if (node.otherwise != null) {
+      node.otherwise = transformOrRemoveStatement(node.otherwise);
+      node.otherwise?.parent = node;
+    }
+    return node;
+  }
+
+  @override
+  visitConditionalExpression(
+      ConditionalExpression node, TreeNode removalSentinel) {
+    final condition = transform(node.condition);
+    if (_isExtendedBoolLiteral(condition)) {
+      final bool value = _getExtendedBoolLiteralValue(condition);
+      final Expression expr = transform(value ? node.then : node.otherwise);
+      if (condition is BlockExpression) {
+        condition.value = expr;
+        expr.parent = condition;
+        return condition;
+      } else {
+        return expr;
+      }
+    }
+    node.condition = condition..parent = node;
+    node.then = transform(node.then)..parent = node;
+    node.otherwise = transform(node.otherwise)..parent = node;
+    node.staticType = visitDartType(node.staticType, cannotRemoveSentinel);
+    return node;
+  }
+
+  @override
+  TreeNode visitNot(Not node, TreeNode removalSentinel) {
+    node.transformOrRemoveChildren(this);
+    final operand = node.operand;
+    if (_isExtendedBoolLiteral(operand)) {
+      final bool value = _getExtendedBoolLiteralValue(operand);
+      if (operand is BlockExpression) {
+        (operand.value as BoolLiteral).value = !value;
+      } else {
+        (operand as BoolLiteral).value = !value;
+      }
+      return operand;
+    }
+    return node;
+  }
+
+  @override
+  TreeNode visitLogicalExpression(
+      LogicalExpression node, TreeNode removalSentinel) {
+    final left = transform(node.left);
+    final operatorEnum = node.operatorEnum;
+    if (_isExtendedBoolLiteral(left)) {
+      final leftValue = _getExtendedBoolLiteralValue(left);
+      if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
+        return left;
+      } else if (!leftValue && operatorEnum == LogicalExpressionOperator.AND) {
+        return left;
+      }
+    }
+    final right = transform(node.right);
+    // Without sound null safety arguments of logical expression
+    // are implicitly checked for null, so transform the node only
+    // if using sound null safety or it evaluates to a bool literal.
+    if (_isExtendedBoolLiteral(left) &&
+        (shaker.typeFlowAnalysis.target.flags.enableNullSafety ||
+            _isExtendedBoolLiteral(right))) {
+      return _evaluateArguments([left], right);
+    }
+    node.left = left..parent = node;
+    node.right = right..parent = node;
+    return node;
+  }
+
+  @override
+  TreeNode visitIsExpression(IsExpression node, TreeNode removalSentinel) {
+    TypeCheck check = shaker.typeFlowAnalysis.isTest(node);
+    if (check != null && (check.alwaysFail || check.alwaysPass)) {
+      final operand = transform(node.operand);
+      final result = BoolLiteral(!check.alwaysFail)
+        ..fileOffset = node.fileOffset;
+      return _evaluateArguments([operand], result);
+    }
+    node.transformOrRemoveChildren(this);
+    return node;
+  }
+
   @override
   TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) {
     node.transformOrRemoveChildren(this);
     TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node);
-    if (check != null && check.canAlwaysSkip) {
+    if (check != null && check.alwaysPass) {
       return StaticInvocation(
           unsafeCast, Arguments([node.operand], types: [node.type]))
         ..fileOffset = node.fileOffset;
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4d13774..588512c 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -154,6 +154,13 @@
   Type getComputedType(List<Type> types);
 }
 
+/// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test.
+/// There is a subtle difference in how these tests handle null value.
+enum SubtypeTestKind {
+  Subtype,
+  IsTest,
+}
+
 /// Base class for types inferred by the type flow analysis.
 /// [Type] describes a specific set of values (Dart instances) and does not
 /// directly correspond to a Dart type.
@@ -174,8 +181,8 @@
   // Returns 'true' if this type will definitely pass a runtime type-check
   // against 'runtimeType'. Returns 'false' if the test might fail (e.g. due to
   // an approximation).
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType);
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind);
 
   @override
   Type getComputedType(List<Type> types) => this;
@@ -241,7 +248,8 @@
   @override
   Type intersection(Type other, TypeHierarchy typeHierarchy) => this;
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     return true;
   }
 }
@@ -271,12 +279,27 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       baseType.isSubtypeOf(typeHierarchy, cls);
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
-    if (typeHierarchy.nullSafety &&
-        other.nullability == Nullability.nonNullable) {
-      return false;
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+    switch (kind) {
+      case SubtypeTestKind.Subtype:
+        if (typeHierarchy.nullSafety &&
+            other.nullability == Nullability.nonNullable) {
+          return false;
+        }
+        break;
+      case SubtypeTestKind.IsTest:
+        if (other.nullability != Nullability.nullable) {
+          final rhs = other._type;
+          if (!(rhs is InterfaceType &&
+              rhs.nullability == Nullability.legacy &&
+              rhs.classNode == typeHierarchy.coreTypes.objectClass)) {
+            return false;
+          }
+        }
+        break;
     }
-    return baseType.isSubtypeOfRuntimeType(typeHierarchy, other);
+    return baseType.isSubtypeOfRuntimeType(typeHierarchy, other, kind);
   }
 
   @override
@@ -349,7 +372,8 @@
     return other;
   }
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     final rhs = other._type;
     return (rhs is DynamicType) ||
         (rhs is VoidType) ||
@@ -403,8 +427,9 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       types.every((ConcreteType t) => t.isSubtypeOf(typeHierarchy, cls));
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) =>
-      types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other));
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other,
+          SubtypeTestKind kind) =>
+      types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other, kind));
 
   @override
   int get order => TypeOrder.Set.index;
@@ -577,7 +602,8 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       typeHierarchy.isSubtype(this.cls.classNode, cls);
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     final rhs = other._type;
     if (rhs is DynamicType || rhs is VoidType) return true;
     if (rhs is InterfaceType) {
@@ -795,8 +821,8 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class other) =>
       typeHierarchy.isSubtype(cls.classNode, other);
 
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind) {
     final rhs = runtimeType._type;
     if (rhs is DynamicType || rhs is VoidType) return true;
     if (rhs is InterfaceType) {
@@ -836,7 +862,7 @@
         }
         assert(ta is RuntimeType);
         if (!ta.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[i])) {
+            typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
           return false;
         }
       }
@@ -856,9 +882,10 @@
         final RuntimeType lhs =
             typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null);
         return lhs.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[0]);
+            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
       } else {
-        return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+        return isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
       }
     }
     return false;
@@ -1149,8 +1176,11 @@
   Class getConcreteClass(TypeHierarchy typeHierarchy) =>
       throw "ERROR: ConcreteClass does not support getConcreteClass.";
 
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind) {
+    if (kind != SubtypeTestKind.Subtype) {
+      throw 'RuntimeType could be only tested for subtyping.';
+    }
     final rhs = runtimeType._type;
     if (typeHierarchy.nullSafety &&
         _type.nullability == Nullability.nullable &&
@@ -1170,14 +1200,15 @@
       if (_type is InterfaceType) {
         Class thisClass = (_type as InterfaceType).classNode;
         if (thisClass == typeHierarchy.coreTypes.futureClass) {
-          return typeArgs[0]
-              .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+          return typeArgs[0].isSubtypeOfRuntimeType(
+              typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
         } else {
-          return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+          return isSubtypeOfRuntimeType(
+              typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
         }
       } else if (_type is FutureOrType) {
-        return typeArgs[0]
-            .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+        return typeArgs[0].isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
       }
     }
 
@@ -1216,8 +1247,8 @@
     assert(usableTypeArgs.length - interfaceOffset >=
         runtimeType.numImmediateTypeArgs);
     for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
-      if (!usableTypeArgs[interfaceOffset + i]
-          .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+      if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType(
+          typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
         return false;
       }
     }
@@ -1264,7 +1295,11 @@
     throw "ERROR: UnknownType does not support intersection with ${other.runtimeType}";
   }
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+    if (kind != SubtypeTestKind.Subtype) {
+      throw 'UnknownType could be only tested for subtyping.';
+    }
     final rhs = other._type;
     return (rhs is DynamicType) ||
         (rhs is VoidType) ||
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
index 625d97f..5b8180a 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -12,15 +12,16 @@
 i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t3)
 t5* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 10))
 t6* = _Call direct [#lib::bar] ()
-t7* = _Call direct [#lib::foo] ()
-t8 = _Join [dynamic] (_T (dart.core::bool, true), t7)
-t9 = _TypeCheck (t8 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
-t10* = _Call direct [#lib::bar] ()
+t7 = _TypeCheck (t6 against dart.core::bool*) (for x is dart.core::bool*)
+t8* = _Call direct [#lib::foo] ()
+t9 = _Join [dynamic] (_T (dart.core::bool, true), t8)
+t10 = _TypeCheck (t9 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
 t11* = _Call direct [#lib::bar] ()
-t12* = _Call direct [#lib::foo] ()
-t13 = _TypeCheck (t12 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-t14* = _Call direct [#lib::foo] ()
-t15 = _TypeCheck (t14 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t12* = _Call direct [#lib::bar] ()
+t13* = _Call direct [#lib::foo] ()
+t14 = _TypeCheck (t13 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t15* = _Call direct [#lib::foo] ()
+t16 = _TypeCheck (t15 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
 y_0 = _Join [dart.core::bool*] (_T (dart.core::bool), _T (dart.core::bool, true))
 RESULT: _T {}?
 ------------ main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index 54aa62d..80bbada 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -124,7 +124,7 @@
 RESULT: _T {}?
 ------------ if8 ------------
 %x = _Parameter #0 [_T ANY?]
-t1 = _Narrow (%x to _T (dart.core::String)+)
+t1 = _TypeCheck (%x against dart.core::String) (for x is dart.core::String)
 t2 = _Call direct [#lib::foo] (t1)
 RESULT: _T {}?
 ------------ if9 ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index 4bba0a1..b5c21e4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -21,7 +21,7 @@
 ------------ bar ------------
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
 %a2 = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Narrow (%a1 to _T (dart.core::int)+)
+t2 = _TypeCheck (%a1 against dart.core::int*) (for v1 is dart.core::int*)
 t3* = _Call [dart.core::num.+] (t2, %a2)
 t4* = _Call [dart.core::num.*] (t3, _T (dart.core::_Smi, 3))
 t5* = _Call [dart.core::int.unary-] (_T (dart.core::_Smi, 1))
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
new file mode 100644
index 0000000..fa5a893
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 elimination of 'is' tests.
+
+// @dart = 2.12
+
+class A {}
+
+class B extends A {
+  void foo() {
+    print('foo');
+  }
+
+  bool get bar => int.parse('1') == 1;
+}
+
+class C implements A {}
+
+A obj = int.parse('2') == 2 ? C() : A();
+A getObj() => obj;
+
+void test1() {
+  var x = getObj();
+  if (x is B) {
+    x.foo();
+  }
+}
+
+void test2(x) {
+  if (x is B && x.bar) {
+    print('bye');
+  }
+}
+
+void test3(x) {
+  if (x is! B) {
+    return;
+  }
+  print('bye');
+}
+
+test4() => (getObj() is B) ? 3 : 4;
+
+void main() {
+  test1();
+  test2(obj);
+  test3(obj);
+  test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
new file mode 100644
index 0000000..3af08e0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
@@ -0,0 +1,40 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::A {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+static field self::A obj = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("2") =={core::num::==}{(core::Object) → core::bool} 2 ?{self::A} new self::C::•() : new self::A::•();
+static method getObj() → self::A
+  return self::obj;
+static method test1() → void {
+  self::A x = self::getObj();
+  ;
+}
+static method test2() → void {
+  ;
+}
+static method test3() → void {
+  {
+    return;
+  }
+  core::print("bye");
+}
+[@vm.unboxing-info.metadata=()->i]static method test4() → dynamic
+  return block {
+    self::getObj();
+  } =>4;
+static method main() → void {
+  self::test1();
+  let final self::A #t1 = self::obj in self::test2();
+  let final self::A #t2 = self::obj in self::test3();
+  self::test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 2fa9807..11d07aa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -13,10 +13,8 @@
 }
 [@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
 static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if( block {
+  {
     [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
-  } =>false) {
-    core::print("null");
   }
 }
 static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
@@ -25,16 +23,17 @@
   }
 }
 static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if( block {
+  {
     [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
-  } =>true) {
-    core::print("null");
+    {
+      core::print("null");
+    }
   }
 }
 static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!( block {
+  if(( block {
     [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
-  } =>false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+  } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
     core::print("not null");
   }
 }
@@ -44,22 +43,20 @@
   }
 }
 static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!( block {
+  {
     [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
-  } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
-    core::print("not null");
   }
 }
 static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !( block {
+  return block {
     [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
-  } =>false) ?{core::String*} "not null" : "null";
+  } =>"not null";
 static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
   return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
 static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !( block {
+  return block {
     [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
-  } =>true) ?{core::String*} "not null" : "null";
+  } =>"null";
 static method someCondition() → dynamic
   return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
 static method main() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
index 89b2f4f..162174d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
@@ -19,8 +19,7 @@
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method add(generic-covariant-impl self::_SplayTree::Node n) → dynamic {
     self::_SplayTree::Node? root = [@vm.direct-call.metadata=#lib::SplayTreeMap._root] [@vm.inferred-type.metadata=#lib::_SplayTreeMapNode<dynamic>] this.{self::_SplayTree::_root}{self::_SplayTree::Node?};
-    if(false)
-      return;
+    ;
     core::print([@vm.direct-call.metadata=#lib::_SplayTreeNode.left] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] root{self::_SplayTree::Node}.{self::_SplayTreeNode::left}{self::_SplayTree::Node?});
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  abstract get /*isLegacy*/ _root() → self::_SplayTree::Node?;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
index 82edbf6..37b6a68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
@@ -16,11 +16,11 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method noSuchMethod(core::Invocation i) → dynamic
     return throw "Not implemented";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (core::Object) →? core::bool test = #C1}) → asy::Future<self::B::T%>
-    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError) → asy::Future<self::B::T%>
+    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: #C4}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::B::T%>
-    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::B::then::R%>
+    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C4}) → asy::Future<self::B::then::R%>
     return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R%)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onError}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::then::R%>;
 }
 static method createB<T extends core::Object? = dynamic>() → self::B<dynamic>
@@ -29,10 +29,10 @@
   core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int>() as{ForNonNullableByDefault} FutureOr<core::double>);
 }
 constants  {
-  #C1 = null
-  #C2 = #catchError
-  #C3 = <core::Type*>[]
-  #C4 = #test
+  #C1 = #catchError
+  #C2 = <core::Type*>[]
+  #C3 = #test
+  #C4 = null
   #C5 = #whenComplete
   #C6 = <dynamic>[]
   #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
index 9f7ad71..7ac9fc8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
@@ -34,7 +34,7 @@
 static method testDynamic() → dynamic
   return _in::unsafeCast<dynamic>(#C3);
 static method testObjectNegative() → dynamic
-  return let dynamic #t1 = #C2 in true ?{core::Object} #t1 as{ForNonNullableByDefault} core::Object : #t1{core::Object};
+  return let dynamic #t1 = #C2 in #t1 as{ForNonNullableByDefault} core::Object;
 static method testNullableObject() → dynamic
   return #C2;
 static method testAOfNum1([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
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 96487b0..6cd1f40 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
@@ -4,8 +4,6 @@
 
 abstract class I extends core::Object {
 }
-abstract class A extends core::Object implements self::I {
-}
 class B extends core::Object implements self::I {
   synthetic constructor •() → self::B
     : super core::Object::•()
@@ -13,9 +11,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{ForNonNullableByDefault} self::A) {
-    throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  }
+  ;
 }
 static method main(core::List<core::String> args) → dynamic {
   self::bar([@vm.inferred-type.metadata=#lib::B?] self::ii);
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d983c2c..4a6ac6b 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5582,6 +5582,7 @@
                             DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD,
+                            DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD)
 #undef DECLARE_OBJECT_STORE_FIELD
 };
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index dccfad1..a425e97 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -127,7 +127,11 @@
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
 #elif defined(TARGET_ARCH_ARM64)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
+#if defined(DART_COMPRESSED_POINTERS)
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 276;
+#else
   static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
+#endif
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
 #endif
 
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 5f947b7..9892d6f 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -123,7 +123,7 @@
 #define EMIT_FIELD_NAME(type, name) #name "_",
         OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME,
                                 EMIT_FIELD_NAME, EMIT_FIELD_NAME,
-                                EMIT_FIELD_NAME)
+                                EMIT_FIELD_NAME, EMIT_FIELD_NAME)
 #undef EMIT_FIELD_NAME
     };
     ObjectPtr* current = from();
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index e502c01..267ff50 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -36,10 +36,11 @@
 //
 // R_ - needs getter only
 // RW - needs getter and setter
+// ARW - needs getter and setter with atomic access
 // CR - needs lazy Core init getter
 // FR - needs lazy Async init getter
 // IR - needs lazy Isolate init getter
-#define OBJECT_STORE_FIELD_LIST(R_, RW, CR, FR, IR)                            \
+#define OBJECT_STORE_FIELD_LIST(R_, RW, ARW, CR, FR, IR)                       \
   CR(Class, list_class)                    /* maybe be null, lazily built */   \
   CR(Type, non_nullable_list_rare_type)    /* maybe be null, lazily built */   \
   CR(Type, non_nullable_map_rare_type)     /* maybe be null, lazily built */   \
@@ -173,8 +174,8 @@
   RW(Function, complete_on_async_return)                                       \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
-  RW(Smi, future_timeout_future_index)                                         \
-  RW(Smi, future_wait_future_index)                                            \
+  ARW(Smi, future_timeout_future_index)                                        \
+  ARW(Smi, future_wait_future_index)                                           \
   RW(CompressedStackMaps, canonicalized_stack_map_entries)                     \
   RW(ObjectPool, global_object_pool)                                           \
   RW(Array, unique_dynamic_targets)                                            \
@@ -391,12 +392,24 @@
   ObjectStore();
   ~ObjectStore();
 
+#define DECLARE_OFFSET(name)                                                   \
+  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
 #define DECLARE_GETTER(Type, name)                                             \
   Type##Ptr name() const { return name##_; }                                   \
-  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+  DECLARE_OFFSET(name)
 #define DECLARE_GETTER_AND_SETTER(Type, name)                                  \
   DECLARE_GETTER(Type, name)                                                   \
   void set_##name(const Type& value) { name##_ = value.ptr(); }
+#define DECLARE_ATOMIC_GETTER_AND_SETTER(Type, name)                           \
+  template <std::memory_order order = std::memory_order_relaxed>               \
+  Type##Ptr name() const {                                                     \
+    return name##_.load(order);                                                \
+  }                                                                            \
+  template <std::memory_order order = std::memory_order_relaxed>               \
+  void set_##name(const Type& value) {                                         \
+    name##_.store(value.ptr(), order);                                         \
+  }                                                                            \
+  DECLARE_OFFSET(name)
 #define DECLARE_LAZY_INIT_GETTER(Type, name, init)                             \
   Type##Ptr name() {                                                           \
     if (name##_.load() == Type::null()) {                                      \
@@ -404,7 +417,7 @@
     }                                                                          \
     return name##_.load();                                                     \
   }                                                                            \
-  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+  DECLARE_OFFSET(name)
 #define DECLARE_LAZY_INIT_CORE_GETTER(Type, name)                              \
   DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreMembers)
 #define DECLARE_LAZY_INIT_ASYNC_GETTER(Type, name)                             \
@@ -413,11 +426,14 @@
   DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitIsolateMembers)
   OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
                           DECLARE_GETTER_AND_SETTER,
+                          DECLARE_ATOMIC_GETTER_AND_SETTER,
                           DECLARE_LAZY_INIT_CORE_GETTER,
                           DECLARE_LAZY_INIT_ASYNC_GETTER,
                           DECLARE_LAZY_INIT_ISOLATE_GETTER)
+#undef DECLARE_OFFSET
 #undef DECLARE_GETTER
 #undef DECLARE_GETTER_AND_SETTER
+#undef DECLARE_ATOMIC_GETTER_AND_SETTER
 #undef DECLARE_LAZY_INIT_GETTER
 #undef DECLARE_LAZY_INIT_CORE_GETTER
 #undef DECLARE_LAZY_INIT_ASYNC_GETTER
@@ -478,15 +494,19 @@
 
   ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&list_class_); }
 #define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
+#define DECLARE_ATOMIC_OBJECT_STORE_FIELD(type, name)                          \
+  std::atomic<type##Ptr> name##_;
 #define DECLARE_LAZY_OBJECT_STORE_FIELD(type, name)                            \
   AcqRelAtomic<type##Ptr> name##_;
   OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
                           DECLARE_OBJECT_STORE_FIELD,
+                          DECLARE_ATOMIC_OBJECT_STORE_FIELD,
                           DECLARE_LAZY_OBJECT_STORE_FIELD,
                           DECLARE_LAZY_OBJECT_STORE_FIELD,
                           DECLARE_LAZY_OBJECT_STORE_FIELD)
-#undef DECLARE_LAZY_OBJECT_STORE_FIELD
 #undef DECLARE_OBJECT_STORE_FIELD
+#undef DECLARE_ATOMIC_OBJECT_STORE_FIELD
+#undef DECLARE_LAZY_OBJECT_STORE_FIELD
   ObjectPtr* to() {
     return reinterpret_cast<ObjectPtr*>(&ffi_as_function_internal_);
   }
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index b2e773d..b2545cf 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -257,9 +257,22 @@
     // Remember context indices of _future variables in _Future.timeout and
     // Future.wait. They are used while collecting async stack traces.
     if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
+#ifdef DEBUG
+      auto old_value = IsolateGroup::Current()
+                           ->object_store()
+                           ->future_timeout_future_index();
+      ASSERT(old_value == Object::null() ||
+             Smi::Value(old_value) == chained_future->index().value());
+#endif  // DEBUG
       IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
           Smi::Handle(Smi::New(chained_future->index().value())));
     } else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
+#ifdef DEBUG
+      auto old_value =
+          IsolateGroup::Current()->object_store()->future_wait_future_index();
+      ASSERT(old_value == Object::null() ||
+             Smi::Value(old_value) == chained_future->index().value());
+#endif  // DEBUG
       IsolateGroup::Current()->object_store()->set_future_wait_future_index(
           Smi::Handle(Smi::New(chained_future->index().value())));
     } else {
diff --git a/tools/VERSION b/tools/VERSION
index 8119d92..6197956 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 340
+PRERELEASE 341
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 7b9a07d..882c827 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -92,22 +92,20 @@
   packages.sort((a, b) => a["name"].compareTo(b["name"]));
 
   var configFile = File(p.join(repoRoot, '.dart_tool', 'package_config.json'));
+  var json =
+      jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
+  var oldPackages = json['packages'] as List<dynamic>;
 
   // Validate the packages entry only, to avoid spurious failures from changes
   // in the dates embedded in the other entries.
-  if (checkOnly) {
-    var json =
-        jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
-    var oldPackages = json['packages'] as List<dynamic>;
-    if (jsonEncode(packages) == jsonEncode(oldPackages)) {
-      print("Package config up to date");
-      exit(0);
-    } else {
-      print("Package config out of date");
-      print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
-          "to update.");
-      exit(1);
-    }
+  if (jsonEncode(packages) == jsonEncode(oldPackages)) {
+    print("Package config up to date");
+    exit(0);
+  } else if (checkOnly) {
+    print("Package config out of date");
+    print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
+        "to update.");
+    exit(1);
   }
 
   var year = DateTime.now().year;
@@ -130,8 +128,8 @@
   };
 
   // TODO(rnystrom): Consider using package_config_v2 to generate this instead.
-  var json = JsonEncoder.withIndent('  ').convert(config);
-  configFile.writeAsStringSync('$json\n');
+  var jsonString = JsonEncoder.withIndent('  ').convert(config);
+  configFile.writeAsStringSync('$jsonString\n');
   print('Generated .dart_tool/package_config.dart containing '
       '${packages.length} packages.');
 }