Version 2.13.0-217.0.dev

Merge commit 'd6824468f90b8e0ec04abde6978a8a04acaa335a' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fe24ae..9dcfa0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,10 @@
   *even if the set is empty* (in which case it just compares the element
   to itself).
 
+#### `dart:developer`
+
+- Added `serverWebSocketUri` property to `ServiceProtocolInfo`.
+
 ### Dart VM
 
 ### Tools
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index e576474..221f315 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 19.0.0
+version: 20.0.0
 description: Logic that is shared between the front_end and analyzer packages.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
 
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
index d072cad..542af9c 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -52,7 +50,7 @@
 
   /// Return the content of the [source] in which the completion is being
   /// requested, or `null` if the content could not be accessed.
-  String get sourceContents;
+  String? get sourceContents;
 
   /// Throw [AbortCompletion] if the completion request has been aborted.
   void checkAborted();
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index e69c357..2c71a1e 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -46,10 +44,10 @@
   ResourceProvider get resourceProvider => result.session.resourceProvider;
 
   @override
-  Source get source => result.unit.declaredElement.source;
+  Source get source => result.unit!.declaredElement!.source;
 
   @override
-  String get sourceContents => result?.content;
+  String? get sourceContents => result.content;
 
   /// Abort the current completion request.
   void abort() {
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index dd3480e..b0c2ac4 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -2,19 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 
 /// Compute a string representing a code completion operation at the
 /// given source and location.
 ///
 /// This string is useful for displaying to users in a diagnostic context.
-String computeCompletionSnippet(String contents, int offset) {
-  if (contents == null ||
-      offset == null ||
-      offset < 0 ||
-      contents.length < offset) {
+String _computeCompletionSnippet(String contents, int offset) {
+  if (offset < 0 || contents.length < offset) {
     return '???';
   }
   var start = offset;
@@ -40,13 +35,17 @@
 
 /// Overall performance of a code completion operation.
 class CompletionPerformance {
-  String path;
+  String? path;
   String snippet = '';
   int suggestionCount = -1;
-  OperationPerformanceImpl _operation;
+  OperationPerformance? _operation;
 
   int get elapsedInMilliseconds {
-    return _operation.elapsed.inMilliseconds;
+    var operation = _operation;
+    if (operation == null) {
+      throw StateError('Access of elapsed time before the operation is run');
+    }
+    return operation.elapsed.inMilliseconds;
   }
 
   String get suggestionCountStr {
@@ -68,6 +67,6 @@
   }
 
   void setContentsAndOffset(String contents, int offset) {
-    snippet = computeCompletionSnippet(contents, offset);
+    snippet = _computeCompletionSnippet(contents, offset);
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 1b6eea7..9fd0c36 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// Utility methods to compute the value of the features used for code
 /// completion.
 import 'dart:math' as math;
@@ -46,27 +44,6 @@
   'string'
 ];
 
-DartType impliedDartTypeWithName(TypeProvider typeProvider, String name) {
-  if (typeProvider == null || name == null || name.isEmpty) {
-    return null;
-  }
-  if (intNames.contains(name)) {
-    return typeProvider.intType;
-  } else if (numNames.contains(name)) {
-    return typeProvider.numType;
-  } else if (listNames.contains(name)) {
-    return typeProvider.listType(typeProvider.dynamicType);
-  } else if (stringNames.contains(name)) {
-    return typeProvider.stringType;
-  } else if (name == 'iterator') {
-    return typeProvider.iterableDynamicType;
-  } else if (name == 'map') {
-    return typeProvider.mapType(
-        typeProvider.dynamicType, typeProvider.dynamicType);
-  }
-  return null;
-}
-
 /// Convert a relevance score (assumed to be between `0.0` and `1.0` inclusive)
 /// to a relevance value between `0` and `1000`.
 int toRelevance(double score) {
@@ -106,6 +83,27 @@
   return (average + 1.0) / 2.0;
 }
 
+DartType? _impliedDartTypeWithName(TypeProvider typeProvider, String name) {
+  if (name.isEmpty) {
+    return null;
+  }
+  if (intNames.contains(name)) {
+    return typeProvider.intType;
+  } else if (numNames.contains(name)) {
+    return typeProvider.numType;
+  } else if (listNames.contains(name)) {
+    return typeProvider.listType(typeProvider.dynamicType);
+  } else if (stringNames.contains(name)) {
+    return typeProvider.stringType;
+  } else if (name == 'iterator') {
+    return typeProvider.iterableDynamicType;
+  } else if (name == 'map') {
+    return typeProvider.mapType(
+        typeProvider.dynamicType, typeProvider.dynamicType);
+  }
+  return null;
+}
+
 /// Return the weighted average of the given [values], applying the given
 /// [weights]. The number of weights must be equal to the number of values.
 double _weightedAverage(List<double> values, List<double> weights) {
@@ -165,7 +163,7 @@
   /// Return the type imposed when completing at the given [offset], where the
   /// offset is within the given [node], or `null` if the context does not
   /// impose any type.
-  DartType computeContextType(AstNode node, int offset) {
+  DartType? computeContextType(AstNode node, int offset) {
     var type = node
         .accept(_ContextTypeVisitor(typeProvider, offset))
         ?.resolveToBound(typeProvider.objectType);
@@ -193,7 +191,7 @@
     } else if (element is FieldElement && element.isEnumConstant) {
       return protocol.ElementKind.ENUM_CONSTANT;
     } else if (element is PropertyAccessorElement) {
-      element = (element as PropertyAccessorElement).variable;
+      element = element.variable;
     }
     var kind = element.kind;
     if (kind == ElementKind.CONSTRUCTOR) {
@@ -229,7 +227,7 @@
   /// Return the value of the _context type_ feature for an element with the
   /// given [elementType] when completing in a location with the given
   /// [contextType].
-  double contextTypeFeature(DartType contextType, DartType elementType) {
+  double contextTypeFeature(DartType? contextType, DartType? elementType) {
     if (contextType == null || elementType == null) {
       // Disable the feature if we don't have both types.
       return 0.0;
@@ -252,8 +250,8 @@
   /// Return the value of the _element kind_ feature for the [element] when
   /// completing at the given [completionLocation]. If a [distance] is given it
   /// will be used to provide finer-grained relevance scores.
-  double elementKindFeature(Element element, String completionLocation,
-      {double distance}) {
+  double elementKindFeature(Element element, String? completionLocation,
+      {double? distance}) {
     if (completionLocation == null) {
       return 0.0;
     }
@@ -327,7 +325,7 @@
 
   /// Return the value of the _keyword_ feature for the [keyword] when
   /// completing at the given [completionLocation].
-  double keywordFeature(String keyword, String completionLocation) {
+  double keywordFeature(String keyword, String? completionLocation) {
     if (completionLocation == null) {
       return 0.0;
     }
@@ -357,7 +355,7 @@
   /// declarations between the local variable and the reference.
   int localVariableDistance(AstNode reference, LocalVariableElement variable) {
     var distance = 0;
-    var node = reference;
+    AstNode? node = reference;
     while (node != null) {
       if (node is ForStatement || node is ForElement) {
         var loopParts = node is ForStatement
@@ -440,7 +438,7 @@
 
   /// Return the value of the _super matches_ feature.
   double superMatchesFeature(
-          String containingMethodName, String proposedMemberName) =>
+          String? containingMethodName, String proposedMemberName) =>
       containingMethodName == null
           ? 0.0
           : (proposedMemberName == containingMethodName ? 1.0 : 0.0);
@@ -451,7 +449,7 @@
     if (distance < 0) {
       return 0.0;
     }
-    return math.pow(0.9, distance);
+    return math.pow(0.9, distance) as double;
   }
 
   /// Return the inheritance distance between the [subclass] and the
@@ -459,7 +457,7 @@
   /// cycles in the type graph.
   ///
   /// This is the implementation of [inheritanceDistance].
-  int _inheritanceDistance(ClassElement subclass, ClassElement superclass,
+  int _inheritanceDistance(ClassElement? subclass, ClassElement superclass,
       Set<ClassElement> visited) {
     if (subclass == null) {
       return -1;
@@ -504,7 +502,7 @@
   _ContextTypeVisitor(this.typeProvider, this.offset);
 
   @override
-  DartType visitAdjacentStrings(AdjacentStrings node) {
+  DartType? visitAdjacentStrings(AdjacentStrings node) {
     if (offset == node.offset) {
       return _visitParent(node);
     }
@@ -512,7 +510,7 @@
   }
 
   @override
-  DartType visitArgumentList(ArgumentList node) {
+  DartType? visitArgumentList(ArgumentList node) {
     if (range
         .endStart(node.leftParenthesis, node.rightParenthesis)
         .contains(offset)) {
@@ -523,7 +521,7 @@
 
       var index = 0;
 
-      DartType typeOfIndexPositionalParameter() {
+      DartType? typeOfIndexPositionalParameter() {
         if (index < parameters.length) {
           var parameter = parameters[index];
           if (parameter.isPositional) {
@@ -533,7 +531,7 @@
         return null;
       }
 
-      Expression previousArgument;
+      Expression? previousArgument;
       for (var argument in node.arguments) {
         if (argument is NamedExpression) {
           if (offset <= argument.offset) {
@@ -560,7 +558,7 @@
   }
 
   @override
-  DartType visitAsExpression(AsExpression node) {
+  DartType? visitAsExpression(AsExpression node) {
     if (node.asOperator.end < offset) {
       return node.expression.staticType;
     }
@@ -568,10 +566,10 @@
   }
 
   @override
-  DartType visitAssertInitializer(AssertInitializer node) {
+  DartType? visitAssertInitializer(AssertInitializer node) {
     if (range
         .endStart(node.leftParenthesis,
-            node.message?.beginToken?.previous ?? node.rightParenthesis)
+            node.message?.beginToken.previous ?? node.rightParenthesis)
         .contains(offset)) {
       return typeProvider.boolType;
     }
@@ -579,10 +577,10 @@
   }
 
   @override
-  DartType visitAssertStatement(AssertStatement node) {
+  DartType? visitAssertStatement(AssertStatement node) {
     if (range
         .endStart(node.leftParenthesis,
-            node.message?.beginToken?.previous ?? node.rightParenthesis)
+            node.message?.beginToken.previous ?? node.rightParenthesis)
         .contains(offset)) {
       return typeProvider.boolType;
     }
@@ -590,7 +588,7 @@
   }
 
   @override
-  DartType visitAssignmentExpression(AssignmentExpression node) {
+  DartType? visitAssignmentExpression(AssignmentExpression node) {
     if (node.operator.end <= offset) {
       // RHS
       if (node.operator.type == TokenType.EQ) {
@@ -599,7 +597,7 @@
       var method = node.staticElement;
       if (method != null) {
         var parameters = method.parameters;
-        if (parameters != null && parameters.isNotEmpty) {
+        if (parameters.isNotEmpty) {
           return parameters[0].type;
         }
       }
@@ -608,12 +606,12 @@
   }
 
   @override
-  DartType visitAwaitExpression(AwaitExpression node) {
+  DartType? visitAwaitExpression(AwaitExpression node) {
     return _visitParent(node);
   }
 
   @override
-  DartType visitBinaryExpression(BinaryExpression node) {
+  DartType? visitBinaryExpression(BinaryExpression node) {
     if (node.operator.end <= offset) {
       return node.rightOperand.staticParameterElement?.type;
     }
@@ -621,15 +619,15 @@
   }
 
   @override
-  DartType visitCascadeExpression(CascadeExpression node) {
-    if (node.target != null && offset == node.target.offset) {
+  DartType? visitCascadeExpression(CascadeExpression node) {
+    if (offset == node.target.offset) {
       return _visitParent(node);
     }
     return null;
   }
 
   @override
-  DartType visitConditionalExpression(ConditionalExpression node) {
+  DartType? visitConditionalExpression(ConditionalExpression node) {
     if (offset <= node.question.offset) {
       return typeProvider.boolType;
     } else {
@@ -638,8 +636,8 @@
   }
 
   @override
-  DartType visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    if (node.equals != null && node.equals.end <= offset) {
+  DartType? visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    if (node.equals.end <= offset) {
       var element = node.fieldName.staticElement;
       if (element is FieldElement) {
         return element.type;
@@ -649,15 +647,16 @@
   }
 
   @override
-  DartType visitDefaultFormalParameter(DefaultFormalParameter node) {
-    if (node.separator != null && node.separator.end <= offset) {
-      return node.parameter.declaredElement.type;
+  DartType? visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var separator = node.separator;
+    if (separator != null && separator.end <= offset) {
+      return node.parameter.declaredElement?.type;
     }
     return null;
   }
 
   @override
-  DartType visitDoStatement(DoStatement node) {
+  DartType? visitDoStatement(DoStatement node) {
     if (range
         .endStart(node.leftParenthesis, node.rightParenthesis)
         .contains(offset)) {
@@ -667,7 +666,7 @@
   }
 
   @override
-  DartType visitExpressionFunctionBody(ExpressionFunctionBody node) {
+  DartType? visitExpressionFunctionBody(ExpressionFunctionBody node) {
     if (range.endEnd(node.functionDefinition, node).contains(offset)) {
       var parent = node.parent;
       if (parent is MethodDeclaration) {
@@ -684,7 +683,7 @@
       } else if (parent is FunctionExpression) {
         var grandparent = parent.parent;
         if (grandparent is FunctionDeclaration) {
-          return BodyInferenceContext.of(parent.body).contextType;
+          return BodyInferenceContext.of(parent.body)?.contextType;
         }
         return _visitParent(parent);
       }
@@ -693,15 +692,15 @@
   }
 
   @override
-  DartType visitFieldDeclaration(FieldDeclaration node) {
-    if (node.fields != null && node.fields.contains(offset)) {
+  DartType? visitFieldDeclaration(FieldDeclaration node) {
+    if (node.fields.contains(offset)) {
       return node.fields.accept(this);
     }
     return null;
   }
 
   @override
-  DartType visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+  DartType? visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     if (range
         .startOffsetEndOffset(node.inKeyword.end, node.end)
         .contains(offset)) {
@@ -716,7 +715,7 @@
   }
 
   @override
-  DartType visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+  DartType? visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
     if (range.endEnd(node.inKeyword, node).contains(offset)) {
       var parent = node.parent;
       if ((parent is ForStatement && parent.awaitKeyword != null) ||
@@ -729,31 +728,27 @@
   }
 
   @override
-  DartType visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
-    if (node.leftSeparator != null &&
-        node.rightSeparator != null &&
-        range
-            .endStart(node.leftSeparator, node.rightSeparator)
-            .contains(offset)) {
+  DartType? visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    if (range
+        .endStart(node.leftSeparator, node.rightSeparator)
+        .contains(offset)) {
       return typeProvider.boolType;
     }
     return null;
   }
 
   @override
-  DartType visitForPartsWithExpression(ForPartsWithExpression node) {
-    if (node.leftSeparator != null &&
-        node.rightSeparator != null &&
-        range
-            .endStart(node.leftSeparator, node.rightSeparator)
-            .contains(offset)) {
+  DartType? visitForPartsWithExpression(ForPartsWithExpression node) {
+    if (range
+        .endStart(node.leftSeparator, node.rightSeparator)
+        .contains(offset)) {
       return typeProvider.boolType;
     }
     return null;
   }
 
   @override
-  DartType visitFunctionExpressionInvocation(
+  DartType? visitFunctionExpressionInvocation(
       FunctionExpressionInvocation node) {
     if (node.function.contains(offset)) {
       return _visitParent(node);
@@ -762,7 +757,7 @@
   }
 
   @override
-  DartType visitIfElement(IfElement node) {
+  DartType? visitIfElement(IfElement node) {
     if (range
         .endStart(node.leftParenthesis, node.rightParenthesis)
         .contains(offset)) {
@@ -772,7 +767,7 @@
   }
 
   @override
-  DartType visitIfStatement(IfStatement node) {
+  DartType? visitIfStatement(IfStatement node) {
     if (range
         .endStart(node.leftParenthesis, node.rightParenthesis)
         .contains(offset)) {
@@ -782,7 +777,7 @@
   }
 
   @override
-  DartType visitIndexExpression(IndexExpression node) {
+  DartType? visitIndexExpression(IndexExpression node) {
     if (range.endStart(node.leftBracket, node.rightBracket).contains(offset)) {
       var parameters = node.staticElement?.parameters;
       if (parameters != null && parameters.isNotEmpty) {
@@ -793,7 +788,7 @@
   }
 
   @override
-  DartType visitIsExpression(IsExpression node) {
+  DartType? visitIsExpression(IsExpression node) {
     if (node.isOperator.end < offset) {
       return node.expression.staticType;
     }
@@ -801,7 +796,7 @@
   }
 
   @override
-  DartType visitLabel(Label node) {
+  DartType? visitLabel(Label node) {
     if (offset == node.offset) {
       return _visitParent(node);
     }
@@ -812,7 +807,7 @@
   }
 
   @override
-  DartType visitListLiteral(ListLiteral node) {
+  DartType? visitListLiteral(ListLiteral node) {
     if (range.endStart(node.leftBracket, node.rightBracket).contains(offset)) {
       return (node.staticType as InterfaceType).typeArguments[0];
     }
@@ -820,10 +815,11 @@
   }
 
   @override
-  DartType visitMapLiteralEntry(MapLiteralEntry node) {
+  DartType? visitMapLiteralEntry(MapLiteralEntry node) {
     var literal = node.thisOrAncestorOfType<SetOrMapLiteral>();
-    if (literal != null && literal.staticType.isDartCoreMap) {
-      var typeArguments = (literal.staticType as InterfaceType).typeArguments;
+    var literalType = literal?.staticType;
+    if (literalType is InterfaceType && literalType.isDartCoreMap) {
+      var typeArguments = literalType.typeArguments;
       if (offset <= node.separator.offset) {
         return typeArguments[0];
       } else {
@@ -834,7 +830,7 @@
   }
 
   @override
-  DartType visitMethodInvocation(MethodInvocation node) {
+  DartType? visitMethodInvocation(MethodInvocation node) {
     if (offset == node.offset) {
       return _visitParent(node);
     }
@@ -842,7 +838,7 @@
   }
 
   @override
-  DartType visitNamedExpression(NamedExpression node) {
+  DartType? visitNamedExpression(NamedExpression node) {
     if (offset == node.offset) {
       return _visitParent(node);
     }
@@ -853,65 +849,66 @@
   }
 
   @override
-  DartType visitParenthesizedExpression(ParenthesizedExpression node) {
+  DartType? visitParenthesizedExpression(ParenthesizedExpression node) {
     return _visitParent(node);
   }
 
   @override
-  DartType visitPostfixExpression(PostfixExpression node) {
+  DartType? visitPostfixExpression(PostfixExpression node) {
     return node.operand.staticParameterElement?.type;
   }
 
   @override
-  DartType visitPrefixedIdentifier(PrefixedIdentifier node) {
+  DartType? visitPrefixedIdentifier(PrefixedIdentifier node) {
     return _visitParent(node);
   }
 
   @override
-  DartType visitPrefixExpression(PrefixExpression node) {
+  DartType? visitPrefixExpression(PrefixExpression node) {
     return node.operand.staticParameterElement?.type;
   }
 
   @override
-  DartType visitPropertyAccess(PropertyAccess node) {
+  DartType? visitPropertyAccess(PropertyAccess node) {
     return _visitParent(node);
   }
 
   @override
-  DartType visitReturnStatement(ReturnStatement node) {
+  DartType? visitReturnStatement(ReturnStatement node) {
     if (node.returnKeyword.end < offset) {
       var functionBody = node.thisOrAncestorOfType<FunctionBody>();
       if (functionBody != null) {
-        return BodyInferenceContext.of(functionBody).contextType;
+        return BodyInferenceContext.of(functionBody)?.contextType;
       }
     }
     return null;
   }
 
   @override
-  DartType visitSetOrMapLiteral(SetOrMapLiteral node) {
+  DartType? visitSetOrMapLiteral(SetOrMapLiteral node) {
     var type = node.staticType;
-    if (range.endStart(node.leftBracket, node.rightBracket).contains(offset) &&
+    if (type is InterfaceType &&
+        range.endStart(node.leftBracket, node.rightBracket).contains(offset) &&
         (type.isDartCoreMap || type.isDartCoreSet)) {
-      return (type as InterfaceType).typeArguments[0];
+      return type.typeArguments[0];
     }
     return null;
   }
 
   @override
-  DartType visitSimpleIdentifier(SimpleIdentifier node) {
+  DartType? visitSimpleIdentifier(SimpleIdentifier node) {
     return _visitParent(node);
   }
 
   @override
-  DartType visitSimpleStringLiteral(SimpleStringLiteral node) {
+  DartType? visitSimpleStringLiteral(SimpleStringLiteral node) {
     // The only completion inside of a String literal would be a directive,
     // where the context type would not be of value.
     return null;
   }
 
   @override
-  DartType visitSpreadElement(SpreadElement node) {
+  DartType? visitSpreadElement(SpreadElement node) {
     if (node.spreadOperator.end <= offset) {
       var currentNode = node.parent;
       while (currentNode != null) {
@@ -931,44 +928,45 @@
   }
 
   @override
-  DartType visitSwitchCase(SwitchCase node) {
+  DartType? visitSwitchCase(SwitchCase node) {
     if (range.endStart(node.keyword, node.colon).contains(offset)) {
       var parent = node.parent;
       if (parent is SwitchStatement) {
-        return parent.expression?.staticType;
+        return parent.expression.staticType;
       }
     }
     return super.visitSwitchCase(node);
   }
 
   @override
-  DartType visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    if (node.variables != null && node.variables.contains(offset)) {
+  DartType? visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    if (node.variables.contains(offset)) {
       return node.variables.accept(this);
     }
     return null;
   }
 
   @override
-  DartType visitVariableDeclaration(VariableDeclaration node) {
-    if (node.equals != null && node.equals.end <= offset) {
+  DartType? visitVariableDeclaration(VariableDeclaration node) {
+    var equals = node.equals;
+    if (equals != null && equals.end <= offset) {
       var parent = node.parent;
       if (parent is VariableDeclarationList) {
         return parent.type?.type ??
-            impliedDartTypeWithName(typeProvider, node.name?.name);
+            _impliedDartTypeWithName(typeProvider, node.name.name);
       }
     }
     return null;
   }
 
   @override
-  DartType visitVariableDeclarationList(VariableDeclarationList node) {
+  DartType? visitVariableDeclarationList(VariableDeclarationList node) {
     for (var varDecl in node.variables) {
-      if (varDecl != null && varDecl.contains(offset)) {
+      if (varDecl.contains(offset)) {
         var equals = varDecl.equals;
         if (equals != null && equals.end <= offset) {
           return node.type?.type ??
-              impliedDartTypeWithName(typeProvider, varDecl.name?.name);
+              _impliedDartTypeWithName(typeProvider, varDecl.name.name);
         }
       }
     }
@@ -976,7 +974,7 @@
   }
 
   @override
-  DartType visitWhileStatement(WhileStatement node) {
+  DartType? visitWhileStatement(WhileStatement node) {
     if (range
         .endStart(node.leftParenthesis, node.rightParenthesis)
         .contains(offset)) {
@@ -986,11 +984,11 @@
   }
 
   @override
-  DartType visitYieldStatement(YieldStatement node) {
+  DartType? visitYieldStatement(YieldStatement node) {
     if (range.endStart(node.yieldKeyword, node.semicolon).contains(offset)) {
       var functionBody = node.thisOrAncestorOfType<FunctionBody>();
       if (functionBody != null) {
-        return BodyInferenceContext.of(functionBody).contextType;
+        return BodyInferenceContext.of(functionBody)?.contextType;
       }
     }
     return null;
@@ -999,7 +997,7 @@
   /// Return the result of visiting the parent of the [node] after setting the
   /// [childNode] to the [node]. Note that this method is destructive in that it
   /// does not reset the [childNode] before returning.
-  DartType _visitParent(AstNode node) {
+  DartType? _visitParent(AstNode node) {
     var parent = node.parent;
     if (parent == null) {
       return null;
@@ -1016,7 +1014,7 @@
 /// Some useful extensions on [ArgumentList] for this computer.
 extension on ArgumentList {
   /// Return the [FunctionType], if there is one, for this [ArgumentList].
-  FunctionType get functionType {
+  FunctionType? get functionType {
     var parent = this.parent;
     if (parent is InstanceCreationExpression) {
       return parent.constructorName.staticElement?.type;
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
index 7fd44bd..7f60edd 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/yaml/producer.dart';
 import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
index e1f1d55..15ef594 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/completion/yaml/producer.dart';
 import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
 import 'package:analyzer/file_system/file_system.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
index c56f9d2..960346f 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -2,12 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
 /// An object that represents the location of a Boolean value.
@@ -117,8 +114,9 @@
   /// Initialize a producer representing a key/value pair in a map.
   const KeyValueProducer();
 
-  /// Returns a producer for values of the given [key].
-  Producer producerForKey(String key);
+  /// Returns a producer for values of the given [key], or `null` if there is
+  /// no registered producer for the [key].
+  Producer? producerForKey(String key);
 }
 
 /// An object that represents the location of an element in a list.
@@ -155,7 +153,7 @@
   const MapProducer(this._children);
 
   @override
-  Producer producerForKey(String key) => _children[key];
+  Producer? producerForKey(String key) => _children[key];
 
   @override
   Iterable<CompletionSuggestion> suggestions(
@@ -198,7 +196,7 @@
   final ResourceProvider resourceProvider;
 
   /// The Pub package service used for looking up package names/versions.
-  final PubPackageService pubPackageService;
+  final PubPackageService? pubPackageService;
 
   /// The absolute path of the file in which completions are being requested.
   final String filePath;
@@ -208,8 +206,8 @@
 
   /// Initialize a newly created completion request.
   YamlCompletionRequest(
-      {@required this.filePath,
-      @required this.precedingText,
-      @required this.resourceProvider,
-      @required this.pubPackageService});
+      {required this.filePath,
+      required this.precedingText,
+      required this.resourceProvider,
+      required this.pubPackageService});
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
index 629db2a..a1e73c3 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/yaml/producer.dart';
 import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
@@ -17,10 +15,12 @@
   @override
   Iterable<CompletionSuggestion> suggestions(
       YamlCompletionRequest request) sync* {
-    final cachedPackages = request.pubPackageService.cachedPackages;
-    var relevance = cachedPackages.length;
-    yield* cachedPackages.map((package) =>
-        packageName('${package.packageName}: ', relevance: relevance--));
+    final cachedPackages = request.pubPackageService?.cachedPackages;
+    if (cachedPackages != null) {
+      var relevance = cachedPackages.length;
+      yield* cachedPackages.map((package) =>
+          packageName('${package.packageName}: ', relevance: relevance--));
+    }
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
index b6bff4c..724475f 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/yaml/producer.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
@@ -19,9 +17,9 @@
   /// completion was requested.
   final ResourceProvider resourceProvider;
 
-  /// A service used for collecting Pub package information. May be null for
+  /// A service used for collecting Pub package information. May be `null` for
   /// generators that do not use Pub packages.
-  final PubPackageService pubPackageService;
+  final PubPackageService? pubPackageService;
 
   /// Initialize a newly created generator to use the [resourceProvider] to
   /// access the content of the file in which completion was requested.
@@ -86,15 +84,21 @@
       }
     }
     final node = nodePath.isNotEmpty ? nodePath.last : null;
-    final replaceNode = node is YamlScalar && node.containsOffset(offset);
-    final replacementOffset = replaceNode ? node.span.start.offset : offset;
-    final replacementLength = replaceNode ? node.span.length : 0;
+    int replacementOffset;
+    int replacementLength;
+    if (node is YamlScalar && node.containsOffset(offset)) {
+      replacementOffset = node.span.start.offset;
+      replacementLength = node.span.length;
+    } else {
+      replacementOffset = offset;
+      replacementLength = 0;
+    }
     return YamlCompletionResults(
         suggestions, replacementOffset, replacementLength);
   }
 
   /// Return the result of parsing the file [content] into a YAML node.
-  YamlNode _parseYaml(String content) {
+  YamlNode? _parseYaml(String content) {
     try {
       return loadYamlNode(content, recover: true);
     } on YamlException {
@@ -108,7 +112,7 @@
   /// and the node containing the offset is the last element in the list.
   List<YamlNode> _pathToOffset(YamlNode root, int offset) {
     var path = <YamlNode>[];
-    var node = root;
+    YamlNode? node = root;
     while (node != null) {
       path.add(node);
       node = node.childContainingOffset(offset);
@@ -118,19 +122,19 @@
 
   /// Return the producer that should be used to produce completion suggestions
   /// for the last node in the node [path].
-  Producer _producerForPath(List<YamlNode> path) {
-    var producer = topLevelProducer;
+  Producer? _producerForPath(List<YamlNode> path) {
+    Producer? producer = topLevelProducer;
     for (var i = 0; i < path.length - 1; i++) {
       var node = path[i];
       if (node is YamlMap && producer is KeyValueProducer) {
         var key = node.keyAtValue(path[i + 1]);
         if (key is YamlScalar) {
-          producer = (producer as KeyValueProducer).producerForKey(key.value);
+          producer = producer.producerForKey(key.value);
         } else {
           return null;
         }
       } else if (node is YamlList && producer is ListProducer) {
-        producer = (producer as ListProducer).element;
+        producer = producer.element;
       } else {
         return producer;
       }
@@ -141,7 +145,7 @@
   /// Return a list of the suggestions that should not be suggested because they
   /// are already in the structure.
   List<String> _siblingsOnPath(List<YamlNode> path) {
-    List<String> siblingsInList(YamlList list, YamlNode currentElement) {
+    List<String> siblingsInList(YamlList list, YamlNode? currentElement) {
       var siblings = <String>[];
       for (var element in list.nodes) {
         if (element != currentElement &&
@@ -153,7 +157,7 @@
       return siblings;
     }
 
-    List<String> siblingsInMap(YamlMap map, YamlNode currentKey) {
+    List<String> siblingsInMap(YamlMap map, YamlNode? currentKey) {
       var siblings = <String>[];
       for (var key in map.nodes.keys) {
         if (key != currentKey && key is YamlScalar && key.value is String) {
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 903f88f..e69df10 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:math';
 
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analysis_server/src/protocol_server.dart'
     show doSourceChange_addElementEdit;
+import 'package:analysis_server/src/utilities/extensions/ast.dart';
 import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -18,6 +18,8 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -26,7 +28,6 @@
     show SourceChange, SourceEdit;
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
-import 'package:meta/meta.dart';
 import 'package:path/path.dart' as pathos;
 
 /// Adds edits to the given [change] that ensure that all the [libraries] are
@@ -38,14 +39,18 @@
   var libUtils = CorrectionUtils(resolveResult);
   var eol = libUtils.endOfLine;
   // Prepare information about existing imports.
-  LibraryDirective libraryDirective;
+  LibraryDirective? libraryDirective;
   var importDirectives = <_ImportDirectiveInfo>[];
   for (var directive in libUtils.unit.directives) {
     if (directive is LibraryDirective) {
       libraryDirective = directive;
     } else if (directive is ImportDirective) {
-      importDirectives.add(_ImportDirectiveInfo(
-          directive.uri.stringValue, directive.offset, directive.end));
+      var uriStr = directive.uri.stringValue;
+      if (uriStr != null) {
+        importDirectives.add(
+          _ImportDirectiveInfo(uriStr, directive.offset, directive.end),
+        );
+      }
     }
   }
 
@@ -126,7 +131,7 @@
 
 /// Climbs up [PrefixedIdentifier] and [PropertyAccess] nodes that include
 /// [node].
-Expression climbPropertyAccess(AstNode node) {
+Expression climbPropertyAccess(Expression node) {
   while (true) {
     var parent = node.parent;
     if (parent is PrefixedIdentifier && parent.identifier == node) {
@@ -156,31 +161,29 @@
 List<SourceRange> getCommentRanges(CompilationUnit unit) {
   var ranges = <SourceRange>[];
   var token = unit.beginToken;
-  while (token != null && token.type != TokenType.EOF) {
-    Token commentToken = token.precedingComments;
+  while (token.type != TokenType.EOF) {
+    var commentToken = token.precedingComments;
     while (commentToken != null) {
       ranges.add(range.token(commentToken));
-      commentToken = commentToken.next;
+      commentToken = commentToken.next as CommentToken?;
     }
-    token = token.next;
+    token = token.next!;
   }
   return ranges;
 }
 
 String getDefaultValueCode(DartType type) {
-  if (type != null) {
-    if (type.isDartCoreBool) {
-      return 'false';
-    }
-    if (type.isDartCoreInt) {
-      return '0';
-    }
-    if (type.isDartCoreDouble) {
-      return '0.0';
-    }
-    if (type.isDartCoreString) {
-      return "''";
-    }
+  if (type.isDartCoreBool) {
+    return 'false';
+  }
+  if (type.isDartCoreInt) {
+    return '0';
+  }
+  if (type.isDartCoreDouble) {
+    return '0.0';
+  }
+  if (type.isDartCoreString) {
+    return "''";
   }
   // no better guess
   return 'null';
@@ -204,10 +207,10 @@
   if (kind == ElementKind.CONSTRUCTOR ||
       kind == ElementKind.FIELD ||
       kind == ElementKind.METHOD) {
-    return '${element.enclosingElement.displayName}.${element.displayName}';
+    return '${element.enclosingElement!.displayName}.${element.displayName}';
   } else if (kind == ElementKind.LIBRARY) {
     // Libraries may not have names, so use a path relative to the context root.
-    final session = element.session;
+    final session = element.session!;
     final pathContext = session.resourceProvider.pathContext;
     final rootPath = session.analysisContext.contextRoot.root.path;
     final library = element as LibraryElement;
@@ -220,13 +223,13 @@
 
 /// If the given [node] is in a class, enum or mixin declaration, return the
 /// declared [ClassElement]. Otherwise return `null`.
-ClassElement getEnclosingClassElement(AstNode node) =>
+ClassElement? getEnclosingClassElement(AstNode node) =>
     node.thisOrAncestorOfType<ClassOrMixinDeclaration>()?.declaredElement;
 
-/// Returns a class or an unit member enclosing the given [node].
-AstNode getEnclosingClassOrUnitMember(AstNode node) {
-  var member = node;
-  while (node != null) {
+/// Returns a class or an unit member enclosing the given [input].
+AstNode? getEnclosingClassOrUnitMember(AstNode input) {
+  var member = input;
+  for (var node in input.withParents) {
     if (node is ClassDeclaration) {
       return member;
     }
@@ -234,14 +237,13 @@
       return member;
     }
     member = node;
-    node = node.parent;
   }
   return null;
 }
 
 /// Return the [ExecutableElement] of the enclosing executable [AstNode].
-ExecutableElement getEnclosingExecutableElement(AstNode node) {
-  while (node != null) {
+ExecutableElement? getEnclosingExecutableElement(AstNode input) {
+  for (var node in input.withParents) {
     if (node is FunctionDeclaration) {
       return node.declaredElement;
     }
@@ -251,14 +253,13 @@
     if (node is MethodDeclaration) {
       return node.declaredElement;
     }
-    node = node.parent;
   }
   return null;
 }
 
 /// Return the enclosing executable [AstNode].
-AstNode getEnclosingExecutableNode(AstNode node) {
-  while (node != null) {
+AstNode? getEnclosingExecutableNode(AstNode input) {
+  for (var node in input.withParents) {
     if (node is FunctionDeclaration) {
       return node;
     }
@@ -268,14 +269,13 @@
     if (node is MethodDeclaration) {
       return node;
     }
-    node = node.parent;
   }
   return null;
 }
 
 /// If the given [node] is in an extension, return the declared
 /// [ExtensionElement]. Otherwise return `null`.
-ExtensionElement getEnclosingExtensionElement(AstNode node) =>
+ExtensionElement? getEnclosingExtensionElement(AstNode node) =>
     node.thisOrAncestorOfType<ExtensionDeclaration>()?.declaredElement;
 
 /// Returns [getExpressionPrecedence] for the parent of [node], or
@@ -283,7 +283,7 @@
 ///
 /// The reason is that `(expr)` is always executed after `expr`.
 Precedence getExpressionParentPrecedence(AstNode node) {
-  var parent = node.parent;
+  var parent = node.parent!;
   if (parent is ParenthesizedExpression) {
     return Precedence.assignment;
   } else if (parent is IndexExpression && parent.index == node) {
@@ -342,7 +342,7 @@
 
 /// Return the [LocalVariableElement] if given [node] is a reference to a local
 /// variable, or `null` in the other case.
-LocalVariableElement getLocalVariableElement(SimpleIdentifier node) {
+LocalVariableElement? getLocalVariableElement(SimpleIdentifier node) {
   var element = node.staticElement;
   if (element is LocalVariableElement) {
     return element;
@@ -351,7 +351,7 @@
 }
 
 /// Return the nearest common ancestor of the given [nodes].
-AstNode getNearestCommonAncestor(List<AstNode> nodes) {
+AstNode? getNearestCommonAncestor(List<AstNode> nodes) {
   // may be no nodes
   if (nodes.isEmpty) {
     return null;
@@ -378,7 +378,7 @@
 
 /// Returns the [Expression] qualifier if given [node] is the name part of a
 /// [PropertyAccess] or a [PrefixedIdentifier]. Maybe `null`.
-Expression getNodeQualifier(SimpleIdentifier node) {
+Expression? getNodeQualifier(SimpleIdentifier node) {
   var parent = node.parent;
   if (parent is MethodInvocation && identical(parent.methodName, node)) {
     return parent.target;
@@ -394,7 +394,7 @@
 
 /// Returns the [ParameterElement] if the given [node] is a reference to a
 /// parameter, or `null` in the other case.
-ParameterElement getParameterElement(SimpleIdentifier node) {
+ParameterElement? getParameterElement(SimpleIdentifier node) {
   var element = node.staticElement;
   if (element is ParameterElement) {
     return element;
@@ -405,29 +405,12 @@
 /// Return parent [AstNode]s from compilation unit (at index "0") to the given
 /// [node].
 List<AstNode> getParents(AstNode node) {
-  // prepare number of parents
-  var numParents = 0;
-  {
-    var current = node.parent;
-    while (current != null) {
-      numParents++;
-      current = current.parent;
-    }
-  }
-  // fill array of parents
-  var parents = List<AstNode>.filled(numParents, null);
-  var current = node.parent;
-  var index = numParents;
-  while (current != null) {
-    parents[--index] = current;
-    current = current.parent;
-  }
-  return parents;
+  return node.withParents.toList().reversed.toList();
 }
 
 /// If given [node] is name of qualified property extraction, returns target
 /// from which this property is extracted, otherwise `null`.
-Expression getQualifiedPropertyTarget(AstNode node) {
+Expression? getQualifiedPropertyTarget(AstNode node) {
   var parent = node.parent;
   if (parent is PrefixedIdentifier) {
     var prefixed = parent;
@@ -446,7 +429,7 @@
 
 /// Returns the given [statement] if not a block, or the first child statement
 /// if a block, or `null` if more than one child.
-Statement getSingleStatement(Statement statement) {
+Statement? getSingleStatement(Statement statement) {
   if (statement is Block) {
     List<Statement> blockStatements = statement.statements;
     if (blockStatements.length != 1) {
@@ -467,11 +450,8 @@
 }
 
 /// Checks if the given [element]'s display name equals to the given [name].
-bool hasDisplayName(Element element, String name) {
-  if (element == null) {
-    return false;
-  }
-  return element.displayName == name;
+bool hasDisplayName(Element? element, String name) {
+  return element?.displayName == name;
 }
 
 /// Checks if given [DartNode] is the left hand side of an assignment, or a
@@ -502,7 +482,7 @@
 /// If the given [expression] is the `expression` property of a
 /// [NamedExpression] then returns this [NamedExpression], otherwise returns
 /// [expression].
-Expression stepUpNamedExpression(Expression expression) {
+Expression? stepUpNamedExpression(Expression? expression) {
   if (expression != null) {
     var parent = expression.parent;
     if (parent is NamedExpression && parent.expression == expression) {
@@ -528,7 +508,7 @@
 /// These inconsistencies may happen as a part of normal workflow, e.g. because
 /// a resource was deleted, or an analysis result was invalidated.
 class CancelCorrectionException {
-  final Object exception;
+  final Object? exception;
 
   CancelCorrectionException({this.exception});
 }
@@ -549,37 +529,39 @@
 
   /// The [ClassElement] the generated code is inserted to, so we can decide if
   /// a type parameter may or may not be used.
-  ClassElement targetClassElement;
+  ClassElement? targetClassElement;
 
-  ExecutableElement targetExecutableElement;
+  ExecutableElement? targetExecutableElement;
 
-  String _endOfLine;
+  String? _endOfLine;
 
   CorrectionUtils(ResolvedUnitResult result)
-      : unit = result.unit,
+      : unit = result.unit!,
         _library = result.libraryElement,
-        _buffer = result.content;
+        _buffer = result.content!;
 
   /// Returns the EOL to use for this [CompilationUnit].
   String get endOfLine {
-    if (_endOfLine == null) {
-      if (_buffer.contains('\r\n')) {
-        _endOfLine = '\r\n';
-      } else {
-        _endOfLine = '\n';
-      }
+    var endOfLine = _endOfLine;
+    if (endOfLine != null) {
+      return endOfLine;
     }
-    return _endOfLine;
+
+    if (_buffer.contains('\r\n')) {
+      return _endOfLine = '\r\n';
+    } else {
+      return _endOfLine = '\n';
+    }
   }
 
   /// Returns the [AstNode] that encloses the given offset.
-  AstNode findNode(int offset) => NodeLocator(offset).searchWithin(unit);
+  AstNode? findNode(int offset) => NodeLocator(offset).searchWithin(unit);
 
   /// Returns names of elements that might conflict with a new local variable
   /// declared at [offset].
   Set<String> findPossibleLocalVariableConflicts(int offset) {
     var conflicts = <String>{};
-    var enclosingNode = findNode(offset);
+    var enclosingNode = findNode(offset)!;
     var enclosingBlock = enclosingNode.thisOrAncestorOfType<Block>();
     if (enclosingBlock != null) {
       var visitor = _CollectReferencedUnprefixedNames();
@@ -747,8 +729,9 @@
     // end
     var endOffset = sourceRange.end;
     var afterEndLineOffset = endOffset;
-    var lineStart = unit.lineInfo.getOffsetOfLine(
-        unit.lineInfo.getLocation(startLineOffset).lineNumber - 1);
+    var lineInfo = unit.lineInfo!;
+    var lineStart = lineInfo
+        .getOffsetOfLine(lineInfo.getLocation(startLineOffset).lineNumber - 1);
     if (lineStart == startLineOffset) {
       // Only consume line ends after the end of the range if there is nothing
       // else on the line containing the beginning of the range. Otherwise this
@@ -814,13 +797,15 @@
   ///
   /// Fills [librariesToImport] with [LibraryElement]s whose elements are
   /// used by the generated source, but not imported.
-  String getTypeSource(DartType type, Set<Source> librariesToImport,
-      {StringBuffer parametersBuffer}) {
-    if (type.aliasElement != null) {
+  String? getTypeSource(DartType type, Set<Source> librariesToImport,
+      {StringBuffer? parametersBuffer}) {
+    var aliasElement = type.aliasElement;
+    var aliasArguments = type.aliasArguments;
+    if (aliasElement != null && aliasArguments != null) {
       return _getTypeCodeElementArguments(
         librariesToImport: librariesToImport,
-        element: type.aliasElement,
-        typeArguments: type.aliasArguments,
+        element: aliasElement,
+        typeArguments: aliasArguments,
       );
     }
 
@@ -888,7 +873,7 @@
       }
       // update line
       if (indentLeft) {
-        line = removeStart(line, indent);
+        line = removeStart(line, indent)!;
       } else {
         line = '$indent$line';
       }
@@ -907,8 +892,8 @@
   /// Return `true` if the given class, mixin, enum or extension [declaration]
   /// has open '{' and close '}' on the same line, e.g. `class X {}`.
   bool isClassWithEmptyBody(CompilationUnitMember declaration) {
-    return getLineThis(_getLeftBracket(declaration).offset) ==
-        getLineThis(_getRightBracket(declaration).offset);
+    return getLineThis(_getLeftBracket(declaration)!.offset) ==
+        getLineThis(_getRightBracket(declaration)!.offset);
   }
 
   /// Return <code>true</code> if [range] contains only whitespace or comments.
@@ -922,12 +907,12 @@
     return TokenUtils.getTokens(trimmedText, unit.featureSet).isEmpty;
   }
 
-  ClassMemberLocation prepareNewClassMemberLocation(
+  ClassMemberLocation? prepareNewClassMemberLocation(
       CompilationUnitMember declaration,
       bool Function(ClassMember existingMember) shouldSkip) {
     var indent = getIndent(1);
     // Find the last target member.
-    ClassMember targetMember;
+    ClassMember? targetMember;
     var members = _getMembers(declaration);
     if (members == null) {
       return null;
@@ -949,10 +934,10 @@
         ? endOfLine
         : '';
     return ClassMemberLocation(
-        endOfLine + indent, _getLeftBracket(declaration).end, suffix);
+        endOfLine + indent, _getLeftBracket(declaration)!.end, suffix);
   }
 
-  ClassMemberLocation prepareNewConstructorLocation(
+  ClassMemberLocation? prepareNewConstructorLocation(
       ClassDeclaration classDeclaration) {
     return prepareNewClassMemberLocation(
         classDeclaration,
@@ -960,13 +945,13 @@
             member is FieldDeclaration || member is ConstructorDeclaration);
   }
 
-  ClassMemberLocation prepareNewFieldLocation(
+  ClassMemberLocation? prepareNewFieldLocation(
       CompilationUnitMember declaration) {
     return prepareNewClassMemberLocation(
         declaration, (member) => member is FieldDeclaration);
   }
 
-  ClassMemberLocation prepareNewGetterLocation(
+  ClassMemberLocation? prepareNewGetterLocation(
       CompilationUnitMember declaration) {
     return prepareNewClassMemberLocation(
         declaration,
@@ -976,7 +961,7 @@
             member is MethodDeclaration && member.isGetter);
   }
 
-  ClassMemberLocation prepareNewMethodLocation(
+  ClassMemberLocation? prepareNewMethodLocation(
       CompilationUnitMember declaration) {
     return prepareNewClassMemberLocation(
         declaration,
@@ -998,7 +983,6 @@
         if (token.type == TokenType.STRING) {
           lineRanges.add(range.token(token));
         }
-        token = token.next;
       }
     }
     // re-indent lines
@@ -1072,7 +1056,7 @@
 
   /// Return the import element used to import given [element] into the library.
   /// May be `null` if was not imported, i.e. declared in the same library.
-  ImportElement _getImportElement(Element element) {
+  ImportElement? _getImportElement(Element element) {
     for (var imp in _library.imports) {
       var definedNames = getImportNamespace(imp);
       if (definedNames.containsValue(element)) {
@@ -1082,7 +1066,7 @@
     return null;
   }
 
-  Token _getLeftBracket(CompilationUnitMember declaration) {
+  Token? _getLeftBracket(CompilationUnitMember declaration) {
     if (declaration is ClassOrMixinDeclaration) {
       return declaration.leftBracket;
     } else if (declaration is ExtensionDeclaration) {
@@ -1091,7 +1075,7 @@
     return null;
   }
 
-  List<ClassMember> _getMembers(CompilationUnitMember declaration) {
+  List<ClassMember>? _getMembers(CompilationUnitMember declaration) {
     if (declaration is ClassOrMixinDeclaration) {
       return declaration.members;
     } else if (declaration is ExtensionDeclaration) {
@@ -1100,7 +1084,7 @@
     return null;
   }
 
-  Token _getRightBracket(CompilationUnitMember declaration) {
+  Token? _getRightBracket(CompilationUnitMember declaration) {
     if (declaration is ClassOrMixinDeclaration) {
       return declaration.rightBracket;
     } else if (declaration is ExtensionDeclaration) {
@@ -1109,10 +1093,10 @@
     return null;
   }
 
-  String _getTypeCodeElementArguments({
-    @required Set<Source> librariesToImport,
-    @required Element element,
-    @required List<DartType> typeArguments,
+  String? _getTypeCodeElementArguments({
+    required Set<Source> librariesToImport,
+    required Element element,
+    required List<DartType> typeArguments,
   }) {
     var sb = StringBuffer();
 
@@ -1126,8 +1110,9 @@
       // ensure import
       var importElement = _getImportElement(element);
       if (importElement != null) {
-        if (importElement.prefix != null) {
-          sb.write(importElement.prefix.displayName);
+        var prefix = importElement.prefix;
+        if (prefix != null) {
+          sb.write(prefix.displayName);
           sb.write('.');
         }
       } else {
@@ -1222,7 +1207,7 @@
     } else if (expression is ParenthesizedExpression) {
       return _invertCondition0(expression.unParenthesized);
     }
-    var type = expression.staticType;
+    var type = expression.typeOrThrow;
     if (type.isDartCoreBool) {
       return _InvertedCondition._simple('!${getNodeText(expression)}');
     }
@@ -1271,7 +1256,7 @@
 class TokenUtils {
   static List<Token> getNodeTokens(AstNode node) {
     var result = <Token>[];
-    for (var token = node.beginToken;; token = token.next) {
+    for (var token = node.beginToken;; token = token.next!) {
       result.add(token);
       if (token == node.endToken) {
         break;
@@ -1285,15 +1270,18 @@
   static List<Token> getTokens(String s, FeatureSet featureSet) {
     try {
       var tokens = <Token>[];
-      var scanner = Scanner(null, CharSequenceReader(s), null)
-        ..configureFeatures(
+      var scanner = Scanner(
+        _SourceMock(),
+        CharSequenceReader(s),
+        AnalysisErrorListener.NULL_LISTENER,
+      )..configureFeatures(
           featureSetForOverriding: featureSet,
           featureSet: featureSet,
         );
       var token = scanner.tokenize();
       while (token.type != TokenType.EOF) {
         tokens.add(token);
-        token = token.next;
+        token = token.next!;
       }
       return tokens;
     } catch (e) {
@@ -1396,3 +1384,8 @@
     }
   }
 }
+
+class _SourceMock implements Source {
+  @override
+  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_api.dart b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
index 2ba45d0..e52dc50 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_api.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
@@ -41,7 +41,7 @@
   };
 
   PubApi(this.instrumentationService, http.Client? httpClient,
-      String envPubHostedUrl)
+      String? envPubHostedUrl)
       : httpClient =
             httpClient != null ? _NoCloseHttpClient(httpClient) : http.Client(),
         _pubHostedUrl = _validPubHostedUrl(envPubHostedUrl);
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
index fd493a4..c6d2078 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
@@ -60,6 +60,19 @@
   bool get inSwitch => thisOrAncestorOfType<SwitchStatement>() != null;
 
   bool get inWhileLoop => thisOrAncestorOfType<WhileStatement>() != null;
+
+  /// Return this node and all its parents.
+  Iterable<AstNode> get withParents sync* {
+    var current = this;
+    while (true) {
+      yield current;
+      var parent = current.parent;
+      if (parent == null) {
+        break;
+      }
+      current = parent;
+    }
+  }
 }
 
 extension ExpressionExtensions on Expression {
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 6e2a9e5..a889acf 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -23,7 +23,7 @@
 
   late String testCode;
   late String testFile;
-  ResolvedUnitResult? testAnalysisResult;
+  late ResolvedUnitResult testAnalysisResult;
   late CompilationUnit testUnit;
   late CompilationUnitElement testUnitElement;
   late LibraryElement testLibraryElement;
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index da9514d..e802863 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/plugin/protocol/protocol_dart.dart';
 import 'package:analyzer/dart/element/element.dart' as engine;
 import 'package:analyzer/src/dart/element/element.dart' as engine;
@@ -88,7 +86,7 @@
       expect(element.name, '_A');
       expect(element.typeParameters, isNull);
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, 27);
         expect(location.length, '_A'.length);
@@ -125,7 +123,7 @@
     expect(element.name, 'myConstructor');
     expect(element.typeParameters, isNull);
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 20);
       expect(location.length, 'myConstructor'.length);
@@ -210,7 +208,7 @@
       expect(element.name, '_E1');
       expect(element.typeParameters, isNull);
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, 17);
         expect(location.length, '_E1'.length);
@@ -246,7 +244,7 @@
       expect(element.kind, ElementKind.ENUM_CONSTANT);
       expect(element.name, 'one');
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, 23);
         expect(location.length, 'one'.length);
@@ -270,7 +268,7 @@
       expect(element.kind, ElementKind.ENUM_CONSTANT);
       expect(element.name, 'three');
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, 44);
         expect(location.length, 'three'.length);
@@ -288,7 +286,7 @@
       expect(element.kind, ElementKind.FIELD);
       expect(element.name, 'index');
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, -1);
         expect(location.length, 'index'.length);
@@ -306,7 +304,7 @@
       expect(element.kind, ElementKind.FIELD);
       expect(element.name, 'values');
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, -1);
         expect(location.length, 'values'.length);
@@ -330,7 +328,7 @@
     expect(element.kind, ElementKind.FIELD);
     expect(element.name, 'myField');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 25);
       expect(location.length, 'myField'.length);
@@ -353,7 +351,7 @@
     expect(element.name, 'F');
     expect(element.typeParameters, '<T>');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 8);
       expect(location.length, 'F'.length);
@@ -376,7 +374,7 @@
     expect(element.name, 'F');
     expect(element.typeParameters, '<out T>');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 8);
       expect(location.length, 'F'.length);
@@ -400,7 +398,7 @@
     expect(element.name, 'F');
     expect(element.typeParameters, '<T>');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 12);
       expect(location.length, 'F'.length);
@@ -424,7 +422,7 @@
     expect(element.kind, ElementKind.GETTER);
     expect(element.name, 'myGetter');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 23);
       expect(location.length, 'myGetter'.length);
@@ -450,7 +448,7 @@
     expect(element.kind, ElementKind.LABEL);
     expect(element.name, 'myLabel');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 9);
       expect(location.length, 'myLabel'.length);
@@ -475,7 +473,7 @@
     expect(element.kind, ElementKind.METHOD);
     expect(element.name, 'myMethod');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 32);
       expect(location.length, 'myGetter'.length);
@@ -499,7 +497,7 @@
       expect(element.name, 'A');
       expect(element.typeParameters, isNull);
       {
-        var location = element.location;
+        var location = element.location!;
         expect(location.file, testFile);
         expect(location.offset, 6);
         expect(location.length, 'A'.length);
@@ -522,7 +520,7 @@
     expect(element.kind, ElementKind.SETTER);
     expect(element.name, 'mySetter');
     {
-      var location = element.location;
+      var location = element.location!;
       expect(location.file, testFile);
       expect(location.offset, 16);
       expect(location.length, 'mySetter'.length);
diff --git a/pkg/analysis_server/test/plugin/test_all.dart b/pkg/analysis_server/test/plugin/test_all.dart
index 66ab7e3..56ce709 100644
--- a/pkg/analysis_server/test/plugin/test_all.dart
+++ b/pkg/analysis_server/test/plugin/test_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'protocol_dart_test.dart' as protocol_dart_test;
diff --git a/pkg/analysis_server/test/search/search_result_test.dart b/pkg/analysis_server/test/search/search_result_test.dart
index 978f0ec..25308ca 100644
--- a/pkg/analysis_server/test/search/search_result_test.dart
+++ b/pkg/analysis_server/test/search/search_result_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:test/test.dart';
@@ -30,7 +28,6 @@
         SearchResultKind.REFERENCE);
     expect(newSearchResultKind_fromEngine(MatchKind.INVOCATION),
         SearchResultKind.INVOCATION);
-    expect(newSearchResultKind_fromEngine(null), SearchResultKind.UNKNOWN);
   }
 
   void test_fromName() {
diff --git a/pkg/analysis_server/test/services/correction/change_test.dart b/pkg/analysis_server/test/services/correction/change_test.dart
index 8616a2c..dead4df 100644
--- a/pkg/analysis_server/test/services/correction/change_test.dart
+++ b/pkg/analysis_server/test/services/correction/change_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
@@ -34,8 +32,7 @@
     change.addEdit('/a.dart', 0, edit2);
     expect(change.edits, hasLength(1));
     {
-      var fileEdit = change.getFileEdit('/a.dart');
-      expect(fileEdit, isNotNull);
+      var fileEdit = change.getFileEdit('/a.dart')!;
       expect(fileEdit.edits, unorderedEquals([edit1, edit2]));
     }
   }
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 3bcc7a9..41c0eec 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
@@ -28,7 +26,7 @@
     await resolveTestCode('class MyClass {}');
     var element = findElement.class_('MyClass');
     // check
-    var location = newLocation_fromElement(element);
+    var location = newLocation_fromElement(element)!;
     expect(location.file, testFile);
     expect(location.offset, 6);
     expect(location.length, 7);
@@ -114,9 +112,10 @@
     var problems = refactoringStatus.problems;
     expect(problems, hasLength(1));
     expect(problems[0].message, 'msg');
-    expect(problems[0].location.file, '/test.dart');
-    expect(problems[0].location.offset, 1);
-    expect(problems[0].location.length, 2);
+    var problemLocation = problems[0].location!;
+    expect(problemLocation.file, '/test.dart');
+    expect(problemLocation.offset, 1);
+    expect(problemLocation.length, 2);
     // add WARNING, resulting severity is still FATAL
     refactoringStatus.addWarning('warning');
     expect(refactoringStatus.severity, RefactoringProblemSeverity.FATAL);
@@ -202,22 +201,22 @@
     refactoringStatus.addError('msgError');
     refactoringStatus.addWarning('msgWarning');
     refactoringStatus.addFatalError('msgFatalError');
+    var problem = refactoringStatus.problem!;
     // get entry
-    {
-      var problem = refactoringStatus.problem;
-      expect(problem.severity, RefactoringProblemSeverity.FATAL);
-      expect(problem.message, 'msgFatalError');
-    }
+    expect(problem.severity, RefactoringProblemSeverity.FATAL);
+    expect(problem.message, 'msgFatalError');
     // get message
-    expect(refactoringStatus.problem.message, 'msgFatalError');
+    expect(problem.message, 'msgFatalError');
   }
 
   void test_newError() {
     var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
     var refactoringStatus = RefactoringStatus.error('msg', location);
+    var problem = refactoringStatus.problem!;
+    var problemLocation = problem.location!;
     expect(refactoringStatus.severity, RefactoringProblemSeverity.ERROR);
-    expect(refactoringStatus.problem.message, 'msg');
-    expect(refactoringStatus.problem.location.file, '/test.dart');
+    expect(problem.message, 'msg');
+    expect(problemLocation.file, '/test.dart');
   }
 
   void test_newFatalError() {
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart
index 203ccf9..fcbee98 100644
--- a/pkg/analysis_server/test/services/correction/util_test.dart
+++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -2,17 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../abstract_single_unit.dart';
-import '../../src/services/correction/assist/assist_processor.dart';
 
 void main() {
   defineReflectiveSuite(() {
@@ -324,8 +322,7 @@
     await addLibraryImports(testAnalysisResult.session, change,
         testLibraryElement, newLibraries.toSet());
     var testEdit = change.getFileEdit(testFile);
-    expect(testEdit, isNotNull);
-    var resultCode = SourceEdit.applySequence(testCode, testEdit.edits);
+    var resultCode = SourceEdit.applySequence(testCode, testEdit!.edits);
     expect(resultCode, expectedCode);
   }
 
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index 21879f2..8d8fa21 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -339,6 +339,7 @@
   }
 
   Future<void> test_folder_outside_workspace_returns_failure() async {
+    await resolveTestFile();
     _createRefactoring('/tmp-new', oldFile: '/tmp');
     // TODO(dantup): These paths should all use convertPath so they're as expected
     // on Windows.
@@ -348,6 +349,7 @@
   }
 
   Future<void> test_nonexistent_file_returns_failure() async {
+    await resolveTestFile();
     _createRefactoring(convertPath('/home/test/test_missing_new.dart'),
         oldFile: convertPath('/home/test/test_missing.dart'));
     await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
@@ -363,6 +365,7 @@
   }
 
   Future<void> test_projectFolder() async {
+    await resolveTestFile();
     _createRefactoring('/home/test2', oldFile: '/home/test');
     await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
         expectedMessage: 'Renaming an analysis root is not supported '
diff --git a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
index 4dbb904..6e27b10 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:test/test.dart';
@@ -19,10 +17,10 @@
 
 @reflectiveTest
 class ContextTypeTest extends FeatureComputerTest {
-  Future<void> assertContextType(String content, String expectedType) async {
+  Future<void> assertContextType(String content, [String? expectedType]) async {
     await completeIn(content);
-    var computer = FeatureComputer(
-        testAnalysisResult.typeSystem, testAnalysisResult.typeProvider);
+    var result = testAnalysisResult;
+    var computer = FeatureComputer(result.typeSystem, result.typeProvider);
     var type = computer.computeContextType(
         completionTarget.containingNode, cursorIndex);
 
@@ -68,7 +66,7 @@
 void g() {
   f(i^:);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_named_beforeLabel() async {
@@ -77,7 +75,7 @@
 void g() {
   f(^i:);
 }
-''', null);
+''');
   }
 
   Future<void>
@@ -118,7 +116,7 @@
 void g() {
   f(j: ^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_named_unresolved_noNamedParameters() async {
@@ -128,7 +126,7 @@
 void g() {
   f(j: ^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_named_with_requiredPositional() async {
@@ -156,7 +154,7 @@
 void g() {
   f(^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_noParameters_whitespace() async {
@@ -165,7 +163,7 @@
 void g() {
   f(  ^  );
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_noParameters_whitespace_left() async {
@@ -174,7 +172,7 @@
 void g() {
   f(  ^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_noParameters_whitespace_right() async {
@@ -183,7 +181,7 @@
 void g() {
   f(^  );
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_positional() async {
@@ -201,7 +199,7 @@
 void g() {
   f(i: ^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_positional_asNamed_beforeColon() async {
@@ -210,7 +208,7 @@
 void g() {
   f(i^:);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_positional_asNamed_beforeLabel() async {
@@ -266,7 +264,7 @@
 void g() {
   f(i: ^);
 }
-''', null);
+''');
   }
 
   Future<void> test_argumentList_requiredPositional_first() async {
@@ -421,7 +419,7 @@
 void g(String s) {
   var x = ^s.length;
 }
-''', null);
+''');
   }
 
   Future<void> test_assignmentExpression_withType() async {
@@ -485,7 +483,7 @@
 class Foo {
   var x =^;
 }
-''', null);
+''');
   }
 
   Future<void> test_fieldDeclaration_var_impliedType_int() async {
@@ -517,7 +515,7 @@
 class Foo {
   var x = ^ ;
 }
-''', null);
+''');
   }
 
   Future<void> test_ifElement() async {
@@ -565,7 +563,7 @@
 void f(int e) {
   var l = ^<int>[e];
 }
-''', null);
+''');
   }
 
   Future<void> test_listLiteral_element() async {
@@ -589,7 +587,7 @@
 void f(int e) {
   var l = <^int>[e];
 }
-''', null);
+''');
   }
 
   Future<void> test_mapLiteralEntry_key() async {
@@ -633,7 +631,7 @@
 void f() {
   var m = ^<int, int>{};
 }
-''', null);
+''');
   }
 
   Future<void> test_setOrMapLiteral_map_element() async {
@@ -649,7 +647,7 @@
 void f() {
   var m = <int, ^int>{};
 }
-''', null);
+''');
   }
 
   Future<void> test_setOrMapLiteral_set_beforeTypeParameter() async {
@@ -657,7 +655,7 @@
 void f() {
   var s = ^<int>{};
 }
-''', null);
+''');
   }
 
   Future<void> test_setOrMapLiteral_set_element() async {
@@ -673,7 +671,7 @@
 void f() {
   var s = <^int>{};
 }
-''', null);
+''');
   }
 
   Future<void> test_topLevelVariableDeclaration_int() async {
@@ -710,26 +708,26 @@
   Future<void> test_topLevelVariableDeclaration_var() async {
     await assertContextType('''
 var x=^;
-''', null);
+''');
   }
 
   Future<void> test_topLevelVariableDeclaration_var_noEqual() async {
     await assertContextType('''
 int x^;
-''', null);
+''');
   }
 
   Future<void> test_topLevelVariableDeclaration_var_whitespace() async {
     await assertContextType('''
 var x=  ^  ;
-''', null);
+''');
   }
 }
 
 abstract class FeatureComputerTest extends AbstractSingleUnitTest {
   int cursorIndex = 0;
 
-  CompletionTarget completionTarget;
+  late CompletionTarget completionTarget;
 
   @override
   bool verifyNoTestUnitErrors = false;
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart
index c9e33de..c86dc28 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/completion/yaml/analysis_options_generator.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:linter/src/rules.dart';
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart
index 3ded781..4634360 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/completion/yaml/fix_data_generator.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 07d2bb7..3df9b93 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
 import 'package:analysis_server/src/services/pub/pub_api.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
@@ -23,9 +21,10 @@
 
 @reflectiveTest
 class PubspecGeneratorTest extends YamlGeneratorTest {
-  MockHttpClient httpClient;
+  late MockHttpClient httpClient;
 
-  PubPackageService pubPackageService;
+  late PubPackageService pubPackageService;
+
   @override
   String get fileName => 'pubspec.yaml';
 
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart b/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart
index e793c59..0d82611 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'analysis_options_generator_test.dart' as analysis_options_generator;
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart b/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart
index 254a855..90a8df5 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
@@ -11,7 +9,7 @@
 
 abstract class YamlGeneratorTest with ResourceProviderMixin {
   /// The completion results produced by [getCompletions].
-  /* late */ List<CompletionSuggestion> results;
+  late List<CompletionSuggestion> results;
 
   /// Return the name of the file being tested.
   String get fileName;
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 547bea6..47717d2 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:io' as io;
 import 'dart:math' as math;
 
@@ -36,7 +34,6 @@
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:args/args.dart';
-import 'package:meta/meta.dart';
 
 import 'output_utilities.dart';
 
@@ -83,7 +80,7 @@
 }
 
 /// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
   if (error != null) {
     print(error);
     print('');
@@ -271,20 +268,20 @@
   InheritanceManager3 inheritanceManager = InheritanceManager3();
 
   /// The library containing the compilation unit being visited.
-  LibraryElement enclosingLibrary;
+  late LibraryElement enclosingLibrary;
 
   /// A flag indicating whether we are currently in a context in which type
   /// parameters are visible.
   bool inGenericContext = false;
 
   /// The type provider associated with the current compilation unit.
-  TypeProvider typeProvider;
+  late TypeProvider typeProvider;
 
   /// The type system associated with the current compilation unit.
-  TypeSystem typeSystem;
+  late TypeSystem typeSystem;
 
   /// The object used to compute the values of features.
-  FeatureComputer featureComputer;
+  late FeatureComputer featureComputer;
 
   /// Initialize a newly created collector to add data points to the given
   /// [data].
@@ -461,10 +458,8 @@
     inGenericContext = inGenericContext || node.typeParameters != null;
     _recordDataForNode('ClassTypeAlias (superclass)', node.superclass);
     var context = 'superclass';
-    if (node.withClause != null) {
-      _recordTokenType('ClassDeclaration ($context)', node.withClause);
-      context = 'with';
-    }
+    _recordTokenType('ClassDeclaration ($context)', node.withClause);
+    context = 'with';
     _recordTokenType('ClassDeclaration ($context)', node.implementsClause);
     super.visitClassTypeAlias(node);
     inGenericContext = wasInGenericContext;
@@ -489,7 +484,7 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    enclosingLibrary = node.declaredElement.library;
+    enclosingLibrary = node.declaredElement!.library;
     typeProvider = enclosingLibrary.typeProvider;
     typeSystem = enclosingLibrary.typeSystem;
     inheritanceManager = InheritanceManager3();
@@ -510,12 +505,6 @@
     data.recordPercentage(
         'Compilation units with at least one prefix', hasPrefix);
     super.visitCompilationUnit(node);
-
-    featureComputer = null;
-    inheritanceManager = null;
-    typeSystem = null;
-    typeProvider = null;
-    enclosingLibrary = null;
   }
 
   @override
@@ -865,13 +854,14 @@
   @override
   void visitImportDirective(ImportDirective node) {
     var context = 'uri';
-    if (node.deferredKeyword != null) {
-      data.recordTokenType(
-          'ImportDirective ($context)', node.deferredKeyword.type);
+    var deferredKeyword = node.deferredKeyword;
+    if (deferredKeyword != null) {
+      data.recordTokenType('ImportDirective ($context)', deferredKeyword.type);
       context = 'deferred';
     }
-    if (node.asKeyword != null) {
-      data.recordTokenType('ImportDirective ($context)', node.asKeyword.type);
+    var asKeyword = node.asKeyword;
+    if (asKeyword != null) {
+      data.recordTokenType('ImportDirective ($context)', asKeyword.type);
       context = 'prefix';
     }
     if (node.configurations.isNotEmpty) {
@@ -977,7 +967,7 @@
     // There are no completions.
     data.recordPercentage(
         'Methods with type parameters', node.typeParameters != null);
-    var element = node.declaredElement;
+    var element = node.declaredElement!;
     if (!element.isStatic && element.enclosingElement is ClassElement) {
       var overriddenMembers = inheritanceManager.getOverridden2(
           element.enclosingElement as ClassElement,
@@ -1293,8 +1283,9 @@
           allowedKeywords: [Keyword.ON]);
       context = 'catch';
     }
-    if (node.finallyKeyword != null) {
-      data.recordTokenType('TryStatement ($context)', node.finallyKeyword.type);
+    var finallyKeyword = node.finallyKeyword;
+    if (finallyKeyword != null) {
+      data.recordTokenType('TryStatement ($context)', finallyKeyword.type);
     }
     super.visitTryStatement(node);
   }
@@ -1329,7 +1320,7 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
-    var keywords = node.parent.parent is FieldDeclaration
+    var keywords = node.parent?.parent is FieldDeclaration
         ? [Keyword.COVARIANT, ...expressionKeywords]
         : expressionKeywords;
     _recordDataForNode('VariableDeclaration (initializer)', node.initializer,
@@ -1375,7 +1366,7 @@
 
   /// Return the context in which the [node] occurs. The [node] is expected to
   /// be the parent of the argument expression.
-  String _argumentListContext(AstNode node) {
+  String _argumentListContext(AstNode? node) {
     if (node is ArgumentList) {
       var parent = node.parent;
       if (parent is InstanceCreationExpression) {
@@ -1412,17 +1403,17 @@
       return 0;
     }
     var depth = 0;
-    var currentElement = element;
+    Element? currentElement = element;
     while (currentElement != enclosingLibrary) {
       depth++;
-      currentElement = currentElement.enclosingElement;
+      currentElement = currentElement?.enclosingElement;
     }
     return depth;
   }
 
   /// Return the first child of the [node] that is neither a comment nor an
   /// annotation.
-  SyntacticEntity _firstChild(AstNode node) {
+  SyntacticEntity? _firstChild(AstNode node) {
     var children = node.childEntities.toList();
     for (var i = 0; i < children.length; i++) {
       var child = children[i];
@@ -1435,13 +1426,13 @@
 
   /// Return the element associated with the left-most identifier that is a
   /// child of the [node].
-  Element _leftMostElement(AstNode node) =>
+  Element? _leftMostElement(AstNode node) =>
       _leftMostIdentifier(node)?.staticElement;
 
   /// Return the left-most child of the [node] if it is a simple identifier, or
   /// `null` if the left-most child is not a simple identifier. Comments and
   /// annotations are ignored for this purpose.
-  SimpleIdentifier _leftMostIdentifier(AstNode node) {
+  SimpleIdentifier? _leftMostIdentifier(AstNode? node) {
     var currentNode = node;
     while (currentNode != null && currentNode is! SimpleIdentifier) {
       var firstChild = _firstChild(currentNode);
@@ -1451,17 +1442,18 @@
         currentNode = null;
       }
     }
-    if (currentNode is SimpleIdentifier && currentNode.inDeclarationContext()) {
-      return null;
+    if (currentNode is SimpleIdentifier &&
+        !currentNode.inDeclarationContext()) {
+      return currentNode;
     }
-    return currentNode;
+    return null;
   }
 
   /// Return the element kind of the element associated with the left-most
   /// identifier that is a child of the [node].
-  ElementKind _leftMostKind(AstNode node) {
+  ElementKind? _leftMostKind(AstNode node) {
     if (node is InstanceCreationExpression) {
-      return convertElementToElementKind(node.constructorName.staticElement);
+      return convertElementToElementKind(node.constructorName.staticElement!);
     }
     var element = _leftMostElement(node);
     if (element == null) {
@@ -1470,17 +1462,17 @@
     if (element is ClassElement) {
       var parent = node.parent;
       if (parent is Annotation && parent.arguments != null) {
-        element = parent.element;
+        element = parent.element!;
       }
     }
     return convertElementToElementKind(element);
   }
 
   /// Return the left-most token that is a child of the [node].
-  Token _leftMostToken(AstNode node) {
-    SyntacticEntity entity = node;
+  Token? _leftMostToken(AstNode node) {
+    SyntacticEntity? entity = node;
     while (entity is AstNode) {
-      entity = _firstChild(entity as AstNode);
+      entity = _firstChild(entity);
     }
     if (entity is Token) {
       return entity;
@@ -1490,7 +1482,7 @@
 
   /// Return the number of functions between the [reference] and the [function]
   /// in which the referenced parameter is declared.
-  int _parameterReferenceDepth(AstNode reference, Element function) {
+  int _parameterReferenceDepth(AstNode? reference, Element function) {
     var depth = 0;
     var node = reference;
     while (node != null) {
@@ -1515,7 +1507,7 @@
     return -1;
   }
 
-  void _recordContextType(DartType type) {
+  void _recordContextType(DartType? type) {
     if (type == null) {
       data.incrementCount('has no context type');
     } else {
@@ -1525,7 +1517,7 @@
 
   /// Record information about the given [node] occurring in the given
   /// [context].
-  void _recordDataForNode(String context, AstNode node,
+  void _recordDataForNode(String context, AstNode? node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     _recordElementKind(context, node);
     if (inGenericContext) {
@@ -1557,7 +1549,7 @@
 
   /// Record the element kind of the element associated with the left-most
   /// identifier that is a child of the [node] in the given [context].
-  void _recordElementKind(String context, AstNode node) {
+  void _recordElementKind(String context, AstNode? node) {
     if (node != null) {
       var kind = _leftMostKind(node);
       if (kind != null) {
@@ -1573,7 +1565,7 @@
 
   /// Record the distance between the static type of the target (the
   /// [targetType]) and the [member] to which the reference was resolved.
-  void _recordMemberDepth(DartType targetType, Element member) {
+  void _recordMemberDepth(DartType? targetType, Element? member) {
     if (member == null) {
       return;
     }
@@ -1593,7 +1585,7 @@
         /// superclasses caused by mixins.
         int getSuperclassDepth() {
           var depth = 0;
-          var currentClass = targetClass;
+          ClassElement? currentClass = targetClass;
           while (currentClass != null) {
             if (currentClass == memberClass) {
               return depth;
@@ -1614,7 +1606,7 @@
         /// includes all of the implicit superclasses caused by mixins.
         int getTargetDepth() {
           var depth = 0;
-          var currentClass = targetClass;
+          ClassElement? currentClass = targetClass;
           while (currentClass != null) {
             depth += currentClass.mixins.length + 1;
             currentClass = currentClass.supertype?.element;
@@ -1663,8 +1655,8 @@
       }
     }
 
-    void recordParameterOverride(ParameterElement overrideParameter,
-        ParameterElement overriddenParameter) {
+    void recordParameterOverride(ParameterElement? overrideParameter,
+        ParameterElement? overriddenParameter) {
       var overrideType = overrideParameter?.type;
       var overriddenType = overriddenParameter?.type;
       if (overrideType == null ||
@@ -1692,11 +1684,11 @@
 
   /// Record the depth of the element associated with the left-most identifier
   /// that is a child of the given [node].
-  void _recordReferenceDepth(AstNode node) {
+  void _recordReferenceDepth(AstNode? node) {
     var reference = _leftMostIdentifier(node);
     var element = reference?.staticElement;
     if (element is ParameterElement) {
-      var definingElement = element.enclosingElement;
+      var definingElement = element.enclosingElement!;
       var depth = _parameterReferenceDepth(node, definingElement);
       _recordDistance('function depth of referenced parameter', depth);
     } else if (element is LocalVariableElement) {
@@ -1705,7 +1697,9 @@
       //  additionally measuring the number of function boundaries that are
       //  crossed and then reporting the distance with a label such as
       //  'local variable ($boundaryCount)'.
-      var distance = featureComputer.localVariableDistance(node, element);
+      var distance = node == null
+          ? -1
+          : featureComputer.localVariableDistance(node, element);
       _recordDistance('distance to local variable', distance);
     } else if (element != null) {
       // TODO(brianwilkerson) We might want to cross reference the depth of
@@ -1718,20 +1712,20 @@
 
   /// Record the number of tokens between a given identifier and the nearest
   /// previous token with the same lexeme.
-  void _recordTokenDistance(AstNode node) {
+  void _recordTokenDistance(AstNode? node) {
     var identifier = _leftMostIdentifier(node);
     if (identifier != null) {
       int distance() {
         var token = identifier.token;
         var lexeme = token.lexeme;
         var distance = 1;
-        token = token.previous;
+        token = token.previous!;
         while (!token.isEof && distance <= 100) {
           if (token.lexeme == lexeme) {
             return distance;
           }
           distance++;
-          token = token.previous;
+          token = token.previous!;
         }
         return -1;
       }
@@ -1742,13 +1736,13 @@
 
   /// Record the token type of the left-most token that is a child of the
   /// [node] in the given [context].
-  void _recordTokenType(String context, AstNode node,
+  void _recordTokenType(String context, AstNode? node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     if (node != null) {
       var token = _leftMostToken(node);
       if (token != null) {
         var type = token.type;
-        if (token.isKeyword && token.keyword.isBuiltInOrPseudo) {
+        if (token.isKeyword && token.keyword!.isBuiltInOrPseudo) {
           // These keywords can be used as identifiers, so determine whether it
           // is being used as a keyword or an identifier.
           if (!allowedKeywords.contains(token.keyword)) {
@@ -1851,7 +1845,7 @@
 
   /// Return the return type of the [element], or `null` if the element doesn't
   /// have a return type.
-  DartType _returnType(Element element) {
+  DartType? _returnType(Element? element) {
     if (element is ExecutableElement) {
       return element.returnType;
     }
@@ -1871,7 +1865,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  Future<void> compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1933,7 +1927,7 @@
   /// output if [verbose] is `true`.
   Future<void> _computeInContext(
       ContextRoot root, RelevanceDataCollector collector,
-      {@required bool verbose}) async {
+      {required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
       includedPaths: root.includedPaths.toList(),
@@ -1950,13 +1944,7 @@
           //
           // Check for errors that cause the file to be skipped.
           //
-          if (resolvedUnitResult == null) {
-            print('File $filePath skipped because resolved unit was null.');
-            if (verbose) {
-              print('');
-            }
-            continue;
-          } else if (resolvedUnitResult.state != ResultState.VALID) {
+          if (resolvedUnitResult.state != ResultState.VALID) {
             print('File $filePath skipped because it could not be analyzed.');
             if (verbose) {
               print('');
@@ -1976,7 +1964,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit.accept(collector);
+          resolvedUnitResult.unit!.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
@@ -2005,7 +1993,7 @@
 
   /// Convert the contents of a single [map] into the values for each row in the
   /// column occupied by the map.
-  List<String> _convertMap<T extends Object>(String context, Map<T, int> map) {
+  List<String> _convertMap<T extends Object>(String context, Map<T, int>? map) {
     var columns = <String>[];
     if (map == null) {
       return columns;
@@ -2062,13 +2050,15 @@
   /// Write a [contextMap] containing one kind of metric data to the [sink].
   void _writeContextMap(
       StringSink sink, Map<String, Map<String, int>> contextMap) {
-    var contexts = contextMap.keys.toList()..sort();
-    for (var i = 0; i < contexts.length; i++) {
+    var entries = contextMap.entries.toList()
+      ..sort((first, second) => first.key.compareTo(second.key));
+    for (var i = 0; i < entries.length; i++) {
       if (i > 0) {
         sink.writeln();
       }
-      var context = contexts[i];
-      var lines = _convertMap(context, contextMap[context]);
+      var context = entries[i].key;
+      var data = entries[i].value;
+      var lines = _convertMap(context, data);
       for (var line in lines) {
         sink.writeln('  $line');
       }
@@ -2132,9 +2122,11 @@
   /// Write a [percentageMap] containing one kind of metric data to the [sink].
   void _writePercentageData(
       StringSink sink, Map<String, _PercentageData> percentageMap) {
-    var names = percentageMap.keys.toList()..sort();
-    for (var name in names) {
-      var data = percentageMap[name];
+    var entries = percentageMap.entries.toList()
+      ..sort((first, second) => first.key.compareTo(second.key));
+    for (var entry in entries) {
+      var name = entry.key;
+      var data = entry.value;
       var total = data.total;
       var value = data.positive;
       var percent = total == 0 ? '  0.0' : _formatPercent(value, total);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 004c776..e5848fa 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:convert';
 import 'dart:io' as io;
 
@@ -29,7 +27,6 @@
 import 'package:analyzer_utilities/package_root.dart' as package_root;
 import 'package:analyzer_utilities/tools.dart';
 import 'package:args/args.dart';
-import 'package:meta/meta.dart';
 
 /// Compute metrics to determine whether they should be used to compute a
 /// relevance score for completion suggestions.
@@ -123,7 +120,7 @@
 }
 
 /// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
   if (error != null) {
     print(error);
     print('');
@@ -195,7 +192,7 @@
         if (key.startsWith('e')) {
           kind = _ElementKind(ElementKind(key.substring(1)));
         } else if (key.startsWith('k')) {
-          kind = _Keyword(Keyword.keywords[key.substring(1)]);
+          kind = _Keyword(Keyword.keywords[key.substring(1)]!);
         } else {
           throw StateError('Invalid initial character in unique key "$key"');
         }
@@ -298,21 +295,21 @@
   final RelevanceData data;
 
   /// The compilation unit in which data is currently being collected.
-  CompilationUnit unit;
+  late CompilationUnit unit;
 
-  InheritanceManager3 inheritanceManager = InheritanceManager3();
+  late InheritanceManager3 inheritanceManager = InheritanceManager3();
 
   /// The library containing the compilation unit being visited.
-  LibraryElement enclosingLibrary;
+  late LibraryElement enclosingLibrary;
 
   /// The type provider associated with the current compilation unit.
-  TypeProvider typeProvider;
+  late TypeProvider typeProvider;
 
   /// The type system associated with the current compilation unit.
-  TypeSystem typeSystem;
+  late TypeSystem typeSystem;
 
   /// The object used to compute the values of features.
-  FeatureComputer featureComputer;
+  late FeatureComputer featureComputer;
 
   /// Initialize a newly created collector to add data points to the given
   /// [data].
@@ -320,7 +317,7 @@
 
   /// Initialize this collector prior to visiting the unit in the [result].
   void initializeFrom(ResolvedUnitResult result) {
-    unit = result.unit;
+    unit = result.unit!;
   }
 
   @override
@@ -468,10 +465,8 @@
   void visitClassTypeAlias(ClassTypeAlias node) {
     _recordDataForNode('ClassTypeAlias_superclass', node.superclass);
     var context = 'superclass';
-    if (node.withClause != null) {
-      _recordKeyword('ClassTypeAlias_$context', node.withClause);
-      context = 'with';
-    }
+    _recordKeyword('ClassTypeAlias_$context', node.withClause);
+    context = 'with';
     _recordKeyword('ClassTypeAlias_$context', node.implementsClause);
     super.visitClassTypeAlias(node);
   }
@@ -490,7 +485,7 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    enclosingLibrary = node.declaredElement.library;
+    enclosingLibrary = node.declaredElement!.library;
     typeProvider = enclosingLibrary.typeProvider;
     typeSystem = enclosingLibrary.typeSystem;
     inheritanceManager = InheritanceManager3();
@@ -505,12 +500,6 @@
           allowedKeywords: declarationKeywords);
     }
     super.visitCompilationUnit(node);
-
-    featureComputer = null;
-    inheritanceManager = null;
-    typeSystem = null;
-    typeProvider = null;
-    enclosingLibrary = null;
   }
 
   @override
@@ -839,12 +828,14 @@
   @override
   void visitImportDirective(ImportDirective node) {
     var context = 'uri';
-    if (node.deferredKeyword != null) {
-      data.recordKeyword('ImportDirective_$context', node.deferredKeyword.type);
+    var deferredKeyword = node.deferredKeyword;
+    if (deferredKeyword != null) {
+      data.recordKeyword('ImportDirective_$context', deferredKeyword.keyword!);
       context = 'deferred';
     }
-    if (node.asKeyword != null) {
-      data.recordKeyword('ImportDirective_$context', node.asKeyword.type);
+    var asKeyword = node.asKeyword;
+    if (asKeyword != null) {
+      data.recordKeyword('ImportDirective_$context', asKeyword.keyword!);
       context = 'prefix';
     }
     if (node.configurations.isNotEmpty) {
@@ -1192,8 +1183,9 @@
           allowedKeywords: [Keyword.ON]);
       context = 'catch';
     }
-    if (node.finallyKeyword != null) {
-      data.recordKeyword('TryStatement_$context', node.finallyKeyword.type);
+    var finallyKeyword = node.finallyKeyword;
+    if (finallyKeyword != null) {
+      data.recordKeyword('TryStatement_$context', finallyKeyword.keyword!);
     }
     super.visitTryStatement(node);
   }
@@ -1228,7 +1220,7 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
-    var keywords = node.parent.parent is FieldDeclaration
+    var keywords = node.parent?.parent is FieldDeclaration
         ? [Keyword.COVARIANT, ...expressionKeywords]
         : expressionKeywords;
     _recordDataForNode('VariableDeclaration_initializer', node.initializer,
@@ -1309,7 +1301,7 @@
 
   /// Return the first child of the [node] that is neither a comment nor an
   /// annotation.
-  SyntacticEntity _firstChild(AstNode node) {
+  SyntacticEntity? _firstChild(AstNode node) {
     var children = node.childEntities.toList();
     for (var i = 0; i < children.length; i++) {
       var child = children[i];
@@ -1322,14 +1314,14 @@
 
   /// Return the element associated with the left-most identifier that is a
   /// child of the [node].
-  Element _leftMostElement(AstNode node) =>
+  Element? _leftMostElement(AstNode node) =>
       _leftMostIdentifier(node)?.staticElement;
 
   /// Return the left-most child of the [node] if it is a simple identifier, or
   /// `null` if the left-most child is not a simple identifier. Comments and
   /// annotations are ignored for this purpose.
-  SimpleIdentifier _leftMostIdentifier(AstNode node) {
-    var currentNode = node;
+  SimpleIdentifier? _leftMostIdentifier(AstNode node) {
+    AstNode? currentNode = node;
     while (currentNode != null && currentNode is! SimpleIdentifier) {
       var firstChild = _firstChild(currentNode);
       if (firstChild is AstNode) {
@@ -1338,18 +1330,19 @@
         currentNode = null;
       }
     }
-    if (currentNode is SimpleIdentifier && currentNode.inDeclarationContext()) {
-      return null;
+    if (currentNode is SimpleIdentifier &&
+        !currentNode.inDeclarationContext()) {
+      return currentNode;
     }
-    return currentNode;
+    return null;
   }
 
   /// Return the element kind of the element associated with the left-most
   /// identifier that is a child of the [node].
-  ElementKind _leftMostKind(AstNode node) {
+  ElementKind? _leftMostKind(AstNode node) {
     if (node is InstanceCreationExpression) {
       return featureComputer
-          .computeElementKind(node.constructorName.staticElement);
+          .computeElementKind(node.constructorName.staticElement!);
     }
     var element = _leftMostElement(node);
     if (element == null) {
@@ -1358,17 +1351,17 @@
     if (element is ClassElement) {
       var parent = node.parent;
       if (parent is Annotation && parent.arguments != null) {
-        element = parent.element;
+        element = parent.element!;
       }
     }
     return featureComputer.computeElementKind(element);
   }
 
   /// Return the left-most token that is a child of the [node].
-  Token _leftMostToken(AstNode node) {
-    SyntacticEntity entity = node;
+  Token? _leftMostToken(AstNode node) {
+    SyntacticEntity? entity = node;
     while (entity is AstNode) {
-      entity = _firstChild(entity as AstNode);
+      entity = _firstChild(entity);
     }
     if (entity is Token) {
       return entity;
@@ -1378,7 +1371,7 @@
 
   /// Record information about the given [node] occurring in the given
   /// [context].
-  void _recordDataForNode(String context, AstNode node,
+  void _recordDataForNode(String context, AstNode? node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     _recordElementKind(context, node);
     _recordKeyword(context, node, allowedKeywords: allowedKeywords);
@@ -1386,7 +1379,7 @@
 
   /// Record the element kind of the element associated with the left-most
   /// identifier that is a child of the [node] in the given [context].
-  void _recordElementKind(String context, AstNode node) {
+  void _recordElementKind(String context, AstNode? node) {
     if (node != null) {
       var kind = _leftMostKind(node);
       if (kind != null) {
@@ -1402,18 +1395,18 @@
 
   /// If the left-most token of the [node] is a keyword, then record that it
   /// occurred in the given [context].
-  void _recordKeyword(String context, AstNode node,
+  void _recordKeyword(String context, AstNode? node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     if (node != null) {
       var token = _leftMostToken(node);
-      if (token.isKeyword) {
-        var keyword = token.type;
+      if (token != null && token.isKeyword) {
+        var keyword = token.keyword!;
         if (keyword == Keyword.NEW) {
           // We don't suggest `new`, so we don't care about the frequency with
           // which it is used.
           return;
-        } else if (token.keyword.isBuiltInOrPseudo &&
-            !allowedKeywords.contains(token.keyword)) {
+        } else if (keyword.isBuiltInOrPseudo &&
+            !allowedKeywords.contains(keyword)) {
           // These keywords can be used as identifiers, so determine whether
           // it is being used as a keyword or an identifier.
           return;
@@ -1436,7 +1429,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  Future<void> compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1453,7 +1446,7 @@
   /// output if [verbose] is `true`.
   Future<void> _computeInContext(
       ContextRoot root, RelevanceDataCollector collector,
-      {@required bool verbose}) async {
+      {required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
       includedPaths: root.includedPaths.toList(),
@@ -1470,13 +1463,7 @@
           //
           // Check for errors that cause the file to be skipped.
           //
-          if (resolvedUnitResult == null) {
-            print('File $filePath skipped because resolved unit was null.');
-            if (verbose) {
-              print('');
-            }
-            continue;
-          } else if (resolvedUnitResult.state != ResultState.VALID) {
+          if (resolvedUnitResult.state != ResultState.VALID) {
             print('File $filePath skipped because it could not be analyzed.');
             if (verbose) {
               print('');
@@ -1497,7 +1484,7 @@
           }
 
           collector.initializeFrom(resolvedUnitResult);
-          resolvedUnitResult.unit.accept(collector);
+          resolvedUnitResult.unit!.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
@@ -1539,9 +1526,11 @@
 ''');
 
     var byKind = data.byKind;
-    var completionLocations = byKind.keys.toList()..sort();
-    for (var completionLocation in completionLocations) {
-      var counts = byKind[completionLocation];
+    var entries = byKind.entries.toList()
+      ..sort((first, second) => first.key.compareTo(second.key));
+    for (var entry in entries) {
+      var completionLocation = entry.key;
+      var counts = entry.value;
       if (_hasElementKind(counts)) {
         var totalCount = _totalCount(counts);
         // TODO(brianwilkerson) If two element kinds have the same count they
@@ -1613,9 +1602,11 @@
 ''');
 
     var byKind = data.byKind;
-    var completionLocations = byKind.keys.toList()..sort();
-    for (var completionLocation in completionLocations) {
-      var counts = byKind[completionLocation];
+    var entries = byKind.entries.toList()
+      ..sort((first, second) => first.key.compareTo(second.key));
+    for (var entry in entries) {
+      var completionLocation = entry.key;
+      var counts = entry.value;
       if (_hasKeyword(counts)) {
         var totalCount = _totalCount(counts);
         // TODO(brianwilkerson) If two keywords have the same count they ought to
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 53c5713..d692e51 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,6 +1,10 @@
-## 1.4.0-dev
+## 1.4.0
 * Deprecated `TypeProvider.nonSubtypableClasses`.
   Use `TypeProvider.isNonSubtypableClass` instead.
+* Added `sdkPath` to `AnalysisContextCollection` constructor.
+* Improved support for generalized type aliases.
+* The feature `nonfunction-type-aliases` is enabled by default in the
+  language version `2.13`.
 
 ## 1.3.0
 * Added `Expression.inConstantContext` to API.
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
index 1f95fa7..fa03a7c 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
@@ -17,10 +17,15 @@
   ///
   /// If a [resourceProvider] is given, then it will be used to access the file
   /// system, otherwise the default resource provider will be used.
-  factory AnalysisContextCollection(
-      {required List<String> includedPaths,
-      List<String>? excludedPaths,
-      ResourceProvider? resourceProvider}) = AnalysisContextCollectionImpl;
+  ///
+  /// If [sdkPath] is given, then Dart SDK at this path will be used, otherwise
+  /// the default Dart SDK will be used.
+  factory AnalysisContextCollection({
+    required List<String> includedPaths,
+    List<String>? excludedPaths,
+    ResourceProvider? resourceProvider,
+    String? sdkPath,
+  }) = AnalysisContextCollectionImpl;
 
   /// Return all of the analysis contexts in this collection.
   List<AnalysisContext> get contexts;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 6d4c820..10eb85c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 1.4.0-dev
+version: 1.4.0
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
@@ -7,7 +7,7 @@
   sdk: '>=2.12.0-0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^19.0.0
+  _fe_analyzer_shared: ^20.0.0
   cli_util: ^0.3.0
   collection: ^1.15.0
   convert: ^3.0.0
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 3cad4cb..5abee00 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -235,6 +235,10 @@
   static final Uri dart__js_helper =
       new Uri(scheme: 'dart', path: '_js_helper');
 
+  /// The URI for 'dart:_late_helper'.
+  static final Uri dart__late_helper =
+      Uri(scheme: 'dart', path: '_late_helper');
+
   /// The URI for 'dart:_rti'.
   static final Uri dart__rti = new Uri(scheme: 'dart', path: '_rti');
 
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 0010e02..81237f8 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -92,6 +92,9 @@
   /// The dart:_js_helper library.
   LibraryEntity get jsHelperLibrary;
 
+  /// The dart:_late_helper library
+  LibraryEntity get lateHelperLibrary;
+
   /// The dart:_interceptors library.
   LibraryEntity get interceptorsLibrary;
 
@@ -440,7 +443,7 @@
 
   FunctionEntity get defineProperty;
 
-  FunctionEntity get throwLateInitializationError;
+  FunctionEntity get throwLateFieldADI;
 
   bool isExtractTypeArguments(FunctionEntity member);
 
@@ -773,6 +776,11 @@
   LibraryEntity get jsHelperLibrary =>
       _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
 
+  LibraryEntity _lateHelperLibrary;
+  @override
+  LibraryEntity get lateHelperLibrary =>
+      _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
+
   LibraryEntity _interceptorsLibrary;
   @override
   LibraryEntity get interceptorsLibrary =>
@@ -1521,6 +1529,9 @@
   ClassEntity _findHelperClass(String name) =>
       _findClass(jsHelperLibrary, name);
 
+  FunctionEntity _findLateHelperFunction(String name) =>
+      _findLibraryMember(lateHelperLibrary, name);
+
   ClassEntity _closureClass;
   @override
   ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
@@ -1787,8 +1798,8 @@
   FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
 
   @override
-  FunctionEntity get throwLateInitializationError =>
-      _findHelperFunction('throwLateInitializationError');
+  FunctionEntity get throwLateFieldADI =>
+      _findLateHelperFunction('throwLateFieldADI');
 
   @override
   bool isExtractTypeArguments(FunctionEntity member) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 327156c..3bd71af 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -407,7 +407,7 @@
   BackendImpact get lazyField {
     return _lazyField ??= new BackendImpact(staticUses: [
       _commonElements.cyclicThrowHelper,
-      _commonElements.throwLateInitializationError
+      _commonElements.throwLateFieldADI,
     ]);
   }
 
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 2d30782..b85031c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -190,7 +190,7 @@
     if (holder[name] === uninitializedSentinel) {
       var value = initializer();
       if (holder[name] !== uninitializedSentinel) {
-        #throwLateInitializationError(name);
+        #throwLateFieldADI(name);
       }
       holder[name] = value;
     }
@@ -766,8 +766,8 @@
       'directAccessTestExpression': js.js(_directAccessTestExpression),
       'cyclicThrow': _emitter
           .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
-      'throwLateInitializationError': _emitter.staticFunctionAccess(
-          _closedWorld.commonElements.throwLateInitializationError),
+      'throwLateFieldADI': _emitter
+          .staticFunctionAccess(_closedWorld.commonElements.throwLateFieldADI),
       'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
       'tearOffCode': new js.Block(buildTearOffCode(
           _options, _emitter, _namer, _closedWorld.commonElements)),
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 5849d77..4d42c97 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -1359,6 +1359,7 @@
       }
       type ??= findIn(Uris.dart_core);
       type ??= findIn(Uris.dart__js_helper);
+      type ??= findIn(Uris.dart__late_helper);
       type ??= findIn(Uris.dart__interceptors);
       type ??= findIn(Uris.dart__native_typed_data);
       type ??= findIn(Uris.dart_collection);
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index a0ce422..d41438e 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -57,6 +57,27 @@
   return allowedNativeTest(uri) || allowedDartLibrary();
 }
 
+int _foldLateLowerings(List<int> lowerings) =>
+    lowerings.fold(LateLowering.none, (a, b) => a | b);
+
+/// Late lowerings which the frontend performs for dart2js.
+const List<int> _allEnabledLateLowerings = [
+  LateLowering.nullableInitializedNonFinalLocal,
+  LateLowering.nonNullableInitializedNonFinalLocal,
+  LateLowering.nullableInitializedFinalLocal,
+  LateLowering.nonNullableInitializedFinalLocal,
+  LateLowering.uninitializedNonFinalStaticField,
+  LateLowering.uninitializedFinalStaticField,
+  LateLowering.initializedNonFinalStaticField,
+  LateLowering.initializedFinalStaticField,
+  LateLowering.uninitializedNonFinalInstanceField,
+  LateLowering.uninitializedFinalInstanceField,
+  LateLowering.initializedNonFinalInstanceField,
+  LateLowering.initializedFinalInstanceField,
+];
+
+final int _enabledLateLowerings = _foldLateLowerings(_allEnabledLateLowerings);
+
 /// A kernel [Target] to configure the Dart Front End for dart2js.
 class Dart2jsTarget extends Target {
   @override
@@ -72,7 +93,7 @@
   bool get enableNoSuchMethodForwarders => true;
 
   @override
-  int get enabledLateLowerings => LateLowering.all;
+  final int enabledLateLowerings = _enabledLateLowerings;
 
   @override
   bool get supportsLateLoweringSentinel => true;
@@ -96,6 +117,7 @@
         'dart:_foreign_helper',
         'dart:_interceptors',
         'dart:_js_helper',
+        'dart:_late_helper',
         'dart:js_util'
       ];
 
@@ -141,8 +163,7 @@
               _nativeClasses)
           .visitLibrary(library);
     }
-    lowering.transformLibraries(
-        libraries, coreTypes, hierarchy, flags.enableNullSafety);
+    lowering.transformLibraries(libraries, coreTypes, hierarchy);
     logger?.call("Lowering transformations performed");
   }
 
@@ -219,6 +240,7 @@
     'dart:_js_embedded_names',
     'dart:_js_helper',
     'dart:_js_names',
+    'dart:_late_helper',
     'dart:_native_typed_data',
     'dart:async',
     'dart:collection',
@@ -241,6 +263,7 @@
     'dart:_js_embedded_names',
     'dart:_js_helper',
     'dart:_js_names',
+    'dart:_late_helper',
     'dart:_native_typed_data',
     'dart:async',
     'dart:collection',
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 6f2ba5f..a677ae9 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -942,6 +942,7 @@
       }
       type ??= findIn(Uris.dart_core);
       type ??= findIn(Uris.dart__js_helper);
+      type ??= findIn(Uris.dart__late_helper);
       type ??= findIn(Uris.dart__interceptors);
       type ??= findIn(Uris.dart__native_typed_data);
       type ??= findIn(Uris.dart_collection);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
new file mode 100644
index 0000000..cf5c62c
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -0,0 +1,112 @@
+// 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.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/library_index.dart';
+import 'package:kernel/type_algebra.dart';
+
+bool _shouldLowerVariable(VariableDeclaration node) =>
+    node.initializer == null && node.isLate;
+
+class LateLowering {
+  final Class _cellClass;
+  final Constructor _cellConstructor;
+
+  final Procedure _readLocal;
+  List<TypeParameter> _readLocalTypeParameters;
+  FunctionType _readLocalTypeWithoutTypeParameters;
+
+  final Procedure _setValue;
+  final Procedure _setFinalLocalValue;
+
+  final Map<VariableDeclaration, VariableDeclaration> _cells = {};
+
+  Member _contextMember;
+
+  LateLowering(LibraryIndex index)
+      : _cellClass = index.getClass('dart:_late_helper', '_Cell'),
+        _cellConstructor = index.getMember('dart:_late_helper', '_Cell', ''),
+        _readLocal = index.getMember('dart:_late_helper', '_Cell', 'readLocal'),
+        _setValue = index.getMember('dart:_late_helper', '_Cell', 'set:value'),
+        _setFinalLocalValue = index.getMember(
+            'dart:_late_helper', '_Cell', 'set:finalLocalValue') {
+    FunctionType _readLocalType = _readLocal.getterType;
+    _readLocalTypeParameters = _readLocalType.typeParameters;
+    _readLocalTypeWithoutTypeParameters = _readLocalType.withoutTypeParameters;
+  }
+
+  VariableDeclaration _variableCell(VariableDeclaration variable) {
+    assert(_shouldLowerVariable(variable));
+    return _cells.putIfAbsent(variable, () {
+      int fileOffset = variable.fileOffset;
+      return VariableDeclaration(variable.name,
+          initializer:
+              ConstructorInvocation(_cellConstructor, Arguments.empty())
+                ..fileOffset = fileOffset,
+          type: InterfaceType(
+              _cellClass, _contextMember.enclosingLibrary.nonNullable),
+          isFinal: true)
+        ..fileOffset = fileOffset;
+    });
+  }
+
+  VariableGet _variableCellAccess(
+          VariableDeclaration variable, int fileOffset) =>
+      VariableGet(_variableCell(variable))..fileOffset = fileOffset;
+
+  TreeNode transformVariableDeclaration(
+      VariableDeclaration node, Member contextMember) {
+    _contextMember = contextMember;
+
+    if (!_shouldLowerVariable(node)) return node;
+
+    // A [VariableDeclaration] being used as a statement must be a direct child
+    // of a [Block].
+    if (node.parent is! Block) return node;
+
+    return _variableCell(node);
+  }
+
+  TreeNode transformVariableGet(VariableGet node, Member contextMember) {
+    _contextMember = contextMember;
+
+    VariableDeclaration variable = node.variable;
+    if (!_shouldLowerVariable(variable)) return node;
+
+    int fileOffset = node.fileOffset;
+    VariableGet cell = _variableCellAccess(variable, fileOffset);
+    List<DartType> typeArguments = [node.promotedType ?? variable.type];
+    return InstanceInvocation(
+        InstanceAccessKind.Instance,
+        cell,
+        _readLocal.name,
+        Arguments(const [], types: typeArguments)..fileOffset = fileOffset,
+        interfaceTarget: _readLocal,
+        functionType:
+            Substitution.fromPairs(_readLocalTypeParameters, typeArguments)
+                .substituteType(_readLocalTypeWithoutTypeParameters))
+      ..fileOffset = fileOffset;
+  }
+
+  TreeNode transformVariableSet(VariableSet node, Member contextMember) {
+    _contextMember = contextMember;
+
+    VariableDeclaration variable = node.variable;
+    if (!_shouldLowerVariable(variable)) return node;
+
+    int fileOffset = node.fileOffset;
+    VariableGet cell = _variableCellAccess(variable, fileOffset);
+    if (variable.isFinal) {
+      return InstanceSet(InstanceAccessKind.Instance, cell,
+          _setFinalLocalValue.name, node.value,
+          interfaceTarget: _setFinalLocalValue)
+        ..fileOffset = fileOffset;
+    } else {
+      return InstanceSet(
+          InstanceAccessKind.Instance, cell, _setValue.name, node.value,
+          interfaceTarget: _setValue)
+        ..fileOffset = fileOffset;
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index 72c4f15..915c5fb 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
@@ -5,52 +5,57 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_environment.dart'
-    show StaticTypeContext, TypeEnvironment;
 import 'factory_specializer.dart';
+import 'late_lowering.dart';
 
 /// dart2js-specific lowering transformations and optimizations combined into a
 /// single transformation pass.
 ///
 /// Each transformation is applied locally to AST nodes of certain types after
 /// transforming children nodes.
-void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
-    ClassHierarchy hierarchy, bool nullSafety) {
-  final transformer = _Lowering(coreTypes, hierarchy, nullSafety);
+void transformLibraries(
+    List<Library> libraries, CoreTypes coreTypes, ClassHierarchy hierarchy) {
+  final transformer = _Lowering(coreTypes, hierarchy);
   libraries.forEach(transformer.visitLibrary);
 }
 
 class _Lowering extends Transformer {
-  final TypeEnvironment env;
-  final bool nullSafety;
   final FactorySpecializer factorySpecializer;
+  final LateLowering _lateLowering;
 
   Member _currentMember;
-  StaticTypeContext _cachedStaticTypeContext;
 
-  _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
-      : env = TypeEnvironment(coreTypes, hierarchy),
-        factorySpecializer = FactorySpecializer(coreTypes, hierarchy);
-
-  // ignore: unused_element
-  StaticTypeContext get _staticTypeContext =>
-      _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
+  _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy)
+      : factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
+        _lateLowering = LateLowering(coreTypes.index);
 
   @override
-  defaultMember(Member node) {
+  TreeNode defaultMember(Member node) {
     _currentMember = node;
-    _cachedStaticTypeContext = null;
-
-    final result = super.defaultMember(node);
-
-    _currentMember = null;
-    _cachedStaticTypeContext = null;
-    return result;
+    return super.defaultMember(node);
   }
 
   @override
-  visitStaticInvocation(StaticInvocation node) {
+  TreeNode visitStaticInvocation(StaticInvocation node) {
     node.transformChildren(this);
     return factorySpecializer.transformStaticInvocation(node, _currentMember);
   }
+
+  @override
+  TreeNode visitVariableDeclaration(VariableDeclaration node) {
+    node.transformChildren(this);
+    return _lateLowering.transformVariableDeclaration(node, _currentMember);
+  }
+
+  @override
+  TreeNode visitVariableGet(VariableGet node) {
+    node.transformChildren(this);
+    return _lateLowering.transformVariableGet(node, _currentMember);
+  }
+
+  @override
+  TreeNode visitVariableSet(VariableSet node) {
+    node.transformChildren(this);
+    return _lateLowering.transformVariableSet(node, _currentMember);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 864f6a8..a729f53 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -463,7 +463,7 @@
                   closedWorld.commonElements.cyclicThrowHelper,
                   CallStructure.ONE_ARG));
               registry.registerStaticUse(new StaticUse.staticInvoke(
-                  closedWorld.commonElements.throwLateInitializationError,
+                  closedWorld.commonElements.throwLateFieldADI,
                   CallStructure.ONE_ARG));
             }
             if (targetElement.isInstanceMember) {
diff --git a/pkg/compiler/test/impact/data/invokes.dart b/pkg/compiler/test/impact/data/invokes.dart
index 6702f0c..a95e117 100644
--- a/pkg/compiler/test/impact/data/invokes.dart
+++ b/pkg/compiler/test/impact/data/invokes.dart
@@ -591,7 +591,7 @@
 /*member: topLevelFieldLazy:
  static=[
   throwCyclicInit(1),
-  throwLateInitializationError(1),
+  throwLateFieldADI(1),
   topLevelFunction1(1)],
  type=[inst:JSNull]
 */
@@ -608,7 +608,7 @@
 /*member: topLevelFieldFinal:
  static=[
   throwCyclicInit(1),
-  throwLateInitializationError(1),
+  throwLateFieldADI(1),
   topLevelFunction1(1)],
  type=[inst:JSNull]
 */
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index dcec2b1..cf0461a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5294,8 +5294,9 @@
       // Inline `debugger()` with no arguments, as a statement if possible,
       // otherwise as an immediately invoked function.
       return isStatement
-          ? js.statement('debugger;')
-          : js.call('(() => { debugger; return true})()');
+          ? js_ast.DebuggerStatement()
+          : js.call(
+              '(() => { #; return true})()', [js_ast.DebuggerStatement()]);
     }
 
     // The signature of `debugger()` is:
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
new file mode 100644
index 0000000..4a82e37
--- /dev/null
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// @dart = 2.9
+
+import 'dart:developer';
+
+void main() {
+  print('1');
+  /*sl:1*/ debugger();
+  print('2');
+  /*sl:2*/ debugger();
+  print('3');
+  foo(/*s:3*/ debugger());
+  print('4');
+  /*sl:4*/ debugger();
+  print('5');
+  foo(/*s:5*/ debugger());
+  print('6');
+  foo(/*s:6*/ debugger());
+}
+
+void foo(bool _) => null;
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 4e0e710..aa44eb0 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -786,6 +786,32 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
+        Message Function(Constant _constant, bool isNonNullableByDefault)>
+    templateConstEvalUnhandledException = const Template<
+            Message Function(Constant _constant, bool isNonNullableByDefault)>(
+        messageTemplate: r"""Unhandled exception: #constant""",
+        withArguments: _withArgumentsConstEvalUnhandledException);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
+    codeConstEvalUnhandledException = const Code<
+        Message Function(Constant _constant, bool isNonNullableByDefault)>(
+  "ConstEvalUnhandledException",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalUnhandledException(
+    Constant _constant, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalUnhandledException,
+      message: """Unhandled exception: ${constant}""" + labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
     Message Function(
         DartType _type,
         String name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 5178dfa..97f21f3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -69,6 +69,7 @@
         templateConstEvalInvalidSymbolName,
         templateConstEvalKeyImplementsEqual,
         templateConstEvalNonConstantVariableGet,
+        templateConstEvalUnhandledException,
         templateConstEvalZeroDivisor;
 
 import 'constant_int_folder.dart';
@@ -1003,6 +1004,24 @@
           ..fileOffset = node.fileOffset;
         errorReporter.reportInvalidExpression(invalid);
         return new UnevaluatedConstant(invalid);
+      } else if (result is _AbortDueToThrowConstant) {
+        final Message message = templateConstEvalUnhandledException
+            .withArguments(result.throwValue, isNonNullableByDefault);
+        final Uri uri = getFileUri(result.node);
+        final int fileOffset = getFileOffset(uri, result.node);
+        final LocatedMessage locatedMessageActualError =
+            message.withLocation(uri, fileOffset, noLength);
+        final List<LocatedMessage> contextMessages = <LocatedMessage>[
+          locatedMessageActualError
+        ];
+        {
+          final Uri uri = getFileUri(node);
+          final int fileOffset = getFileOffset(uri, node);
+          final LocatedMessage locatedMessage = messageConstEvalStartingPoint
+              .withLocation(uri, fileOffset, noLength);
+          errorReporter.report(locatedMessage, contextMessages);
+        }
+        return new UnevaluatedConstant(new InvalidExpression(message.message));
       }
       throw "Unexpected error constant";
     }
@@ -2953,6 +2972,16 @@
   }
 
   @override
+  Constant visitThrow(Throw node) {
+    if (enableConstFunctions) {
+      final Constant value = _evaluateSubexpression(node.expression);
+      if (value is AbortConstant) return value;
+      return new _AbortDueToThrowConstant(node, value);
+    }
+    return defaultExpression(node);
+  }
+
+  @override
   Constant visitInstantiation(Instantiation node) {
     final Constant constant = _evaluateSubexpression(node.expression);
     if (constant is AbortConstant) return constant;
@@ -3329,9 +3358,6 @@
 
   @override
   Constant visitThisExpression(ThisExpression node) => defaultExpression(node);
-
-  @override
-  Constant visitThrow(Throw node) => defaultExpression(node);
 }
 
 class StatementConstantEvaluator extends StatementVisitor<ExecutionStatus> {
@@ -3478,6 +3504,42 @@
   }
 
   @override
+  ExecutionStatus visitTryCatch(TryCatch node) {
+    final ExecutionStatus tryStatus = node.body.accept(this);
+    if (tryStatus is AbortStatus) {
+      final Constant error = tryStatus.error;
+      if (error is _AbortDueToThrowConstant) {
+        final Constant throwConstant = error.throwValue;
+        final DartType defaultType =
+            exprEvaluator.typeEnvironment.coreTypes.objectNonNullableRawType;
+        for (Catch catchClause in node.catches) {
+          if (exprEvaluator.isSubtype(throwConstant, catchClause.guard,
+                  SubtypeCheckMode.withNullabilities) ||
+              catchClause.guard == defaultType) {
+            return exprEvaluator.withNewEnvironment(() {
+              if (catchClause.exception != null) {
+                exprEvaluator.env
+                    .addVariableValue(catchClause.exception, throwConstant);
+              }
+              // TODO(kallentu): Store appropriate stack trace in environment.
+              return catchClause.body.accept(this);
+            });
+          }
+        }
+      }
+    }
+    return tryStatus;
+  }
+
+  @override
+  ExecutionStatus visitTryFinally(TryFinally node) {
+    final ExecutionStatus tryStatus = node.body.accept(this);
+    final ExecutionStatus finallyStatus = node.finalizer.accept(this);
+    if (finallyStatus is! ProceedStatus) return finallyStatus;
+    return tryStatus;
+  }
+
+  @override
   ExecutionStatus visitVariableDeclaration(VariableDeclaration node) {
     Constant value = evaluate(node.initializer);
     if (value is AbortConstant) return new AbortStatus(value);
@@ -3852,6 +3914,63 @@
   }
 }
 
+class _AbortDueToThrowConstant extends AbortConstant {
+  final Throw node;
+  final Constant throwValue;
+
+  _AbortDueToThrowConstant(this.node, this.throwValue);
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  R acceptReference<R>(Visitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression asExpression() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  DartType getType(StaticTypeContext context) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String leakingDebugToString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toStringInternal() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toText(AstTextStrategy strategy) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    throw new UnimplementedError();
+  }
+}
+
 abstract class ErrorReporter {
   const ErrorReporter();
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 624830e..a8965ac 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -135,6 +135,8 @@
 ConstEvalTruncateError/example: Fail
 ConstEvalUnevaluated/analyzerCode: Fail
 ConstEvalUnevaluated/example: Fail
+ConstEvalUnhandledException/analyzerCode: Fail
+ConstEvalUnhandledException/example: Fail
 ConstEvalZeroDivisor/example: Fail
 ConstFieldWithoutInitializer/example: Fail
 ConstructorNotFound/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index b1ae496..0226a47 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -219,6 +219,9 @@
 ConstEvalUnevaluated:
   template: "Couldn't evaluate constant expression."
 
+ConstEvalUnhandledException:
+  template: "Unhandled exception: #constant"
+
 NotConstantExpression:
   template: "#string is not a constant expression."
   analyzerCode: NOT_CONSTANT_EXPRESSION
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart
new file mode 100644
index 0000000..130be7d
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart
@@ -0,0 +1,121 @@
+// 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 try-catch and try-finally with const functions.
+
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+const var2 = fn(1);
+int fn(dynamic error) {
+  try {
+    throw error;
+  } on String {
+    return 0;
+  } catch (e) {
+    return 1;
+  }
+}
+
+const var3 = fn1(10);
+const var4 = fn1("s");
+int fn1(dynamic error) {
+  try {
+    throw error;
+  } on int catch (e) {
+    return e;
+  } catch (e) {
+    return 1;
+  }
+}
+
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+int finallyReturn(dynamic error) {
+  try {
+    if (error != 1) throw error;
+  } on int catch (e) {
+    return e;
+  } catch (e) {
+    return 1;
+  } finally {
+    return 100;
+  }
+}
+
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyReturn1(int x) {
+  try {
+    if (x == 1) {
+      throw x;
+    } else {
+      return 0;
+    }
+  } finally {
+    return 100;
+  }
+}
+
+const var10 = finallyMutate();
+int finallyMutate() {
+  int x = 0;
+  try {
+    return x;
+  } finally {
+    x++;
+  }
+}
+
+const var11 = subtypeFn();
+int subtypeFn() {
+  try {
+    throw 2.5;
+  } on num catch (e) {
+    return 0;
+  }
+}
+
+const var12 = orderFn();
+String orderFn() {
+  String x = "st";
+  try {
+    x += "ri";
+    throw 2;
+  } catch (e) {
+    x += "n";
+  } finally {
+    return x + "g";
+  }
+}
+
+const var13 = notThrowStatement();
+int notThrowStatement() {
+  int count = 0;
+  try {
+    for (int i = 0; i < 1; throw 'a') {
+      count += i;
+    }
+  } catch (e) {
+    return 1;
+  }
+  return 0;
+}
+
+void main() {
+  Expect.equals(var1, 0);
+  Expect.equals(var2, 1);
+  Expect.equals(var3, 10);
+  Expect.equals(var4, 1);
+  Expect.equals(var5, 100);
+  Expect.equals(var6, 100);
+  Expect.equals(var7, 100);
+  Expect.equals(var8, 100);
+  Expect.equals(var9, 100);
+  Expect.equals(var10, 0);
+  Expect.equals(var11, 0);
+  Expect.equals(var12, "string");
+  Expect.equals(var13, 1);
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::String catch(no-exception-var) {
+    return 0;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method fn1(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::int catch(final core::int e) {
+    return e;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method finallyReturn(dynamic error) → core::int {
+  try
+    try {
+      if(!error.{core::Object::==}(1))
+        throw error;
+    }
+    on core::int catch(final core::int e) {
+      return e;
+    }
+    on core::Object catch(final core::Object e) {
+      return 1;
+    }
+  finally {
+    return 100;
+  }
+}
+static method finallyReturn1(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    return 100;
+  }
+}
+static method finallyMutate() → core::int {
+  core::int x = 0;
+  try {
+    return x;
+  }
+  finally {
+    x = x.{core::num::+}(1);
+  }
+}
+static method subtypeFn() → core::int {
+  try {
+    throw 2.5;
+  }
+  on core::num catch(final core::num e) {
+    return 0;
+  }
+}
+static method orderFn() → core::String {
+  core::String x = "st";
+  try
+    try {
+      x = x.{core::String::+}("ri");
+      throw 2;
+    }
+    on core::Object catch(final core::Object e) {
+      x = x.{core::String::+}("n");
+    }
+  finally {
+    return x.{core::String::+}("g");
+  }
+}
+static method notThrowStatement() → core::int {
+  core::int count = 0;
+  try {
+    for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+      count = count.{core::num::+}(i);
+    }
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+  return 0;
+}
+static method main() → void {
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C3, 10);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C5, "string");
+  exp::Expect::equals(#C2, 1);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+  #C3 = 10
+  #C4 = 100
+  #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::String catch(no-exception-var) {
+    return 0;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method fn1(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::int catch(final core::int e) {
+    return e;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method finallyReturn(dynamic error) → core::int {
+  try
+    try {
+      if(!error.{core::Object::==}(1))
+        throw error;
+    }
+    on core::int catch(final core::int e) {
+      return e;
+    }
+    on core::Object catch(final core::Object e) {
+      return 1;
+    }
+  finally {
+    return 100;
+  }
+}
+static method finallyReturn1(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    return 100;
+  }
+}
+static method finallyMutate() → core::int {
+  core::int x = 0;
+  try {
+    return x;
+  }
+  finally {
+    x = x.{core::num::+}(1);
+  }
+}
+static method subtypeFn() → core::int {
+  try {
+    throw 2.5;
+  }
+  on core::num catch(final core::num e) {
+    return 0;
+  }
+}
+static method orderFn() → core::String {
+  core::String x = "st";
+  try
+    try {
+      x = x.{core::String::+}("ri");
+      throw 2;
+    }
+    on core::Object catch(final core::Object e) {
+      x = x.{core::String::+}("n");
+    }
+  finally {
+    return x.{core::String::+}("g");
+  }
+}
+static method notThrowStatement() → core::int {
+  core::int count = 0;
+  try {
+    for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+      count = count.{core::num::+}(i);
+    }
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+  return 0;
+}
+static method main() → void {
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C3, 10);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C5, "string");
+  exp::Expect::equals(#C2, 1);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+  #C3 = 10
+  #C4 = 100
+  #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect
new file mode 100644
index 0000000..f52793b
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+const var2 = fn(1);
+int fn(dynamic error) {}
+const var3 = fn1(10);
+const var4 = fn1("s");
+int fn1(dynamic error) {}
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+int finallyReturn(dynamic error) {}
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyReturn1(int x) {}
+const var10 = finallyMutate();
+int finallyMutate() {}
+const var11 = subtypeFn();
+int subtypeFn() {}
+const var12 = orderFn();
+String orderFn() {}
+const var13 = notThrowStatement();
+int notThrowStatement() {}
+void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f69f0de
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+import "package:expect/expect.dart";
+
+String orderFn() {}
+const var1 = fn("s");
+const var10 = finallyMutate();
+const var11 = subtypeFn();
+const var12 = orderFn();
+const var13 = notThrowStatement();
+const var2 = fn(1);
+const var3 = fn1(10);
+const var4 = fn1("s");
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyMutate() {}
+int finallyReturn(dynamic error) {}
+int finallyReturn1(int x) {}
+int fn(dynamic error) {}
+int fn1(dynamic error) {}
+int notThrowStatement() {}
+int subtypeFn() {}
+void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::String catch(no-exception-var) {
+    return 0;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method fn1(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::int catch(final core::int e) {
+    return e;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method finallyReturn(dynamic error) → core::int {
+  try
+    try {
+      if(!error.{core::Object::==}(1))
+        throw error;
+    }
+    on core::int catch(final core::int e) {
+      return e;
+    }
+    on core::Object catch(final core::Object e) {
+      return 1;
+    }
+  finally {
+    return 100;
+  }
+}
+static method finallyReturn1(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    return 100;
+  }
+}
+static method finallyMutate() → core::int {
+  core::int x = 0;
+  try {
+    return x;
+  }
+  finally {
+    x = x.{core::num::+}(1);
+  }
+}
+static method subtypeFn() → core::int {
+  try {
+    throw 2.5;
+  }
+  on core::num catch(final core::num e) {
+    return 0;
+  }
+}
+static method orderFn() → core::String {
+  core::String x = "st";
+  try
+    try {
+      x = x.{core::String::+}("ri");
+      throw 2;
+    }
+    on core::Object catch(final core::Object e) {
+      x = x.{core::String::+}("n");
+    }
+  finally {
+    return x.{core::String::+}("g");
+  }
+}
+static method notThrowStatement() → core::int {
+  core::int count = 0;
+  try {
+    for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+      count = count.{core::num::+}(i);
+    }
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+  return 0;
+}
+static method main() → void {
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C3, 10);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C5, "string");
+  exp::Expect::equals(#C2, 1);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+  #C3 = 10
+  #C4 = 100
+  #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect
new file mode 100644
index 0000000..36bf8ab
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = self::fn("s");
+static const field core::int var2 = self::fn(1);
+static const field core::int var3 = self::fn1(10);
+static const field core::int var4 = self::fn1("s");
+static const field core::int var5 = self::finallyReturn(10);
+static const field core::int var6 = self::finallyReturn("s");
+static const field core::int var7 = self::finallyReturn(1);
+static const field core::int var8 = self::finallyReturn1(0);
+static const field core::int var9 = self::finallyReturn1(1);
+static const field core::int var10 = self::finallyMutate();
+static const field core::int var11 = self::subtypeFn();
+static const field core::String var12 = self::orderFn();
+static const field core::int var13 = self::notThrowStatement();
+static method fn(dynamic error) → core::int
+  ;
+static method fn1(dynamic error) → core::int
+  ;
+static method finallyReturn(dynamic error) → core::int
+  ;
+static method finallyReturn1(core::int x) → core::int
+  ;
+static method finallyMutate() → core::int
+  ;
+static method subtypeFn() → core::int
+  ;
+static method orderFn() → core::String
+  ;
+static method notThrowStatement() → core::int
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::String catch(no-exception-var) {
+    return 0;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method fn1(dynamic error) → core::int {
+  try {
+    throw error;
+  }
+  on core::int catch(final core::int e) {
+    return e;
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+}
+static method finallyReturn(dynamic error) → core::int {
+  try
+    try {
+      if(!error.{core::Object::==}(1))
+        throw error;
+    }
+    on core::int catch(final core::int e) {
+      return e;
+    }
+    on core::Object catch(final core::Object e) {
+      return 1;
+    }
+  finally {
+    return 100;
+  }
+}
+static method finallyReturn1(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    return 100;
+  }
+}
+static method finallyMutate() → core::int {
+  core::int x = 0;
+  try {
+    return x;
+  }
+  finally {
+    x = x.{core::num::+}(1);
+  }
+}
+static method subtypeFn() → core::int {
+  try {
+    throw 2.5;
+  }
+  on core::num catch(final core::num e) {
+    return 0;
+  }
+}
+static method orderFn() → core::String {
+  core::String x = "st";
+  try
+    try {
+      x = x.{core::String::+}("ri");
+      throw 2;
+    }
+    on core::Object catch(final core::Object e) {
+      x = x.{core::String::+}("n");
+    }
+  finally {
+    return x.{core::String::+}("g");
+  }
+}
+static method notThrowStatement() → core::int {
+  core::int count = 0;
+  try {
+    for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+      count = count.{core::num::+}(i);
+    }
+  }
+  on core::Object catch(final core::Object e) {
+    return 1;
+  }
+  return 0;
+}
+static method main() → void {
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C3, 10);
+  exp::Expect::equals(#C2, 1);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C4, 100);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C1, 0);
+  exp::Expect::equals(#C5, "string");
+  exp::Expect::equals(#C2, 1);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+  #C3 = 10
+  #C4 = 100
+  #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart
new file mode 100644
index 0000000..706483b
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart
@@ -0,0 +1,42 @@
+// 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 erroneous try-catch and try-finally with const functions.
+
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+int finallyThrow(int x) {
+  try {
+    if (x == 1) {
+      throw x;
+    } else {
+      return 0;
+    }
+  } finally {
+    throw 2;
+  }
+}
+
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+int unhandledThrow(dynamic x) {
+  try {
+    throw x;
+  } on String catch (e) {
+    throw e;
+  }
+}
+
+const var5 = unhandledThrow2();
+int unhandledThrow2() {
+  int count = 0;
+  for (int i = 0; i < 1; throw 'a') {
+    count += i;
+  }
+  return 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+//     throw x;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+//     throw e;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+//   for (int i = 0; i < 1; throw 'a') {
+//                          ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    throw 2;
+  }
+}
+static method unhandledThrow(dynamic x) → core::int {
+  try {
+    throw x;
+  }
+  on core::String catch(final core::String e) {
+    throw e;
+  }
+}
+static method unhandledThrow2() → core::int {
+  core::int count = 0;
+  for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+    count = count.{core::num::+}(i);
+  }
+  return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+//     throw x;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+//     throw e;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+//   for (int i = 0; i < 1; throw 'a') {
+//                          ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    throw 2;
+  }
+}
+static method unhandledThrow(dynamic x) → core::int {
+  try {
+    throw x;
+  }
+  on core::String catch(final core::String e) {
+    throw e;
+  }
+}
+static method unhandledThrow2() → core::int {
+  core::int count = 0;
+  for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+    count = count.{core::num::+}(i);
+  }
+  return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect
new file mode 100644
index 0000000..d2e07cc
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+int finallyThrow(int x) {}
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+int unhandledThrow(dynamic x) {}
+const var5 = unhandledThrow2();
+int unhandledThrow2() {}
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..73e5e70
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+const var5 = unhandledThrow2();
+int finallyThrow(int x) {}
+int unhandledThrow(dynamic x) {}
+int unhandledThrow2() {}
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+//     throw x;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+//     throw e;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+//   for (int i = 0; i < 1; throw 'a') {
+//                          ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    throw 2;
+  }
+}
+static method unhandledThrow(dynamic x) → core::int {
+  try {
+    throw x;
+  }
+  on core::String catch(final core::String e) {
+    throw e;
+  }
+}
+static method unhandledThrow2() → core::int {
+  core::int count = 0;
+  for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+    count = count.{core::num::+}(i);
+  }
+  return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect
new file mode 100644
index 0000000..62a0b0a
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = self::finallyThrow(0);
+static const field core::int var2 = self::finallyThrow(1);
+static const field core::int var3 = self::unhandledThrow(0);
+static const field core::int var4 = self::unhandledThrow("string");
+static const field core::int var5 = self::unhandledThrow2();
+static method finallyThrow(core::int x) → core::int
+  ;
+static method unhandledThrow(dynamic x) → core::int
+  ;
+static method unhandledThrow2() → core::int
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+//     throw 2;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+//     throw x;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+//     throw e;
+//     ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+//              ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+//   for (int i = 0; i < 1; throw 'a') {
+//                          ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+  try {
+    if(x.{core::num::==}(1)) {
+      throw x;
+    }
+    else {
+      return 0;
+    }
+  }
+  finally {
+    throw 2;
+  }
+}
+static method unhandledThrow(dynamic x) → core::int {
+  try {
+    throw x;
+  }
+  on core::String catch(final core::String e) {
+    throw e;
+  }
+}
+static method unhandledThrow2() → core::int {
+  core::int count = 0;
+  for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+    count = count.{core::num::+}(i);
+  }
+  return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
index fe43261..e90385e 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
@@ -14,61 +14,39 @@
   self::testNonNullableInitializedFinalLocal();
 }
 static method testNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
-  function #x#set(core::int? #t2) → dynamic
-    return #x = #t2;
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  late core::int? x;
+  x = 42;
+  core::print(x{core::int});
 }
 static method testNonNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x;
-  function #x#get() → core::int
-    return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
-  function #x#set(core::int #t4) → dynamic
-    return #x = #t4;
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  late core::int x;
+  x = 42;
+  core::print(x);
 }
 static method testNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
-  function #x#set(core::int? #t6) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t6;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  late final core::int? x;
+  x = 42;
+  core::print(x{core::int});
 }
 static method testNonNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x;
-  function #x#get() → core::int
-    return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
-  function #x#set(core::int #t8) → dynamic
-    if(#x == null)
-      return #x = #t8;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  late final core::int x;
+  x = 42;
+  core::print(x);
 }
 static method testNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
-  function #x#set(core::int? #t10) → dynamic
-    return #x = #t10;
+    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+  function #x#set(core::int? #t2) → dynamic
+    return #x = #t2;
   core::print(#x#get(){() → core::int?});
   #x#set(42){(core::int?) → dynamic};
   core::print(#x#get(){() → core::int?});
   lowered core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
-  function #y#set(core::int? #t12) → dynamic
-    return #y = #t12;
+    return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+  function #y#set(core::int? #t4) → dynamic
+    return #y = #t4;
   core::print(#y#get(){() → core::int?});
   #y#set(42){(core::int?) → dynamic};
   core::print(#y#get(){() → core::int?});
@@ -76,9 +54,9 @@
 static method testNonNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x;
   function #x#get() → core::int
-    return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
-  function #x#set(core::int #t14) → dynamic
-    return #x = #t14;
+    return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+  function #x#set(core::int #t6) → dynamic
+    return #x = #t6;
   core::print(#x#get(){() → core::int});
   #x#set(42){(core::int) → dynamic};
   core::print(#x#get(){() → core::int});
@@ -86,16 +64,16 @@
 static method testNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
   core::print(#x#get(){() → core::int?});
   lowered final core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+    return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
   core::print(#y#get(){() → core::int?});
 }
 static method testNonNullableInitializedFinalLocal() → void {
   lowered final core::int? #x;
   function #x#get() → core::int
-    return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+    return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
   core::print(#x#get(){() → core::int});
 }
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
index ac86677..54ef534 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_late_helper" as _la;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
@@ -14,61 +15,39 @@
   self::testNonNullableInitializedFinalLocal();
 }
 static method testNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
-  function #x#set(core::int? #t2) → dynamic
-    return #x = #t2;
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::value} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNonNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x;
-  function #x#get() → core::int
-    return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
-  function #x#set(core::int #t4) → dynamic
-    return #x = #t4;
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::value} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
-  function #x#set(core::int? #t6) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t6;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::finalLocalValue} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNonNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x;
-  function #x#get() → core::int
-    return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
-  function #x#set(core::int #t8) → dynamic
-    if(#x == null)
-      return #x = #t8;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::finalLocalValue} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
-  function #x#set(core::int? #t10) → dynamic
-    return #x = #t10;
+    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+  function #x#set(core::int? #t2) → dynamic
+    return #x = #t2;
   core::print(#x#get(){() → core::int?});
   #x#set(42){(core::int?) → dynamic};
   core::print(#x#get(){() → core::int?});
   lowered core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
-  function #y#set(core::int? #t12) → dynamic
-    return #y = #t12;
+    return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+  function #y#set(core::int? #t4) → dynamic
+    return #y = #t4;
   core::print(#y#get(){() → core::int?});
   #y#set(42){(core::int?) → dynamic};
   core::print(#y#get(){() → core::int?});
@@ -76,9 +55,9 @@
 static method testNonNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x;
   function #x#get() → core::int
-    return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
-  function #x#set(core::int #t14) → dynamic
-    return #x = #t14;
+    return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+  function #x#set(core::int #t6) → dynamic
+    return #x = #t6;
   core::print(#x#get(){() → core::int});
   #x#set(42){(core::int) → dynamic};
   core::print(#x#get(){() → core::int});
@@ -86,17 +65,17 @@
 static method testNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
   core::print(#x#get(){() → core::int?});
   lowered final core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+    return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
   core::print(#y#get(){() → core::int?});
 }
 static method testNonNullableInitializedFinalLocal() → void {
   lowered final core::int? #x;
   function #x#get() → core::int
-    return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+    return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
   core::print(#x#get(){() → core::int});
 }
 
@@ -109,4 +88,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
 Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
 Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
-Extra constant evaluation: evaluated: 168, effectively constant: 7
+Extra constant evaluation: evaluated: 130, effectively constant: 7
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
index 26979f0..0e44ebb 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
@@ -14,61 +14,39 @@
   self::testNonNullableInitializedFinalLocal();
 }
 static method testNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
-  function #x#set(core::int? #t2) → dynamic
-    return #x = #t2;
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  late core::int? x;
+  x = 42;
+  core::print(x{core::int});
 }
 static method testNonNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int>();
-  function #x#get() → core::int
-    return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
-  function #x#set(core::int #t4) → dynamic
-    return #x = #t4;
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  late core::int x;
+  x = 42;
+  core::print(x);
 }
 static method testNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
-  function #x#set(core::int? #t6) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t6;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  late final core::int? x;
+  x = 42;
+  core::print(x{core::int});
 }
 static method testNonNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int>();
-  function #x#get() → core::int
-    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
-  function #x#set(core::int #t8) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t8;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  late final core::int x;
+  x = 42;
+  core::print(x);
 }
 static method testNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
-  function #x#set(core::int? #t10) → dynamic
-    return #x = #t10;
+    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+  function #x#set(core::int? #t2) → dynamic
+    return #x = #t2;
   core::print(#x#get(){() → core::int?});
   #x#set(42){(core::int?) → dynamic};
   core::print(#x#get(){() → core::int?});
   lowered core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
-  function #y#set(core::int? #t12) → dynamic
-    return #y = #t12;
+    return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+  function #y#set(core::int? #t4) → dynamic
+    return #y = #t4;
   core::print(#y#get(){() → core::int?});
   #y#set(42){(core::int?) → dynamic};
   core::print(#y#get(){() → core::int?});
@@ -76,9 +54,9 @@
 static method testNonNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int>();
   function #x#get() → core::int
-    return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
-  function #x#set(core::int #t14) → dynamic
-    return #x = #t14;
+    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+  function #x#set(core::int #t6) → dynamic
+    return #x = #t6;
   core::print(#x#get(){() → core::int});
   #x#set(42){(core::int) → dynamic};
   core::print(#x#get(){() → core::int});
@@ -86,16 +64,16 @@
 static method testNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
   core::print(#x#get(){() → core::int?});
   lowered final core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+    return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
   core::print(#y#get(){() → core::int?});
 }
 static method testNonNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int>();
   function #x#get() → core::int
-    return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+    return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
   core::print(#x#get(){() → core::int});
 }
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
index 640d4d4..0d8bf0e 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_late_helper" as _la;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
@@ -14,61 +15,39 @@
   self::testNonNullableInitializedFinalLocal();
 }
 static method testNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
-  function #x#set(core::int? #t2) → dynamic
-    return #x = #t2;
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::value} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNonNullableUninitializedNonFinalLocal() → void {
-  lowered core::int? #x = _in::createSentinel<core::int>();
-  function #x#get() → core::int
-    return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
-  function #x#set(core::int #t4) → dynamic
-    return #x = #t4;
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::value} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int?>();
-  function #x#get() → core::int?
-    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
-  function #x#set(core::int? #t6) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t6;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int?) → dynamic};
-  core::print(#x#get(){() → core::int?});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::finalLocalValue} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNonNullableUninitializedFinalLocal() → void {
-  lowered final core::int? #x = _in::createSentinel<core::int>();
-  function #x#get() → core::int
-    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
-  function #x#set(core::int #t8) → dynamic
-    if(_in::isSentinel(#x))
-      return #x = #t8;
-    else
-      throw new _in::LateError::localAI("x");
-  #x#set(42){(core::int) → dynamic};
-  core::print(#x#get(){() → core::int});
+  final _la::_Cell x = new _la::_Cell::•();
+  x.{_la::_Cell::finalLocalValue} = 42;
+  core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
 }
 static method testNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
-  function #x#set(core::int? #t10) → dynamic
-    return #x = #t10;
+    return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+  function #x#set(core::int? #t2) → dynamic
+    return #x = #t2;
   core::print(#x#get(){() → core::int?});
   #x#set(42){(core::int?) → dynamic};
   core::print(#x#get(){() → core::int?});
   lowered core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
-  function #y#set(core::int? #t12) → dynamic
-    return #y = #t12;
+    return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+  function #y#set(core::int? #t4) → dynamic
+    return #y = #t4;
   core::print(#y#get(){() → core::int?});
   #y#set(42){(core::int?) → dynamic};
   core::print(#y#get(){() → core::int?});
@@ -76,9 +55,9 @@
 static method testNonNullableInitializedNonFinalLocal() → void {
   lowered core::int? #x = _in::createSentinel<core::int>();
   function #x#get() → core::int
-    return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
-  function #x#set(core::int #t14) → dynamic
-    return #x = #t14;
+    return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+  function #x#set(core::int #t6) → dynamic
+    return #x = #t6;
   core::print(#x#get(){() → core::int});
   #x#set(42){(core::int) → dynamic};
   core::print(#x#get(){() → core::int});
@@ -86,17 +65,17 @@
 static method testNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int?>();
   function #x#get() → core::int?
-    return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+    return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
   core::print(#x#get(){() → core::int?});
   lowered final core::int? #y = _in::createSentinel<core::int?>();
   function #y#get() → core::int?
-    return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+    return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
   core::print(#y#get(){() → core::int?});
 }
 static method testNonNullableInitializedFinalLocal() → void {
   lowered final core::int? #x = _in::createSentinel<core::int>();
   function #x#get() → core::int
-    return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+    return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
   core::print(#x#get(){() → core::int});
 }
 
@@ -109,4 +88,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
 Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
 Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
-Extra constant evaluation: evaluated: 172, effectively constant: 7
+Extra constant evaluation: evaluated: 132, effectively constant: 7
diff --git a/pkg/status_file/lib/expectation.dart b/pkg/status_file/lib/expectation.dart
index 6e94845..93979fb 100644
--- a/pkg/status_file/lib/expectation.dart
+++ b/pkg/status_file/lib/expectation.dart
@@ -91,6 +91,11 @@
   static final Expectation nonUtf8Error =
       new Expectation._('NonUtf8Output', group: fail);
 
+  /// The stdout or stderr produced by the test was too long and had to be
+  /// truncated by the test runner.
+  static final Expectation truncatedOutput =
+      new Expectation._('TruncatedOutput', group: fail);
+
   /// The VM exited with the special exit code 252.
   static final Expectation dartkCrash =
       new Expectation._('DartkCrash', group: crash);
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 09134bb..5d8e490 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -53,6 +53,7 @@
     if (hasTimedOut) return Expectation.timeout;
     if (_didFail(testCase)) return Expectation.fail;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     return Expectation.pass;
   }
@@ -64,6 +65,7 @@
     if (hasTimedOut) return Expectation.timeout;
     if (_didFail(testCase)) return Expectation.fail;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     return Expectation.pass;
   }
@@ -117,6 +119,9 @@
 
   bool get hasNonUtf8 => exitCode == nonUtfFakeExitCode;
 
+  /// Whether the command's output was too long and was truncated.
+  bool get truncatedOutput => exitCode == truncatedFakeExitCode;
+
   /// Called when producing output for a test failure to describe this output.
   void describe(TestCase testCase, Progress progress, OutputWriter output) {
     output.subsection("exit code");
@@ -335,6 +340,7 @@
     }
 
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // Multitests are handled specially.
     if (testCase.hasRuntimeError) {
@@ -354,6 +360,7 @@
     }
 
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
     return _outcome;
   }
 
@@ -622,6 +629,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     List<StaticError> errors;
     try {
@@ -683,6 +691,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     List<StaticError> errors;
     try {
@@ -791,6 +800,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     if (exitCode != 0) return Expectation.fail;
     for (var line in decodeUtf8(stdout).split('\n')) {
@@ -807,6 +817,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     if (exitCode != 0) return Expectation.fail;
     for (var line in decodeUtf8(stdout).split('\n')) {
@@ -836,6 +847,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     if (testCase.hasCompileError) {
       if (testCase.hasSyntaxError) {
@@ -861,6 +873,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
     if (hasSyntaxError) return Expectation.syntaxError;
     if (exitCode != 0) return Expectation.syntaxError;
     return Expectation.pass;
@@ -884,6 +897,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // Multitests are handled specially.
     if (testCase.hasCompileError) {
@@ -924,6 +938,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // The actual outcome depends on the exitCode.
     if (exitCode == _compileErrorExitCode) return Expectation.compileTimeError;
@@ -986,6 +1001,7 @@
           : Expectation.timeout;
     }
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // Handle dart2js specific crash detection
     if (exitCode == _crashExitCode ||
@@ -1010,6 +1026,7 @@
           : Expectation.timeout;
     }
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // Handle dart2js specific crash detection
     if (exitCode == _crashExitCode ||
@@ -1112,6 +1129,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // If it's a static error test, validate the exact errors.
     if (testCase.testFile.isStaticErrorTest) {
@@ -1134,6 +1152,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // If it's a static error test, validate the exact errors.
     if (testCase.testFile.isStaticErrorTest) {
@@ -1185,6 +1204,7 @@
     if (hasCrashed) return Expectation.dartkCrash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // If the frontend had an uncaught exception, then we'll consider this a
     // crash.
@@ -1227,6 +1247,7 @@
     if (hasCrashed) return Expectation.dartkCrash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     // If the frontend had an uncaught exception, then we'll consider this a
     // crash.
@@ -1267,6 +1288,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     if (testCase.hasRuntimeError) {
       if (exitCode != 0) return Expectation.pass;
@@ -1284,6 +1306,7 @@
     if (hasCrashed) return Expectation.crash;
     if (hasTimedOut) return Expectation.timeout;
     if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
 
     if (exitCode != 0) return Expectation.runtimeError;
     var output = decodeUtf8(stdout);
@@ -1435,7 +1458,11 @@
   void describe(TestCase testCase, Progress progress, OutputWriter output) {
     // Handle static error test output specially. We don't want to show the raw
     // stdout if we can give the user the parsed expectations instead.
-    if (testCase.testFile.isStaticErrorTest && !hasCrashed && !hasTimedOut) {
+    if (testCase.testFile.isStaticErrorTest &&
+        !hasCrashed &&
+        !hasTimedOut &&
+        !hasNonUtf8 &&
+        !truncatedOutput) {
       try {
         _validateExpectedErrors(testCase, output);
       } catch (_) {
@@ -1444,19 +1471,21 @@
         super.describe(testCase, progress, output);
         return;
       }
-    }
 
-    // Don't show the "raw" output unless something strange happened or the
-    // user explicitly requests all the output.
-    if (hasTimedOut ||
-        hasCrashed ||
-        !testCase.testFile.isStaticErrorTest ||
-        progress == Progress.verbose) {
+      // Always show the raw output when specifically requested.
+      if (progress == Progress.verbose) {
+        super.describe(testCase, progress, output);
+      }
+    } else {
+      // Something strange happened, so show the raw output.
       super.describe(testCase, progress, output);
     }
   }
 
   Expectation result(TestCase testCase) {
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
+
     // If it's a static error test, validate the exact errors.
     if (testCase.testFile.isStaticErrorTest) {
       return _validateExpectedErrors(testCase);
@@ -1466,6 +1495,9 @@
   }
 
   Expectation realResult(TestCase testCase) {
+    if (hasNonUtf8) return Expectation.nonUtf8Error;
+    if (truncatedOutput) return Expectation.truncatedOutput;
+
     // If it's a static error test, validate the exact errors.
     if (testCase.testFile.isStaticErrorTest) {
       return _validateExpectedErrors(testCase);
diff --git a/pkg/test_runner/lib/src/output_log.dart b/pkg/test_runner/lib/src/output_log.dart
index 35b5b258..fa8caae 100644
--- a/pkg/test_runner/lib/src/output_log.dart
+++ b/pkg/test_runner/lib/src/output_log.dart
@@ -6,85 +6,61 @@
 import 'dart:convert';
 import 'dart:io';
 
-/// An OutputLog records the output from a test, but truncates it if
-/// it is longer than [_maxHead] characters, and just keeps the head and
-/// the last [_tailLength] characters of the output.
-class OutputLog implements StreamConsumer<List<int>> {
-  static const _maxHead = 500 * 1024;
-  static const _tailLength = 10 * 1024;
+const _nonUtf8Error = '[test.dart: This test output contains non-UTF8 data]';
+const _truncatedError =
+    '[test.dart: This test output was too long and was truncated here.';
 
-  List<int> _head = [];
-  List<int> _tail;
-  List<int> complete;
-  bool _dataDropped = false;
+/// Records the output from a test.
+class OutputLog implements StreamConsumer<List<int>> {
+  // TODO(45618): Reduce this if language_2/unsorted/disassemble_test is fixed
+  // to produce less output and any other large-output tests are fixed.
+  static const _maxLength = 10 * 1024 * 1024;
+
+  final List<int> _data = [];
   StreamSubscription _subscription;
 
-  bool _hasNonUtf8 = false;
-  bool get hasNonUtf8 => _hasNonUtf8;
+  bool get hasNonUtf8 => _hasNonUtf8 ??= _checkUtf8();
+  bool _hasNonUtf8;
+
+  bool get wasTruncated => _wasTruncated;
+  bool _wasTruncated = false;
+
+  List<int> get bytes => _data;
 
   void add(List<int> data) {
-    if (complete != null) {
-      throw StateError("Cannot add to OutputLog after calling toList");
+    if (_hasNonUtf8 != null) {
+      throw StateError("Cannot add to OutputLog after accessing bytes.");
     }
-    if (_tail == null) {
-      _head.addAll(data);
-      if (_head.length > _maxHead) {
-        _tail = _head.sublist(_maxHead);
-        _head.length = _maxHead;
-      }
+
+    // Discard additional output after we've reached the limit.
+    if (_wasTruncated) return;
+
+    if (_data.length + data.length > _maxLength) {
+      _data.addAll(data.take(_maxLength - _data.length));
+      _data.addAll(utf8.encode(_truncatedError));
+      _wasTruncated = true;
     } else {
-      _tail.addAll(data);
-    }
-    if (_tail != null && _tail.length > 2 * _tailLength) {
-      _tail = _truncatedTail();
-      _dataDropped = true;
+      _data.addAll(data);
     }
   }
 
-  List<int> _truncatedTail() => _tail.length > _tailLength
-      ? _tail.sublist(_tail.length - _tailLength)
-      : _tail;
+  void clear() {
+    _data.clear();
+  }
 
-  void _checkUtf8(List<int> data) {
+  bool _checkUtf8() {
     try {
-      utf8.decode(data, allowMalformed: false);
+      utf8.decode(_data, allowMalformed: false);
+      return false;
     } on FormatException {
-      _hasNonUtf8 = true;
-      var malformed = utf8.decode(data, allowMalformed: true);
-      data
-        ..clear()
-        ..addAll(utf8.encode(malformed))
-        ..addAll("""
-*****************************************************************************
-test.dart: The output of this test contained non-UTF8 formatted data.
-*****************************************************************************
-"""
-            .codeUnits);
+      var malformed = utf8.decode(_data, allowMalformed: true);
+      _data.clear();
+      _data.addAll(utf8.encode(malformed));
+      _data.addAll(utf8.encode(_nonUtf8Error));
+      return true;
     }
   }
 
-  List<int> toList() {
-    if (complete == null) {
-      complete = _head;
-      if (_dataDropped) {
-        complete.addAll("""
-*****************************************************************************
-test.dart: Data was removed due to excessive length. If you need the limit to
-be increased, please contact dart-engprod or file an issue.
-*****************************************************************************
-"""
-            .codeUnits);
-        complete.addAll(_truncatedTail());
-      } else if (_tail != null) {
-        complete.addAll(_tail);
-      }
-      _head = null;
-      _tail = null;
-      _checkUtf8(complete);
-    }
-    return complete;
-  }
-
   @override
   Future addStream(Stream<List<int>> stream) {
     _subscription = stream.listen(add);
@@ -92,14 +68,9 @@
   }
 
   @override
-  Future close() {
-    toList();
-    return _subscription?.cancel();
-  }
+  Future close() => _subscription?.cancel();
 
-  Future cancel() {
-    return _subscription?.cancel();
-  }
+  Future cancel() => _subscription?.cancel();
 }
 
 /// An [OutputLog] that tees the output to a file as well.
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index 7b29ea8..ff3e1f1 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -1082,11 +1082,19 @@
     if (outcome == "CRASH") exitCode = unhandledCompilerExceptionExitCode;
     if (outcome == "PARSE_FAIL") exitCode = parseFailExitCode;
     if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
+
+    // Fail if the output was too long or incorrectly formatted.
+    if (_testStdout.hasNonUtf8 || _testStderr.hasNonUtf8) {
+      exitCode = nonUtfFakeExitCode;
+    } else if (_testStdout.wasTruncated || _testStderr.wasTruncated) {
+      exitCode = truncatedFakeExitCode;
+    }
+
     var output = _command.createOutput(
         exitCode,
         outcome == "TIMEOUT",
-        _testStdout.toList(),
-        _testStderr.toList(),
+        _testStdout.bytes,
+        _testStderr.bytes,
         DateTime.now().difference(_startTime),
         false);
     assert(_completer != null);
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 159b636..9316d76 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -20,7 +20,8 @@
 
 const _slowTimeoutMultiplier = 4;
 const _extraSlowTimeoutMultiplier = 8;
-const nonUtfFakeExitCode = 0xFFFD;
+const nonUtfFakeExitCode = 0xfffd;
+const truncatedFakeExitCode = 0xfffc;
 
 /// Some IO tests use these variables and get confused if the host environment
 /// variables are inherited so they are excluded.
@@ -220,25 +221,24 @@
 /// are no pointers to it, so it should be available to be garbage collected as
 /// soon as it is done.
 class RunningProcess {
-  ProcessCommand command;
-  int timeout;
+  final ProcessCommand command;
+  final int timeout;
   bool timedOut = false;
   DateTime startTime;
   int pid;
-  OutputLog stdout;
-  OutputLog stderr = OutputLog();
-  List<String> diagnostics = <String>[];
+  final OutputLog _stdout;
+  final OutputLog _stderr = OutputLog();
+  final List<String> diagnostics = [];
   bool compilationSkipped = false;
   Completer<CommandOutput> completer;
-  TestConfiguration configuration;
+  final TestConfiguration configuration;
 
   RunningProcess(this.command, this.timeout,
-      {this.configuration, io.File outputFile}) {
-    stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
-  }
+      {this.configuration, io.File outputFile})
+      : _stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
 
   Future<CommandOutput> run() {
-    completer = Completer<CommandOutput>();
+    completer = Completer();
     startTime = DateTime.now();
     _runCommand();
     return completer.future;
@@ -255,8 +255,8 @@
           environment: processEnvironment,
           workingDirectory: command.workingDirectory);
       processFuture.then<dynamic>((io.Process process) {
-        var stdoutFuture = process.stdout.pipe(stdout);
-        var stderrFuture = process.stderr.pipe(stderr);
+        var stdoutFuture = process.stdout.pipe(_stdout);
+        var stderrFuture = process.stderr.pipe(_stderr);
         pid = process.pid;
 
         // Close stdin so that tests that try to block on input will fail.
@@ -329,15 +329,15 @@
               onTimeout: () async {
             DebugLogger.warning(
                 "$maxStdioDelayPassedMessage (command: $command)");
-            await stdout.cancel();
-            await stderr.cancel();
+            await _stdout.cancel();
+            await _stderr.cancel();
             return null;
           }).then((_) {
-            if (stdout is FileOutputLog) {
+            if (_stdout is FileOutputLog) {
               // Prevent logging data that has already been written to a file
-              // and is unlikely too add value in the logs because the command
+              // and is unlikely to add value in the logs because the command
               // succeeded.
-              stdout.complete = <int>[];
+              _stdout.clear();
             }
             _commandComplete(exitCode);
           });
@@ -359,15 +359,16 @@
   }
 
   CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) {
-    var stdoutData = stdout.toList();
-    var stderrData = stderr.toList();
-    if (stdout.hasNonUtf8 || stderr.hasNonUtf8) {
-      // If the output contained non-utf8 formatted data, then make the exit
-      // code non-zero if it isn't already.
-      if (exitCode == 0) {
-        exitCode = nonUtfFakeExitCode;
-      }
+    var stdoutData = _stdout.bytes;
+    var stderrData = _stderr.bytes;
+
+    // Fail if the output was too long or incorrectly formatted.
+    if (_stdout.hasNonUtf8 || _stderr.hasNonUtf8) {
+      exitCode = nonUtfFakeExitCode;
+    } else if (_stdout.wasTruncated || _stderr.wasTruncated) {
+      exitCode = truncatedFakeExitCode;
     }
+
     var commandOutput = command.createOutput(
         exitCode,
         timedOut,
diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart
index 389350a..8ea87ad 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory/lib/src/elements/instance_ref.dart
@@ -162,6 +162,7 @@
             ]
         ];
       case M.InstanceKind.plainInstance:
+      case M.InstanceKind.receivePort:
         return [
           new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
             ..classes = ['emphasize']
diff --git a/runtime/observatory/tests/service/developer_server_control_test.dart b/runtime/observatory/tests/service/developer_server_control_test.dart
index f599dc3..18498f2 100644
--- a/runtime/observatory/tests/service/developer_server_control_test.dart
+++ b/runtime/observatory/tests/service/developer_server_control_test.dart
@@ -11,6 +11,7 @@
 int? majorVersion;
 int? minorVersion;
 Uri? serverUri;
+Uri? wsServerUri;
 
 Future<Null> testeeBefore() async {
   print('testee before');
@@ -20,8 +21,8 @@
   ServiceProtocolInfo info = await Service.getInfo();
   majorVersion = info.majorVersion;
   minorVersion = info.minorVersion;
-  serverUri = info.serverUri;
   Expect.isNull(info.serverUri);
+  Expect.isNull(info.serverWebSocketUri);
   {
     // Now, start the web server and store the URI which is expected to be
     // non NULL in the top level variable.
@@ -30,7 +31,11 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNotNull(info.serverUri);
+    Expect.isNotNull(info.serverWebSocketUri);
     serverUri = info.serverUri;
+    wsServerUri = info.serverWebSocketUri;
+    Expect.equals(wsServerUri!.scheme, 'ws');
+    Expect.isTrue(wsServerUri!.path.endsWith('ws'));
   }
   {
     // Now try starting the web server again, this should just return the
@@ -39,6 +44,7 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.equals(info.serverUri, serverUri);
+    Expect.equals(info.serverWebSocketUri, wsServerUri);
   }
   {
     // Try turning off the web server, this should turn off the server and
@@ -47,6 +53,7 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNull(info.serverUri);
+    Expect.isNull(info.serverWebSocketUri);
   }
   {
     // Try turning off the web server again, this should be a nop
@@ -55,16 +62,17 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNull(info.serverUri);
+    Expect.isNull(info.serverWebSocketUri);
   }
   {
     // Start the web server again for the test below.
     ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
     majorVersion = info.majorVersion;
     minorVersion = info.minorVersion;
-    serverUri = info.serverUri;
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
-    Expect.equals(info.serverUri, serverUri);
+    Expect.isNotNull(info.serverUri);
+    Expect.isNotNull(info.serverWebSocketUri);
   }
 }
 
diff --git a/runtime/observatory_2/lib/src/elements/instance_ref.dart b/runtime/observatory_2/lib/src/elements/instance_ref.dart
index 1895783..f1b37ea 100644
--- a/runtime/observatory_2/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory_2/lib/src/elements/instance_ref.dart
@@ -264,6 +264,7 @@
           return members;
         }
       case M.InstanceKind.plainInstance:
+      case M.InstanceKind.receivePort:
         return _loadedInstance.fields
             .map<Element>((f) => new DivElement()
               ..children = <Element>[
diff --git a/runtime/observatory_2/tests/service_2/developer_server_control_test.dart b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
index 62889e4..c4a81392 100644
--- a/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
+++ b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
@@ -11,6 +11,7 @@
 int majorVersion;
 int minorVersion;
 Uri serverUri;
+Uri wsServerUri;
 
 Future<Null> testeeBefore() async {
   print('testee before');
@@ -20,8 +21,8 @@
   ServiceProtocolInfo info = await Service.getInfo();
   majorVersion = info.majorVersion;
   minorVersion = info.minorVersion;
-  serverUri = info.serverUri;
   Expect.isNull(info.serverUri);
+  Expect.isNull(info.serverWebSocketUri);
   {
     // Now, start the web server and store the URI which is expected to be
     // non NULL in the top level variable.
@@ -31,6 +32,9 @@
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNotNull(info.serverUri);
     serverUri = info.serverUri;
+    wsServerUri = info.serverWebSocketUri;
+    Expect.equals(wsServerUri.scheme, 'ws');
+    Expect.isTrue(wsServerUri.path.endsWith('ws'));
   }
   {
     // Now try starting the web server again, this should just return the
@@ -39,6 +43,7 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.equals(info.serverUri, serverUri);
+    Expect.equals(info.serverWebSocketUri, wsServerUri);
   }
   {
     // Try turning off the web server, this should turn off the server and
@@ -47,6 +52,7 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNull(info.serverUri);
+    Expect.isNull(info.serverWebSocketUri);
   }
   {
     // Try turning off the web server again, this should be a nop
@@ -55,16 +61,17 @@
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
     Expect.isNull(info.serverUri);
+    Expect.isNull(info.serverWebSocketUri);
   }
   {
     // Start the web server again for the test below.
     ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
     majorVersion = info.majorVersion;
     minorVersion = info.minorVersion;
-    serverUri = info.serverUri;
     Expect.equals(info.majorVersion, majorVersion);
     Expect.equals(info.minorVersion, minorVersion);
-    Expect.equals(info.serverUri, serverUri);
+    Expect.isNotNull(info.serverUri);
+    Expect.isNotNull(info.serverWebSocketUri);
   }
 }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index d4bfbe0..436bad9 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -377,10 +377,12 @@
 
 [ $builder_tag == crossword || $builder_tag == crossword_ast ]
 dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
+dart/gen_snapshot_include_resolved_urls_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot.
 dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart/split_aot_kernel_generation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
+dart_2/gen_snapshot_include_resolved_urls_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot.
 dart_2/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/split_aot_kernel_generation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index e779915..537bfe0 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2415,6 +2415,15 @@
     objects_.Add(weak);
   }
 
+  void RetraceEphemerons(Serializer* s) {
+    for (intptr_t i = 0; i < objects_.length(); i++) {
+      WeakSerializationReferencePtr weak = objects_[i];
+      if (!s->HasRef(weak->untag()->target())) {
+        s->Push(weak->untag()->replacement());
+      }
+    }
+  }
+
   intptr_t FinalizeWeak(Serializer* s) { return objects_.length(); }
 
   void WriteAlloc(Serializer* s) {
@@ -5029,7 +5038,15 @@
   void Trace(Serializer* s, ObjectPtr object) {
     WeakPropertyPtr property = WeakProperty::RawCast(object);
     objects_.Add(property);
-    PushFromTo(property);
+  }
+
+  void RetraceEphemerons(Serializer* s) {
+    for (intptr_t i = 0; i < objects_.length(); i++) {
+      WeakPropertyPtr property = objects_[i];
+      if (s->HasRef(property->untag()->key())) {
+        s->Push(property->untag()->value());
+      }
+    }
   }
 
   void WriteAlloc(Serializer* s) {
@@ -5047,7 +5064,14 @@
     for (intptr_t i = 0; i < count; i++) {
       WeakPropertyPtr property = objects_[i];
       AutoTraceObject(property);
-      WriteFromTo(property);
+      if (s->HasRef(property->untag()->key())) {
+        s->WriteOffsetRef(property->untag()->key(), WeakProperty::key_offset());
+        s->WriteOffsetRef(property->untag()->value(),
+                          WeakProperty::value_offset());
+      } else {
+        s->WriteOffsetRef(Object::null(), WeakProperty::key_offset());
+        s->WriteOffsetRef(Object::null(), WeakProperty::value_offset());
+      }
     }
   }
 
@@ -6759,7 +6783,24 @@
   roots->PushRoots(this);
 
   while (stack_.length() > 0) {
-    Trace(stack_.RemoveLast());
+    // Strong references.
+    while (stack_.length() > 0) {
+      Trace(stack_.RemoveLast());
+    }
+
+    // Ephemeron references.
+#if defined(DART_PRECOMPILER)
+    if (auto const cluster =
+            reinterpret_cast<WeakSerializationReferenceSerializationCluster*>(
+                clusters_by_cid_[kWeakSerializationReferenceCid])) {
+      cluster->RetraceEphemerons(this);
+    }
+#endif
+    if (auto const cluster =
+            reinterpret_cast<WeakPropertySerializationCluster*>(
+                clusters_by_cid_[kWeakPropertyCid])) {
+      cluster->RetraceEphemerons(this);
+    }
   }
 
   GrowableArray<SerializationCluster*> canonical_clusters;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 9b15447..5b0fc05 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -6092,6 +6092,20 @@
   return this;
 }
 
+Representation LoadIndexedInstr::RepresentationOfArrayElement(
+    intptr_t array_cid) {
+  switch (array_cid) {
+    case kImmutableArrayCid:
+    case kTypeArgumentsCid:
+      return kTagged;
+    case kExternalOneByteStringCid:
+    case kExternalTwoByteStringCid:
+      return kUnboxedIntPtr;
+    default:
+      return StoreIndexedInstr::RepresentationOfArrayElement(array_cid);
+  }
+}
+
 StoreIndexedInstr::StoreIndexedInstr(Value* array,
                                      Value* index,
                                      Value* value,
@@ -6133,6 +6147,64 @@
   return this;
 }
 
+Representation StoreIndexedInstr::RepresentationOfArrayElement(
+    intptr_t array_cid) {
+  switch (array_cid) {
+    case kArrayCid:
+      return kTagged;
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnboxedIntPtr;
+    case kTypedDataInt32ArrayCid:
+      return kUnboxedInt32;
+    case kTypedDataUint32ArrayCid:
+      return kUnboxedUint32;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      return kUnboxedInt64;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+      return kUnboxedDouble;
+    case kTypedDataInt32x4ArrayCid:
+      return kUnboxedInt32x4;
+    case kTypedDataFloat32x4ArrayCid:
+      return kUnboxedFloat32x4;
+    case kTypedDataFloat64x2ArrayCid:
+      return kUnboxedFloat64x2;
+    default:
+      UNREACHABLE();
+      return kTagged;
+  }
+}
+
+Representation StoreIndexedInstr::RequiredInputRepresentation(
+    intptr_t idx) const {
+  // Array can be a Dart object or a pointer to external data.
+  if (idx == 0) return kNoRepresentation;  // Flexible input representation.
+  if (idx == 1) {
+    if (index_unboxed_) {
+#if defined(TARGET_ARCH_X64)
+      return kUnboxedInt64;
+#else
+      // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32 on 32-bit
+      //  architectures.
+      return kNoRepresentation;  // Index can be any unboxed representation.
+#endif
+    } else {
+      return kTagged;  // Index is a smi.
+    }
+  }
+  ASSERT(idx == 2);
+  return RepresentationOfArrayElement(class_id());
+}
+
 bool Utf8ScanInstr::IsScanFlagsUnboxed() const {
   return FlowGraphCompiler::IsUnboxedField(scan_flags_field_.field());
 }
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index fc05085..b4d5f3a 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5661,7 +5661,13 @@
     return GetDeoptId() != DeoptId::kNone;
   }
 
-  virtual Representation representation() const;
+  // Representation of LoadIndexed from arrays with given cid.
+  static Representation RepresentationOfArrayElement(intptr_t array_cid);
+
+  Representation representation() const {
+    return RepresentationOfArrayElement(class_id());
+  }
+
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
   virtual bool HasUnknownSideEffects() const { return false; }
@@ -5957,6 +5963,9 @@
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
+  // Representation of value passed to StoreIndexed for arrays with given cid.
+  static Representation RepresentationOfArrayElement(intptr_t array_cid);
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const;
 
   bool IsExternal() const {
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index c8b681f..93540db 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1753,46 +1753,6 @@
   __ StoreToOffset(value, obj, instr->offset_from_tagged());
 }
 
-Representation LoadIndexedInstr::representation() const {
-  switch (class_id_) {
-    case kArrayCid:
-    case kImmutableArrayCid:
-    case kTypeArgumentsCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNREACHABLE();
-      return kTagged;
-  }
-}
-
 static bool CanBeImmediateIndex(Value* value,
                                 intptr_t cid,
                                 bool is_external,
@@ -2061,54 +2021,6 @@
   }
 }
 
-Representation StoreIndexedInstr::RequiredInputRepresentation(
-    intptr_t idx) const {
-  // Array can be a Dart object or a pointer to external data.
-  if (idx == 0) return kNoRepresentation;  // Flexible input representation.
-  if (idx == 1) {
-    if (index_unboxed_) {
-      // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32.
-      return kNoRepresentation;
-    } else {
-      return kTagged;  // Index is a smi.
-    }
-  }
-  ASSERT(idx == 2);
-  switch (class_id_) {
-    case kArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNREACHABLE();
-      return kTagged;
-  }
-}
-
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const bool directly_addressable =
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 3bab356..a0ee87a 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1660,46 +1660,6 @@
   __ StoreToOffset(value, obj, instr->offset_from_tagged());
 }
 
-Representation LoadIndexedInstr::representation() const {
-  switch (class_id_) {
-    case kArrayCid:
-    case kImmutableArrayCid:
-    case kTypeArgumentsCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNIMPLEMENTED();
-      return kTagged;
-  }
-}
-
 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) {
   ConstantInstr* constant = value->definition()->AsConstant();
   if ((constant == NULL) || !constant->value().IsSmi()) {
@@ -1891,53 +1851,6 @@
   __ SmiTag(result);
 }
 
-Representation StoreIndexedInstr::RequiredInputRepresentation(
-    intptr_t idx) const {
-  // Array can be a Dart object or a pointer to external data.
-  if (idx == 0) return kNoRepresentation;  // Flexible input representation.
-  if (idx == 1) {
-    if (index_unboxed_) {
-      return kNoRepresentation;  // Index can be any unboxed representation.
-    } else {
-      return kTagged;  // Index is a smi.
-    }
-  }
-  ASSERT(idx == 2);
-  switch (class_id_) {
-    case kArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNREACHABLE();
-      return kTagged;
-  }
-}
-
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 8c6fe6d..a308aaa 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1433,46 +1433,6 @@
   __ movl(compiler::Address(obj, instr->offset_from_tagged()), value);
 }
 
-Representation LoadIndexedInstr::representation() const {
-  switch (class_id_) {
-    case kArrayCid:
-    case kImmutableArrayCid:
-    case kTypeArgumentsCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNIMPLEMENTED();
-      return kTagged;
-  }
-}
-
 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -1627,54 +1587,6 @@
   }
 }
 
-Representation StoreIndexedInstr::RequiredInputRepresentation(
-    intptr_t idx) const {
-  // Array can be a Dart object or a pointer to external data.
-  if (idx == 0) return kNoRepresentation;  // Flexible input representation.
-  if (idx == 1) {
-    if (index_unboxed_) {
-      // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32.
-      return kNoRepresentation;
-    } else {
-      return kTagged;  // Index is a smi.
-    }
-  }
-  ASSERT(idx == 2);
-  switch (class_id_) {
-    case kArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNIMPLEMENTED();
-      return kTagged;
-  }
-}
-
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index da435ce3..9eaa60c 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1683,46 +1683,6 @@
   const Register result_;
 };
 
-Representation LoadIndexedInstr::representation() const {
-  switch (class_id_) {
-    case kArrayCid:
-    case kImmutableArrayCid:
-    case kTypeArgumentsCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTwoByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNIMPLEMENTED();
-      return kTagged;
-  }
-}
-
 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -1933,52 +1893,6 @@
   }
 }
 
-Representation StoreIndexedInstr::RequiredInputRepresentation(
-    intptr_t idx) const {
-  if (idx == 0) return kNoRepresentation;
-  if (idx == 1) {
-    if (index_unboxed_) {
-      return kUnboxedInt64;
-    } else {
-      return kTagged;  // Index is a smi.
-    }
-  }
-  ASSERT(idx == 2);
-  switch (class_id_) {
-    case kArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      return kUnboxedInt64;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-    default:
-      UNIMPLEMENTED();
-      return kTagged;
-  }
-}
-
 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
   const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 012a80e..ed3fba1 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1302,8 +1302,6 @@
           compiler::ffi::RecognizedMethodAlignment(kind);
       const classid_t typed_data_cid =
           compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
-      const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
-          zone_, ffi_type_arg_cid);
 
       ASSERT(function.NumParameters() == 2);
       LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
@@ -1324,59 +1322,45 @@
       body += LoadIndexed(typed_data_cid, /*index_scale=*/1,
                           /*index_unboxed=*/true, alignment);
       if (kind == MethodRecognizer::kFfiLoadFloat ||
-          kind == MethodRecognizer::kFfiLoadFloatUnaligned ||
-          kind == MethodRecognizer::kFfiLoadDouble ||
-          kind == MethodRecognizer::kFfiLoadDoubleUnaligned) {
-        if (kind == MethodRecognizer::kFfiLoadFloat ||
-            kind == MethodRecognizer::kFfiLoadFloatUnaligned) {
-          body += FloatToDouble();
-        }
-        body += Box(kUnboxedDouble);
-      } else if (kind == MethodRecognizer::kFfiLoadInt8 ||
-                 kind == MethodRecognizer::kFfiLoadInt16 ||
-                 kind == MethodRecognizer::kFfiLoadUint8 ||
-                 kind == MethodRecognizer::kFfiLoadUint16) {
-        // LoadIndexed instruction with 8-bit and 16-bit elements
-        // results in value with kUnboxedIntPtr representation
-        // (see LoadIndexedInstr::representation).
-        // Avoid any unnecessary (and potentially deoptimizing) int
-        // conversions by using the correct representation at the first place.
-        body += Box(kUnboxedIntPtr);
-      } else {
-        body += Box(native_rep.AsRepresentationOverApprox(zone_));
-        if (kind == MethodRecognizer::kFfiLoadPointer) {
-          const auto class_table = thread_->isolate_group()->class_table();
-          ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
-          const auto& pointer_class =
-              Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
+          kind == MethodRecognizer::kFfiLoadFloatUnaligned) {
+        body += FloatToDouble();
+      }
+      // Avoid any unnecessary (and potentially deoptimizing) int
+      // conversions by using the representation returned from LoadIndexed.
+      body +=
+          Box(LoadIndexedInstr::RepresentationOfArrayElement(typed_data_cid));
+      if (kind == MethodRecognizer::kFfiLoadPointer) {
+        const auto class_table = thread_->isolate_group()->class_table();
+        ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
+        const auto& pointer_class =
+            Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
 
-          // We find the reified type to use for the pointer allocation.
-          //
-          // Call sites to this recognized method are guaranteed to pass a
-          // Pointer<Pointer<X>> as RawParameterVariable(0). This function
-          // will return a Pointer<X> object - for which we inspect the
-          // reified type on the argument.
-          //
-          // The following is safe to do, as (1) we are guaranteed to have a
-          // Pointer<Pointer<X>> as argument, and (2) the bound on the pointer
-          // type parameter guarantees X is an interface type.
-          ASSERT(function.NumTypeParameters() == 1);
-          LocalVariable* address = MakeTemporary();
-          body += LoadLocal(parsed_function_->RawParameterVariable(0));
-          body += LoadNativeField(
-              Slot::GetTypeArgumentsSlotFor(thread_, pointer_class));
-          body += LoadNativeField(Slot::GetTypeArgumentsIndexSlot(
-              thread_, Pointer::kNativeTypeArgPos));
-          body += LoadNativeField(Slot::Type_arguments());
-          body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
-          LocalVariable* pointer = MakeTemporary();
-          body += LoadLocal(pointer);
-          body += LoadLocal(address);
-          body += UnboxTruncate(kUnboxedFfiIntPtr);
-          body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
-          body += StoreUntagged(compiler::target::Pointer::data_field_offset());
-          body += DropTempsPreserveTop(1);  // Drop [address] keep [pointer].
-        }
+        // We find the reified type to use for the pointer allocation.
+        //
+        // Call sites to this recognized method are guaranteed to pass a
+        // Pointer<Pointer<X>> as RawParameterVariable(0). This function
+        // will return a Pointer<X> object - for which we inspect the
+        // reified type on the argument.
+        //
+        // The following is safe to do, as (1) we are guaranteed to have a
+        // Pointer<Pointer<X>> as argument, and (2) the bound on the pointer
+        // type parameter guarantees X is an interface type.
+        ASSERT(function.NumTypeParameters() == 1);
+        LocalVariable* address = MakeTemporary();
+        body += LoadLocal(parsed_function_->RawParameterVariable(0));
+        body += LoadNativeField(
+            Slot::GetTypeArgumentsSlotFor(thread_, pointer_class));
+        body += LoadNativeField(Slot::GetTypeArgumentsIndexSlot(
+            thread_, Pointer::kNativeTypeArgPos));
+        body += LoadNativeField(Slot::Type_arguments());
+        body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
+        LocalVariable* pointer = MakeTemporary();
+        body += LoadLocal(pointer);
+        body += LoadLocal(address);
+        body += UnboxTruncate(kUnboxedFfiIntPtr);
+        body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
+        body += StoreUntagged(compiler::target::Pointer::data_field_offset());
+        body += DropTempsPreserveTop(1);  // Drop [address] keep [pointer].
       }
       body += DropTempsPreserveTop(1);  // Drop [arg_offset].
     } break;
@@ -1400,8 +1384,6 @@
           compiler::ffi::RecognizedMethodAlignment(kind);
       const classid_t typed_data_cid =
           compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
-      const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
-          zone_, ffi_type_arg_cid);
 
       LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
       LocalVariable* arg_offset = parsed_function_->RawParameterVariable(1);
@@ -1463,27 +1445,15 @@
         // This can only be Pointer, so it is always safe to LoadUntagged.
         body += LoadUntagged(compiler::target::Pointer::data_field_offset());
         body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
-      } else if (kind == MethodRecognizer::kFfiStoreFloat ||
-                 kind == MethodRecognizer::kFfiStoreFloatUnaligned ||
-                 kind == MethodRecognizer::kFfiStoreDouble ||
-                 kind == MethodRecognizer::kFfiStoreDoubleUnaligned) {
-        body += UnboxTruncate(kUnboxedDouble);
+      } else {
+        // Avoid any unnecessary (and potentially deoptimizing) int
+        // conversions by using the representation consumed by StoreIndexed.
+        body += UnboxTruncate(
+            StoreIndexedInstr::RepresentationOfArrayElement(typed_data_cid));
         if (kind == MethodRecognizer::kFfiStoreFloat ||
             kind == MethodRecognizer::kFfiStoreFloatUnaligned) {
           body += DoubleToFloat();
         }
-      } else if (kind == MethodRecognizer::kFfiStoreInt8 ||
-                 kind == MethodRecognizer::kFfiStoreInt16 ||
-                 kind == MethodRecognizer::kFfiStoreUint8 ||
-                 kind == MethodRecognizer::kFfiStoreUint16) {
-        // StoreIndexed instruction with 8-bit and 16-bit elements
-        // takes value with kUnboxedIntPtr representation
-        // (see StoreIndexedInstr::RequiredInputRepresentation).
-        // Avoid any unnecessary (and potentially deoptimizing) int
-        // conversions by using the correct representation at the first place.
-        body += UnboxTruncate(kUnboxedIntPtr);
-      } else {
-        body += UnboxTruncate(native_rep.AsRepresentationOverApprox(zone_));
       }
       body += StoreIndexedTypedData(typed_data_cid, /*index_scale=*/1,
                                     /*index_unboxed=*/true, alignment);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 4c5578f..8e91315 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -41,6 +41,7 @@
 #include "vm/port.h"
 #include "vm/profiler.h"
 #include "vm/profiler_service.h"
+#include "vm/raw_object_fields.h"
 #include "vm/resolver.h"
 #include "vm/reusable_handles.h"
 #include "vm/service_event.h"
@@ -2127,6 +2128,7 @@
   ObjectGraph graph(thread);
   Array& path = Array::Handle(Array::New(limit * 2));
   intptr_t length = graph.InboundReferences(target, path);
+  OffsetsTable offsets_table(thread->zone());
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "InboundReferences");
   {
@@ -2147,17 +2149,35 @@
         intptr_t element_index =
             slot_offset.Value() - (Array::element_offset(0) >> kWordSizeLog2);
         jselement.AddProperty("parentListIndex", element_index);
-      } else if (source.IsInstance()) {
-        source_class = source.clazz();
-        parent_field_map = source_class.OffsetToFieldMap();
-        intptr_t offset = slot_offset.Value();
-        if (offset > 0 && offset < parent_field_map.Length()) {
-          field ^= parent_field_map.At(offset);
-          jselement.AddProperty("parentField", field);
-        }
       } else {
-        intptr_t element_index = slot_offset.Value();
-        jselement.AddProperty("_parentWordOffset", element_index);
+        if (source.IsInstance()) {
+          source_class = source.clazz();
+          parent_field_map = source_class.OffsetToFieldMap();
+          intptr_t offset = slot_offset.Value();
+          if (offset > 0 && offset < parent_field_map.Length()) {
+            field ^= parent_field_map.At(offset);
+            if (!field.IsNull()) {
+              jselement.AddProperty("parentField", field);
+              continue;
+            }
+          }
+        }
+        const char* field_name = offsets_table.FieldNameForOffset(
+            source.GetClassId(), slot_offset.Value() * kWordSize);
+        if (field_name != nullptr) {
+          jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+          // TODO(vm-service): Adjust RPC type to allow returning a field name
+          // without a field object, or reify the fields described by
+          // raw_object_fields.cc
+          // jselement.AddProperty("_parentFieldName", field_name);
+        } else if (source.IsContext()) {
+          intptr_t element_index =
+              slot_offset.Value() -
+              (Context::variable_offset(0) >> kWordSizeLog2);
+          jselement.AddProperty("parentListIndex", element_index);
+        } else {
+          jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+        }
       }
     }
   }
@@ -2236,6 +2256,7 @@
   WeakProperty& wp = WeakProperty::Handle();
   String& name = String::Handle();
   limit = Utils::Minimum(limit, length);
+  OffsetsTable offsets_table(thread->zone());
   for (intptr_t i = 0; i < limit; ++i) {
     JSONObject jselement(&elements);
     element = path.At(i * 2);
@@ -2266,23 +2287,32 @@
         wp ^= static_cast<WeakPropertyPtr>(element.ptr());
         element = wp.key();
         jselement.AddProperty("parentMapKey", element);
-      } else if (element.IsInstance()) {
-        element_class = element.clazz();
-        element_field_map = element_class.OffsetToFieldMap();
-        OS::PrintErr("Class: %s Map: %s\n", element_class.ToCString(),
-                     element_field_map.ToCString());
-        intptr_t offset = slot_offset.Value();
-        if (offset > 0 && offset < element_field_map.Length()) {
-          field ^= element_field_map.At(offset);
-          ASSERT(!field.IsNull());
-          // TODO(bkonyi): check for mapping between C++ name and Dart name (V8
-          // snapshot writer?)
-          name ^= field.name();
-          jselement.AddProperty("parentField", name.ToCString());
-        }
       } else {
-        intptr_t element_index = slot_offset.Value();
-        jselement.AddProperty("_parentWordOffset", element_index);
+        if (element.IsInstance()) {
+          element_class = element.clazz();
+          element_field_map = element_class.OffsetToFieldMap();
+          intptr_t offset = slot_offset.Value();
+          if ((offset > 0) && (offset < element_field_map.Length())) {
+            field ^= element_field_map.At(offset);
+            if (!field.IsNull()) {
+              name ^= field.name();
+              jselement.AddProperty("parentField", name.ToCString());
+              continue;
+            }
+          }
+        }
+        const char* field_name = offsets_table.FieldNameForOffset(
+            element.GetClassId(), slot_offset.Value() * kWordSize);
+        if (field_name != nullptr) {
+          jselement.AddProperty("parentField", field_name);
+        } else if (element.IsContext()) {
+          intptr_t element_index =
+              slot_offset.Value() -
+              (Context::variable_offset(0) >> kWordSizeLog2);
+          jselement.AddProperty("parentListIndex", element_index);
+        } else {
+          jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+        }
       }
     }
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 98cf5e8..a5e1837 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -48,7 +48,6 @@
 import 'dart:_internal'
     show
         EfficientLengthIterable,
-        LateError,
         MappedIterable,
         IterableElementError,
         SubListIterable;
@@ -3025,9 +3024,6 @@
 const kRequiredSentinel = const _Required();
 bool isRequired(Object? value) => identical(kRequiredSentinel, value);
 
-/// Called by generated code to throw a LateInitializationError.
-void throwLateInitializationError(String name) => throw LateError(name);
-
 /// Checks that [f] is a function that supports interop.
 @pragma('dart2js:tryInline')
 bool isJSFunction(Function f) => JS('bool', 'typeof(#) == "function"', f);
diff --git a/sdk/lib/_internal/js_runtime/lib/late_helper.dart b/sdk/lib/_internal/js_runtime/lib/late_helper.dart
new file mode 100644
index 0000000..e6136e8
--- /dev/null
+++ b/sdk/lib/_internal/js_runtime/lib/late_helper.dart
@@ -0,0 +1,58 @@
+// 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.
+
+library _late_helper;
+
+import 'dart:_internal' show LateError;
+
+void throwLateFieldADI(String fieldName) => throw LateError.fieldADI(fieldName);
+
+/// A boxed variable used for lowering `late` variables when they are local or
+/// uninitialized statics.
+///
+/// The [LateError]s produced have empty variable names.
+class _Cell {
+  Object? _value;
+
+  _Cell() {
+    // `this` is a unique sentinel.
+    _value = this;
+  }
+
+  @pragma('dart2js:tryInline')
+  @pragma('dart2js:as:trust')
+  T readLocal<T>() => _readLocal() as T;
+
+  @pragma('dart2js:tryInline')
+  @pragma('dart2js:as:trust')
+  T readField<T>() => _readField() as T;
+
+  Object? _readLocal() {
+    if (identical(_value, this)) throw LateError.localNI('');
+    return _value;
+  }
+
+  Object? _readField() {
+    if (identical(_value, this)) throw LateError.fieldNI('');
+    return _value;
+  }
+
+  void set value(Object? v) {
+    _value = v;
+  }
+
+  void set finalLocalValue(Object? v) {
+    // TODO(fishythefish): Throw [LateError.localADI] if this occurs during
+    // recursive initialization.
+    if (!identical(_value, this)) throw LateError.localAI('');
+    _value = v;
+  }
+
+  void set finalFieldValue(Object? v) {
+    // TODO(fishythefish): Throw [LateError.fieldADI] if this occurs during
+    // recursive initialization.
+    if (!identical(_value, this)) throw LateError.fieldAI('');
+    _value = v;
+  }
+}
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 84d68ad..8e56fe9 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -149,6 +149,8 @@
       dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
   "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
       categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_late_helper": const LibraryInfo("_internal/js_runtime/lib/late_helper.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
   "_rti": const LibraryInfo("_internal/js_runtime/lib/rti.dart",
       categories: "", documented: false, platforms: DART2JS_PLATFORM),
   "_interceptors": const LibraryInfo(
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 6fd58c3..8715d25 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -17,10 +17,30 @@
   /// not support the service protocol, this is 0.
   final int minorVersion = _getServiceMinorVersion();
 
-  /// The Uri to access the service. If the web server is not running, this
-  /// will be null.
+  /// The Uri to connect to the debugger client hosted by the service. If the
+  /// web server is not running, this will be null.
   final Uri? serverUri;
 
+  /// The Uri to connect to the service via web socket. If the web server is
+  /// not running, this will be null.
+  Uri? get serverWebSocketUri {
+    Uri? uri = serverUri;
+    if (uri != null) {
+      final pathSegments = <String>[];
+      if (uri.pathSegments.isNotEmpty) {
+        pathSegments.addAll(uri.pathSegments.where(
+          // Strip out the empty string that appears at the end of path segments.
+          // Empty string elements will result in an extra '/' being added to the
+          // URI.
+          (s) => s.isNotEmpty,
+        ));
+      }
+      pathSegments.add('ws');
+      uri = uri.replace(scheme: 'ws', pathSegments: pathSegments);
+    }
+    return uri;
+  }
+
   ServiceProtocolInfo(this.serverUri);
 
   String toString() {
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 8f584e2..a595503 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -242,6 +242,9 @@
       "_js_helper": {
         "uri": "_internal/js_runtime/lib/js_helper.dart"
       },
+      "_late_helper": {
+        "uri": "_internal/js_runtime/lib/late_helper.dart"
+      },
       "_rti": {
         "uri": "_internal/js_runtime/lib/rti.dart"
       },
@@ -338,6 +341,9 @@
       "_js_helper": {
         "uri": "_internal/js_runtime/lib/js_helper.dart"
       },
+      "_late_helper": {
+        "uri": "_internal/js_runtime/lib/late_helper.dart"
+      },
       "_rti": {
         "uri": "_internal/js_runtime/lib/rti.dart"
       },
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 89e3640..87beca8 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -240,6 +240,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _late_helper:
+      uri: "_internal/js_runtime/lib/late_helper.dart"
+
     _rti:
       uri: "_internal/js_runtime/lib/rti.dart"
 
@@ -334,6 +337,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _late_helper:
+      uri: "_internal/js_runtime/lib/late_helper.dart"
+
     _rti:
       uri: "_internal/js_runtime/lib/rti.dart"
 
diff --git a/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart b/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart
new file mode 100644
index 0000000..09ce941
--- /dev/null
+++ b/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart
@@ -0,0 +1,57 @@
+// 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 erroneous try-catch and try-finally with const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+//           ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+const var2 = finallyThrow(1);
+//           ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int finallyThrow(int x) {
+  try {
+    if (x == 1) {
+      throw x;
+    } else {
+      return 0;
+    }
+  } finally {
+    throw 2;
+  }
+}
+
+const var3 = unhandledThrow(0);
+//           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+const var4 = unhandledThrow("string");
+//           ^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int unhandledThrow(dynamic x) {
+  try {
+    throw x;
+  } on String catch (e) {
+    throw e;
+  }
+}
+
+const var5 = unhandledThrow2();
+//           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int unhandledThrow2() {
+  int count = 0;
+  for (int i = 0; i < 1; throw 'a') {
+    count += i;
+  }
+  return 0;
+}
diff --git a/tests/language/const_functions/const_functions_try_catch_finally_test.dart b/tests/language/const_functions/const_functions_try_catch_finally_test.dart
new file mode 100644
index 0000000..5c56167
--- /dev/null
+++ b/tests/language/const_functions/const_functions_try_catch_finally_test.dart
@@ -0,0 +1,149 @@
+// 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 try-catch and try-finally with const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+//           ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var2 = fn(1);
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn(dynamic error) {
+  try {
+    throw error;
+  } on String {
+    return 0;
+  } catch (e) {
+    return 1;
+  }
+}
+
+const var3 = fn1(10);
+//           ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var4 = fn1("s");
+//           ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn1(dynamic error) {
+  try {
+    throw error;
+  } on int catch (e) {
+    return e;
+  } catch (e) {
+    return 1;
+  }
+}
+
+const var5 = finallyReturn(10);
+//           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var6 = finallyReturn("s");
+//           ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var7 = finallyReturn(1);
+//           ^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyReturn(dynamic error) {
+  try {
+    if (error != 1) throw error;
+  } on int catch (e) {
+    return e;
+  } catch (e) {
+    return 1;
+  } finally {
+    return 100;
+  }
+}
+
+const var8 = finallyReturn1(0);
+//           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var9 = finallyReturn1(1);
+//           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyReturn1(int x) {
+  try {
+    if (x == 1) {
+      throw x;
+    } else {
+      return 0;
+    }
+  } finally {
+    return 100;
+  }
+}
+
+const var10 = finallyMutate();
+//            ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyMutate() {
+  int x = 0;
+  try {
+    return x;
+  } finally {
+    x++;
+  }
+}
+
+const var11 = subtypeFn();
+//            ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int subtypeFn() {
+  try {
+    throw 2.5;
+  } on num catch (e) {
+    return 0;
+  }
+}
+
+const var12 = orderFn();
+//            ^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+String orderFn() {
+  String x = "st";
+  try {
+    x += "ri";
+    throw 2;
+  } catch (e) {
+    x += "n";
+  } finally {
+    return x + "g";
+  }
+}
+
+const var13 = notThrowStatement();
+//            ^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int notThrowStatement() {
+  int count = 0;
+  try {
+    for (int i = 0; i < 1; throw 'a') {
+      count += i;
+    }
+  } catch (e) {
+    return 1;
+  }
+  return 0;
+}
+
+void main() {
+  Expect.equals(var1, 0);
+  Expect.equals(var2, 1);
+  Expect.equals(var3, 10);
+  Expect.equals(var4, 1);
+  Expect.equals(var5, 100);
+  Expect.equals(var6, 100);
+  Expect.equals(var7, 100);
+  Expect.equals(var8, 100);
+  Expect.equals(var9, 100);
+  Expect.equals(var10, 0);
+  Expect.equals(var11, 0);
+  Expect.equals(var12, "string");
+  Expect.equals(var13, 1);
+}
diff --git a/tests/language/nnbd/late/chained_assignment_test.dart b/tests/language/nnbd/late/chained_assignment_test.dart
new file mode 100644
index 0000000..1ca1c65
--- /dev/null
+++ b/tests/language/nnbd/late/chained_assignment_test.dart
@@ -0,0 +1,104 @@
+// 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.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  int x = 0;
+
+  int _y = 0;
+  int get y => _y;
+  void set y(int y) => _y = y;
+
+  static late int z;
+  late int w;
+}
+
+void main() {
+  final foo = Foo();
+  int a = 0;
+  late int b;
+  late int c;
+  late int d;
+
+  b = a = 1;
+  Expect.equals(a, 1);
+  Expect.equals(b, 1);
+
+  a = b = 2;
+  Expect.equals(a, 2);
+  Expect.equals(b, 2);
+
+  b = foo.x = 3;
+  Expect.equals(foo.x, 3);
+  Expect.equals(b, 3);
+
+  foo.x = b = 4;
+  Expect.equals(foo.x, 4);
+  Expect.equals(b, 4);
+
+  b = foo.y = 5;
+  Expect.equals(foo.y, 5);
+  Expect.equals(b, 5);
+
+  foo.y = b = 6;
+  Expect.equals(foo.y, 6);
+  Expect.equals(b, 6);
+
+  b = c = 7;
+  Expect.equals(b, 7);
+  Expect.equals(c, 7);
+
+  d = b = 8;
+  Expect.equals(b, 8);
+  Expect.equals(d, 8);
+
+  Foo.z = a = 9;
+  Expect.equals(a, 9);
+  Expect.equals(Foo.z, 9);
+
+  a = Foo.z = 10;
+  Expect.equals(a, 10);
+  Expect.equals(Foo.z, 10);
+
+  Foo.z = foo.x = 11;
+  Expect.equals(foo.x, 11);
+  Expect.equals(Foo.z, 11);
+
+  foo.x = Foo.z = 12;
+  Expect.equals(foo.x, 12);
+  Expect.equals(Foo.z, 12);
+
+  Foo.z = foo.y = 13;
+  Expect.equals(foo.y, 13);
+  Expect.equals(Foo.z, 13);
+
+  foo.y = Foo.z = 14;
+  Expect.equals(foo.y, 14);
+  Expect.equals(Foo.z, 14);
+
+  foo.w = a = 15;
+  Expect.equals(a, 15);
+  Expect.equals(foo.w, 15);
+
+  a = foo.w = 16;
+  Expect.equals(a, 16);
+  Expect.equals(foo.w, 16);
+
+  foo.w = foo.x = 17;
+  Expect.equals(foo.x, 17);
+  Expect.equals(foo.w, 17);
+
+  foo.x = foo.w = 18;
+  Expect.equals(foo.x, 18);
+  Expect.equals(foo.w, 18);
+
+  foo.w = foo.y = 19;
+  Expect.equals(foo.y, 19);
+  Expect.equals(foo.w, 19);
+
+  foo.y = foo.w = 20;
+  Expect.equals(foo.y, 20);
+  Expect.equals(foo.w, 20);
+}
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 914a376..9b5f403 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -118,4 +118,4 @@
 optimize/deopt_inlined_function_lazy_test: Skip
 
 [ $mode == debug && ($hot_reload || $hot_reload_rollback) ]
-regress/regress41983_test: Pass, Slow
+regress/regress41983_test: Pass, Slow
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index 3a74f75..78626b7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 216
+PRERELEASE 217
 PRERELEASE_PATCH 0
\ No newline at end of file