Version 2.14.0-386.0.dev

Merge commit '0f04dc651d5f68ab894e3da13c47e24b2a0d7cb4' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 5644191..d2df8f3 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-08-04T21:18:41.561058",
+  "generated": "2021-08-04T16:42:24.433381",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -226,7 +226,7 @@
       "name": "dart2native",
       "rootUri": "../pkg/dart2native",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "dart_internal",
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 655d3dd..d635651 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 
 /// A contributor that produces suggestions based on the members of an
 /// extension.
@@ -113,8 +112,7 @@
   void _addExtensionMembers(LibraryElement containingLibrary,
       CompletionSuggestionKind? kind, DartType type) {
     var typeSystem = containingLibrary.typeSystem;
-    var nameScope = containingLibrary.scope;
-    for (var extension in nameScope.extensions) {
+    for (var extension in containingLibrary.accessibleExtensions) {
       var extendedType =
           extension.resolvedExtendedType(containingLibrary, type);
       if (extendedType != null && typeSystem.isSubtypeOf(type, extendedType)) {
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
index aceacd3..aacc03d 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/ignore_comments/ignore_info.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError, Element;
 
@@ -234,7 +235,9 @@
   /// Leading comments for the first directive in a file are considered library
   /// comments and not returned unless they contain blank lines, in which case
   /// only the last part of the comment will be returned (unless it is a
-  /// language directive comment, in which case it will also be skipped).
+  /// language directive comment, in which case it will also be skipped) or an
+  /// '// ignore:' comment which should always be treated as attached to the
+  /// import.
   static Token? getLeadingComment(
       CompilationUnit unit, UriBasedDirective directive, LineInfo lineInfo) {
     if (directive.beginToken.precedingComments == null) {
@@ -260,22 +263,25 @@
       firstComment = firstComment.next;
     }
 
-    // Check if the comment is the first comment in the document
-    if (firstComment != unit.beginToken.precedingComments) {
-      var previousDirectiveLine =
-          lineInfo.getLocation(directive.beginToken.previous!.end).lineNumber;
-
-      // Skip over any comments on the same line as the previous directive
-      // as they will be attached to the end of it.
-      var comment = firstComment;
-      while (comment != null &&
-          previousDirectiveLine ==
-              lineInfo.getLocation(comment.offset).lineNumber) {
-        comment = comment.next;
-      }
-      return comment;
+    // If the comment is the first comment in the document then whether we
+    // consider it the leading comment depends on whether it's an ignore comment
+    // or not.
+    if (firstComment != null &&
+        firstComment == unit.beginToken.precedingComments) {
+      return _isIgnoreComment(firstComment) ? firstComment : null;
     }
-    return null;
+
+    // Skip over any comments on the same line as the previous directive
+    // as they will be attached to the end of it.
+    var previousDirectiveLine =
+        lineInfo.getLocation(directive.beginToken.previous!.end).lineNumber;
+    comment = firstComment;
+    while (comment != null &&
+        previousDirectiveLine ==
+            lineInfo.getLocation(comment.offset).lineNumber) {
+      comment = comment.next;
+    }
+    return comment;
   }
 
   /// Gets the last comment token considered to be the trailing comment for this
@@ -295,6 +301,11 @@
     }
     return null;
   }
+
+  /// Returns whether this token is a '// ignore:' comment (but not an
+  /// '// ignore_for_file:' comment).
+  static bool _isIgnoreComment(Token token) =>
+      IgnoreInfo.IGNORE_MATCHER.matchAsPrefix(token.lexeme) != null;
 }
 
 class _DirectiveInfo implements Comparable<_DirectiveInfo> {
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index b99492a..f28613f 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -42,6 +42,46 @@
 ''');
   }
 
+  Future<void> test_ignore_asFirstComment() async {
+    // Usually the first comment is treated as a library comment and not moved
+    // but if it's an 'ignore:' it should be treated as attached to the import.
+    await _computeUnitAndErrors(r'''
+// ignore: unused_import
+import 'dart:io';
+import 'dart:async';
+
+Future a;
+''');
+    // validate change
+    _assertOrganize(r'''
+import 'dart:async';
+// ignore: unused_import
+import 'dart:io';
+
+Future a;
+''');
+  }
+
+  Future<void> test_ignoreForFile_asFirstComment() async {
+    // Unlike 'ignore:', 'ignore_for_file:' still _should_ be kept at the top
+    // of the file and not attached to the import.
+    await _computeUnitAndErrors(r'''
+// ignore_for_file: unused_import
+import 'dart:io';
+import 'dart:async';
+
+Future a;
+''');
+    // validate change
+    _assertOrganize(r'''
+// ignore_for_file: unused_import
+import 'dart:async';
+import 'dart:io';
+
+Future a;
+''');
+  }
+
   Future<void> test_keep_duplicateImports_withDifferentPrefix() async {
     await _computeUnitAndErrors(r'''
 import 'dart:async' as async1;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 77c23d9..f34732b 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1300,6 +1300,10 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class LibraryElement implements _ExistingElement {
+  /// Returns a list containing all of the extension elements accessible within
+  /// this library.
+  List<ExtensionElement> get accessibleExtensions;
+
   /// Return the compilation unit that defines this library.
   CompilationUnitElement get definingCompilationUnit;
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index ed78b2e..53fdfae 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 167;
+  static const int DATA_VERSION = 168;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
index 74e302c..6dc30c4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
@@ -63,9 +63,7 @@
       if (member is ConstructorDeclaration) {
         signature.addInt(_kindConstructorDeclaration);
         _addTokens(member.beginToken, member.parameters.endToken);
-        if (member.constKeyword != null) {
-          _addNodeList(member.initializers);
-        }
+        _addNodeList(member.initializers);
         _addNode(member.redirectedConstructor);
       } else if (member is FieldDeclaration) {
         signature.addInt(_kindFieldDeclaration);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index c998b6a..531e95f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3689,6 +3689,9 @@
         super(name, offset);
 
   @override
+  List<ExtensionElement> get accessibleExtensions => scope.extensions;
+
+  @override
   CompilationUnitElement get definingCompilationUnit =>
       _definingCompilationUnit;
 
@@ -3942,7 +3945,7 @@
   }
 
   @override
-  Scope get scope {
+  LibraryScope get scope {
     return _scope ??= LibraryScope(this);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index 6ad246d..3f5ac4f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/listener.dart';
@@ -19,7 +18,6 @@
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/util/either.dart';
@@ -37,8 +35,6 @@
   bool get _genericMetadataIsEnabled =>
       _resolver.definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
 
-  Scope get _nameScope => _resolver.nameScope;
-
   TypeProvider get _typeProvider => _resolver.typeProvider;
 
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
@@ -397,7 +393,7 @@
       }
     }
 
-    for (var extension in _nameScope.extensions) {
+    for (var extension in _resolver.definingLibrary.accessibleExtensions) {
       checkExtension(extension);
     }
     return candidates;
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 845c8e1..83c03c4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -6,9 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/scope.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart';
 
@@ -350,20 +348,3 @@
     return null;
   }
 }
-
-extension ScopeExtension on Scope {
-  List<ExtensionElement> get extensions {
-    return _enclosingLibraryScope.extensions;
-  }
-
-  LibraryScope get _enclosingLibraryScope {
-    Scope? scope = this;
-    while (scope != null) {
-      if (scope is LibraryScope) {
-        return scope;
-      }
-      scope = (scope as EnclosedScope).parent;
-    }
-    throw StateError('Can only be used in a LibraryScope.');
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 6a09580..4c75b2a 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2507,6 +2507,7 @@
         nameScope,
         element.typeParameters,
       );
+      _setNodeNameScope(node, nameScope);
       visitClassDeclarationInScope(node);
 
       nameScope = ClassScope(nameScope, element);
@@ -2669,6 +2670,7 @@
         nameScope,
         element.typeParameters,
       );
+      _setNodeNameScope(node, nameScope);
       visitExtensionDeclarationInScope(node);
 
       nameScope = ExtensionScope(nameScope, element);
@@ -2788,6 +2790,7 @@
         nameScope,
         element.typeParameters,
       );
+      _setNodeNameScope(node, nameScope);
       visitFunctionDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
@@ -2895,6 +2898,7 @@
       GenericFunctionTypeElement element =
           (node as GenericFunctionTypeImpl).declaredElement!;
       nameScope = TypeParameterScope(nameScope, element.typeParameters);
+      _setNodeNameScope(node, nameScope);
       super.visitGenericFunctionType(node);
     } finally {
       nameScope = outerScope;
@@ -2908,6 +2912,7 @@
     try {
       var element = node.declaredElement as TypeAliasElement;
       nameScope = TypeParameterScope(nameScope, element.typeParameters);
+      _setNodeNameScope(node, nameScope);
       visitGenericTypeAliasInScope(node);
 
       var aliasedElement = element.aliasedElement;
@@ -2962,6 +2967,7 @@
         nameScope,
         element.typeParameters,
       );
+      _setNodeNameScope(node, nameScope);
       visitMethodDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
@@ -2990,6 +2996,7 @@
       node.metadata.accept(this);
 
       nameScope = TypeParameterScope(nameScope, element.typeParameters);
+      _setNodeNameScope(node, nameScope);
       visitMixinDeclarationInScope(node);
 
       nameScope = ClassScope(nameScope, element);
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index da1447b..0c63950 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -66,14 +66,11 @@
   }
 
   void resolveConstructorNode(ConstructorDeclarationImpl node) {
-    var isConst = node.constKeyword != null;
     // We don't want to visit the whole node because that will try to create an
     // element for it; we just want to process its children so that we can
     // resolve initializers and/or a redirection.
     void visit(AstVisitor<Object?> visitor) {
-      if (isConst) {
-        node.initializers.accept(visitor);
-      }
+      node.initializers.accept(visitor);
       node.redirectedConstructor?.accept(visitor);
     }
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 51a33b6..2c9d02c 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -162,11 +162,8 @@
     );
     reader._addFormalParameters(element.parameters);
     _readFormalParameters(reader, element.parameters);
-    if (element.isConst || element.isFactory) {
-      element.redirectedConstructor =
-          reader.readElement() as ConstructorElement?;
-      element.constantInitializers = reader._readNodeList();
-    }
+    element.redirectedConstructor = reader.readElement() as ConstructorElement?;
+    element.constantInitializers = reader._readNodeList();
     applyConstantOffsets?.perform();
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 5fd0bf8..4b67169 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -165,10 +165,8 @@
     try {
       _writeList(element.parameters, _writeParameterElement);
       _writeMacro(element.macro);
-      if (element.isConst || element.isFactory) {
-        _resolutionSink.writeElement(element.redirectedConstructor);
-        _resolutionSink._writeNodeList(element.constantInitializers);
-      }
+      _resolutionSink.writeElement(element.redirectedConstructor);
+      _resolutionSink._writeNodeList(element.constantInitializers);
     } finally {
       _resolutionSink.localElements.popScope();
     }
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index bc471b2..195647b 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -285,6 +285,10 @@
       findInClass(class_);
     }
 
+    for (var extension_ in unitElement.extensions) {
+      findIn(extension_.typeParameters);
+    }
+
     for (var mixin in unitElement.mixins) {
       findInClass(mixin);
     }
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
index 1507f47..5d2201c 100644
--- a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -117,7 +117,7 @@
   }
 
   test_class_constructor_initializer_empty() {
-    assertSameSignature(r'''
+    assertNotSameSignature(r'''
 class C {
   C.foo() : ;
 }
@@ -128,8 +128,9 @@
 ''');
   }
 
+  /// See https://github.com/dart-lang/sdk/issues/46206
   test_class_constructor_initializer_notConst() {
-    assertSameSignature(r'''
+    assertNotSameSignature(r'''
 class C {
   final int f;
   C.foo() : f = 1;
diff --git a/pkg/analyzer/test/src/lint/linter/resolve_name_in_scope_test.dart b/pkg/analyzer/test/src/lint/linter/resolve_name_in_scope_test.dart
index 036ee36..0520a63 100644
--- a/pkg/analyzer/test/src/lint/linter/resolve_name_in_scope_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/resolve_name_in_scope_test.dart
@@ -68,6 +68,38 @@
     _checkGetterDifferent(import.topSet('foo'));
   }
 
+  test_class_getter_fromExtends_blockBody() async {
+    await resolve('''
+class A {
+  int get foo => 0;
+}
+
+class B extends A {
+  void bar(int foo) {
+    this.foo;
+  }
+}
+''');
+    _checkGetterRequested(
+      findElement.parameter('foo'),
+    );
+  }
+
+  test_class_getter_fromExtends_expressionBody() async {
+    await resolve('''
+class A {
+  int get foo => 0;
+}
+
+class B extends A {
+  void bar(int foo) => this.foo;
+}
+''');
+    _checkGetterRequested(
+      findElement.parameter('foo'),
+    );
+  }
+
   test_class_getter_none_fromExtends() async {
     await resolve('''
 class A {
@@ -408,6 +440,16 @@
     _checkMethodRequested(findElement.typeParameter('foo'));
   }
 
+  test_class_method_typeParameter() async {
+    await resolve('''
+class A {
+  void foo<T>(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
   test_class_setter_different_formalParameter_constructor() async {
     await resolve('''
 class A {
@@ -538,6 +580,46 @@
     _checkSetterRequested(findElement.setter('foo'));
   }
 
+  test_class_typeParameter_inConstructor() async {
+    await resolve('''
+class A<T> {
+  A(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_class_typeParameter_inField() async {
+    await resolve('''
+class A<T> {
+  T? a;
+}
+''');
+    var node = findNode.simple('T?');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_class_typeParameter_inMethod() async {
+    await resolve('''
+class A<T> {
+  void foo(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_class_typeParameter_inSetter() async {
+    await resolve('''
+class A<T> {
+  set foo(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
   test_extension_method_none_fromExtended() async {
     await resolve('''
 class A {
@@ -608,6 +690,41 @@
     _checkMethodRequested(findElement.method('foo'));
   }
 
+  test_extension_typeParameter_inMethod() async {
+    await resolve('''
+extension E<T> on int {
+  void foo(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_function_typeParameter() async {
+    await resolve('''
+void foo<T>(int T) {}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_genericFunctionType_typeParameter() async {
+    await resolve('''
+void foo(void Function<T>(String T) b) {}
+''');
+    var node = findNode.simple('T)');
+    var T = findNode.typeParameter('T>').declaredElement!;
+    _resultRequested(node, 'T', false, T);
+  }
+
+  test_genericTypeAlias_typeParameter() async {
+    await resolve('''
+typedef A<T> = List<T>;
+''');
+    var node = findNode.simple('T>;');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
   test_mixin_method_requested_formalParameter_method() async {
     await resolve('''
 mixin M {
@@ -634,6 +751,26 @@
     _checkMethodRequested(findElement.method('foo'));
   }
 
+  test_mixin_typeParameter_inField() async {
+    await resolve('''
+mixin A<T> {
+  T? a;
+}
+''');
+    var node = findNode.simple('T?');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
+  test_mixin_typeParameter_inMethod() async {
+    await resolve('''
+mixin A<T> {
+  void foo(int T) {}
+}
+''');
+    var node = findNode.simple('T)');
+    _resultRequested(node, 'T', false, findElement.typeParameter('T'));
+  }
+
   void _checkGetterDifferent(Element expected) {
     var node = findNode.this_('this.foo;');
     _resultDifferent(node, 'foo', false, expected);
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 8473b16..9adf69a 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -13388,6 +13388,7 @@
             periodOffset: 13
             nameEnd: 19
           @25
+            redirectedConstructor: self::@class::C::@constructor::named
 ''');
   }
 
@@ -13467,6 +13468,7 @@
           named @21
             periodOffset: 20
             nameEnd: 26
+            redirectedConstructor: self::@class::C::@constructor::•
 ''');
   }
 
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index 1073c93..ada6b1e 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -39,6 +39,7 @@
   path: any
   source_maps: any
   test: any
+  cli_util: any
   # Unpublished packages that can be used via path dependency
   async_helper:
     path: ../async_helper
diff --git a/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
new file mode 100644
index 0000000..13cc373
--- /dev/null
+++ b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
@@ -0,0 +1,247 @@
+// 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 "dart:convert";
+import "dart:io";
+import "package:kernel/kernel.dart";
+import "package:kernel/ast.dart";
+
+main(List<String> args) async {
+  // Ensure right args are passed.
+  if (args.length < 1) {
+    print("usage: ${Platform.script} a.dill");
+  }
+
+  // Parse .dill and extract component.
+  var dill = args[0];
+  var component = loadComponentFromBinary(dill);
+  var visitor = MetricsVisitor(["dart:html"]);
+
+  // Visit component.
+  component.accept(visitor);
+
+  // Save data to file.
+  visitor.saveDataToFile("dart2html_metrics.json");
+}
+
+/// Visits classes in libraries specified by `libraryFilter`
+/// and aggregates metrics by class.
+class MetricsVisitor extends RecursiveVisitor {
+  String currentClass;
+  List<String> libraryFilter;
+  Map<String, ClassMetrics> classInfo = {};
+
+  MetricsVisitor([filter]) {
+    libraryFilter = filter ?? [];
+  }
+
+  @override
+  void visitComponent(Component node) {
+    super.visitComponent(node);
+    _processData();
+  }
+
+  @override
+  void visitLibrary(Library node) {
+    // Check if this is a library we want to visit.
+    var visit = libraryFilter.isNotEmpty
+        ? libraryFilter
+            .contains("${node.importUri.scheme}:${node.importUri.path}")
+        : true;
+
+    if (visit) {
+      super.visitLibrary(node);
+    }
+  }
+
+  @override
+  void visitProcedure(Procedure node) {
+    classInfo[currentClass].methods.add(ClassMetricsMethod(
+        node.name.text,
+        node.containsSuperCalls,
+        node.isInstanceMember,
+        node.isExternal,
+        node.isAbstract,
+        node.kind.toString()));
+  }
+
+  @override
+  void visitClass(Class node) {
+    // Dont want to add duplicate info.
+    // When mixed, anonymous mixin class generated so we want to ignore.
+    if (!node.isAnonymousMixin) {
+      currentClass = node.name;
+      var metrics = ClassMetrics();
+
+      // Check if class contains native members.
+      if (node.annotations.any(_isNativeMarkerAnnotation)) {
+        metrics.containsNativeMember = true;
+      }
+
+      // Check if Mixed.
+      if (node.superclass?.isAnonymousMixin ?? false) {
+        metrics.mixed = true;
+        metrics.mixins = _filterMixins(node.superclass.demangledName);
+      }
+
+      // Add parents.
+      if (node.superclass != null) {
+        var unmangledParent = _getParent(node.superclass);
+        metrics.parent = unmangledParent;
+      }
+
+      // Check for implemented classes.
+      if (node.implementedTypes.length > 0) {
+        var implementedTypes =
+            node.implementedTypes.map((type) => type.className.asClass.name);
+        metrics.implementedTypes = implementedTypes.toList();
+      }
+
+      classInfo[currentClass] = metrics;
+
+      super.visitClass(node);
+    }
+  }
+
+  // Returns List of parsed mixins from superclass name.
+  List<String> _filterMixins(String superWithMixins) {
+    var start = superWithMixins.indexOf("with") + 4;
+    var mixins = superWithMixins.substring(start);
+    mixins = mixins.replaceAll(" ", "");
+
+    return mixins.split(",");
+  }
+
+  // Recursively searches superclasses, filtering anonymous mixins,
+  // and returns parent class name.
+  String _getParent(Class node) {
+    if (node.isAnonymousMixin) {
+      return _getParent(node.superclass);
+    }
+
+    return node.name;
+  }
+
+  // Returns true if a class Annotation is Native.
+  bool _isNativeMarkerAnnotation(Expression annotation) {
+    if (annotation is ConstructorInvocation) {
+      var type = annotation.constructedType;
+      if (type.classNode.name == "Native") {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Passes through the aggregated data and processes,
+  // adding child classes and overridden methods from parent.
+  void _processData() {
+    classInfo.keys.forEach((className) {
+      var parentName = classInfo[className].parent;
+      if (classInfo[parentName] != null) {
+        classInfo[parentName].inheritedBy.add(className);
+
+        var notOverridden = <String>[];
+        var parentMethods = classInfo[parentName].methods.map((m) => m.name);
+        var classMethods = classInfo[className].methods.map((m) => m.name);
+
+        parentMethods.forEach((method) =>
+            {if (!classMethods.contains(method)) notOverridden.add(method)});
+
+        // Update Method Info.
+        classInfo[className].notOverriddenMethods = notOverridden;
+      }
+    });
+  }
+
+  // Saves the data to file.
+  void saveDataToFile(String filename) {
+    var formatted = jsonFormat(classInfo);
+
+    File(filename).writeAsStringSync(formatted);
+  }
+
+  // Converts the passed Map to a pretty print JSON string.
+  String jsonFormat(Map<String, ClassMetrics> info) {
+    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
+    return encoder.convert(info);
+  }
+}
+
+/// Tracks info compiled for a class.
+class ClassMetrics {
+  List<ClassMetricsMethod> methods;
+  List<String> mixins;
+  List<String> implementedTypes;
+  List<String> notOverriddenMethods;
+  List<String> inheritedBy;
+  String parent;
+  bool mixed;
+  bool containsNativeMember;
+
+  ClassMetrics(
+      {this.mixed = false,
+      this.containsNativeMember = false,
+      this.parent,
+      methods,
+      mixins,
+      notOverridden,
+      implementedTypes,
+      inheritedBy}) {
+    this.methods = methods ?? [];
+    this.mixins = mixins ?? [];
+    this.notOverriddenMethods = notOverridden ?? [];
+    this.implementedTypes = implementedTypes ?? [];
+    this.inheritedBy = inheritedBy ?? [];
+  }
+
+  bool get invokesSuper {
+    if (methods.isNotEmpty) {
+      return methods.any((e) => e.invokesSuper);
+    }
+
+    return false;
+  }
+
+  Map<String, dynamic> toJson() {
+    return {
+      "invokesSuper": invokesSuper,
+      "methods": methods,
+      "mixed": mixed,
+      "mixins": mixins,
+      "parent": parent,
+      "inheritedBy": inheritedBy,
+      "containsNativeMember": containsNativeMember,
+      "notOverriddenMethods": notOverriddenMethods,
+      "implementedTypes": implementedTypes
+    };
+  }
+}
+
+/// Tracks info related to a specific method.
+class ClassMetricsMethod {
+  String name;
+  String methodKind;
+  bool invokesSuper;
+  bool isInstanceMember;
+  bool isExternal;
+  bool isAbstract;
+
+  ClassMetricsMethod(this.name,
+      [this.invokesSuper = false,
+      this.isInstanceMember = false,
+      this.isExternal = false,
+      this.isAbstract = false,
+      this.methodKind = ""]);
+
+  Map<String, dynamic> toJson() {
+    return {
+      "name": name,
+      "invokesSuper": invokesSuper,
+      "isInstanceMember": isInstanceMember,
+      "isExternal": isExternal,
+      "isAbstract": isAbstract,
+      "methodKind": methodKind
+    };
+  }
+}
diff --git a/pkg/compiler/tool/kernel_visitor/test/info_visitor_test.dart b/pkg/compiler/tool/kernel_visitor/test/info_visitor_test.dart
new file mode 100644
index 0000000..1e24648
--- /dev/null
+++ b/pkg/compiler/tool/kernel_visitor/test/info_visitor_test.dart
@@ -0,0 +1,96 @@
+// 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/kernel.dart";
+import "package:expect/expect.dart";
+import "package:expect/minitest.dart";
+import "../dart_html_metrics_visitor.dart";
+import "package:cli_util/cli_util.dart";
+import "package:path/path.dart" as path;
+import "dart:io";
+
+main() async {
+  // Compile Dill
+  var sdkPath = getSdkPath();
+  if (!sdkPath.contains("ReleaseX64")) sdkPath = path.join(sdkPath, "ReleaseX64", "dart-sdk");
+  var scriptPath = Platform.script.path;
+  var pkgPath = path.dirname(
+      path.dirname(path.dirname(path.dirname(path.dirname(scriptPath)))));
+  var compilePath = path.canonicalize(
+      path.join(pkgPath, "front_end", "tool", "_fasta", "compile.dart"));
+  var testClassesPath = path
+      .canonicalize(path.join(path.dirname(scriptPath), "test_classes.dart"));
+  var ddcOutlinePath =
+      path.canonicalize(path.join(sdkPath, "lib", "_internal", "ddc_sdk.dill"));
+  var dillPath = path
+      .canonicalize(path.join(path.dirname(scriptPath), "test_classes.dill"));
+
+  await Process.run(path.join(sdkPath, "bin", "dart"), [
+    compilePath,
+    "--target=dartdevc",
+    "--platform=${ddcOutlinePath}",
+    "-o=${dillPath}",
+    testClassesPath
+  ]);
+
+  // Dill compiled from test_classes.dart using ddc.
+  var component = loadComponentFromBinary(dillPath);
+  var visitor = MetricsVisitor(["file:${testClassesPath}"]);
+
+  component.accept(visitor);
+
+  test("Class A does not call super", () {
+    Expect.equals(visitor.classInfo["A"].invokesSuper, false);
+  });
+
+  test("Class B does call super", () {
+    Expect.equals(visitor.classInfo["B"].invokesSuper, true);
+
+    var callingMethod = visitor.classInfo["B"].methods
+        .where((m) => m.name == "testSuper")
+        .toList()[0];
+    Expect.equals(callingMethod.invokesSuper, true);
+  });
+
+  test("Class C does not call super", () {
+    Expect.equals(visitor.classInfo["C"].invokesSuper, false);
+  });
+
+  test("Class A inherited by B", () {
+    Expect.equals(visitor.classInfo["A"].inheritedBy.contains("B"), true);
+    Expect.equals(visitor.classInfo["B"].parent, "A");
+  });
+
+  test("Class B inherited by C", () {
+    Expect.equals(visitor.classInfo["B"].inheritedBy.contains("C"), true);
+    Expect.equals(visitor.classInfo["C"].parent, "B");
+  });
+
+  test("Class B inherited by F", () {
+    Expect.equals(visitor.classInfo["B"].inheritedBy.contains("F"), true);
+    Expect.equals(visitor.classInfo["F"].parent, "B");
+  });
+
+  test("Class C inherited by nothing", () {
+    Expect.equals(visitor.classInfo["C"].inheritedBy.length, 0);
+  });
+
+  test("Class D mixed with Mix1 and Mix2", () {
+    Expect.equals(visitor.classInfo["D"].mixed, true);
+    Expect.deepEquals(visitor.classInfo["D"].mixins, ["Mix1", "Mix2"]);
+  });
+
+  test("Class F mixed with Mix1 and Mix2", () {
+    Expect.equals(visitor.classInfo["F"].mixed, true);
+    Expect.deepEquals(visitor.classInfo["F"].mixins, ["Mix1", "Mix2"]);
+  });
+
+  test("Class E implements A", () {
+    Expect.equals(visitor.classInfo["E"].implementedTypes.contains("A"), true);
+  });
+
+  test("Class G extends A but fails to override getValue()", () {
+    Expect.equals(
+        visitor.classInfo["G"].notOverriddenMethods.contains("getValue"), true);
+  });
+}
diff --git a/pkg/compiler/tool/kernel_visitor/test/test_classes.dart b/pkg/compiler/tool/kernel_visitor/test/test_classes.dart
new file mode 100644
index 0000000..2b02ef8
--- /dev/null
+++ b/pkg/compiler/tool/kernel_visitor/test/test_classes.dart
@@ -0,0 +1,60 @@
+// 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 info_visitor_test_classes;
+
+// Test superclass value.
+class A {
+  A();
+
+  getValue() {
+    return "Value";
+  }
+}
+
+// Test subclass calling "super".
+class B extends A {
+  B();
+
+  testSuper() {
+    return super.getValue();
+  }
+}
+
+// Test subclass not calling "super".
+class C extends B {
+  C();
+
+  @override
+  getValue() {
+    return "Value";
+  }
+}
+
+// Test class with mixins.
+class Mix1 {}
+
+class Mix2 {}
+
+class D with Mix1, Mix2 {
+  D();
+}
+
+class F extends B with Mix1, Mix2 {
+  F();
+}
+
+// Test class with interface
+class E implements A {
+  E();
+
+  @override
+  getValue() {
+    return "E Value";
+  }
+}
+
+// Test class with unoverriden superclass method
+class G extends A {
+  G();
+}
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index d5d888a..f8e95ef 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -21,7 +21,7 @@
 
 Future<void> main(List<String> args) async {
   // If we're outputting to a terminal, wrap usage text to that width.
-  int outputLineWidth;
+  int? outputLineWidth;
   try {
     outputLineWidth = stdout.terminalColumns;
   } catch (_) {/* Ignore. */}
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
index 3329a8d..f5f0dfe 100644
--- a/pkg/dart2native/lib/dart2native.dart
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -44,7 +44,7 @@
     String platformDill,
     String sourceFile,
     String kernelFile,
-    String packages,
+    String? packages,
     List<String> defines,
     {String enableExperiment = '',
     List<String> extraGenKernelOptions = const []}) {
@@ -68,7 +68,7 @@
     String genSnapshot,
     String kernelFile,
     String snapshotFile,
-    String debugFile,
+    String? debugFile,
     bool enableAsserts,
     List<String> extraGenSnapshotOptions) {
   return Process.run(genSnapshot, [
diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart
index 8c773d6..23797c9 100644
--- a/pkg/dart2native/lib/generate.dart
+++ b/pkg/dart2native/lib/generate.dart
@@ -21,14 +21,14 @@
 
 Future<void> generateNative({
   String kind = 'exe',
-  String sourceFile,
-  String outputFile,
-  String debugFile,
-  String packages,
-  List<String> defines,
+  required String sourceFile,
+  String? outputFile,
+  String? debugFile,
+  String? packages,
+  required List<String> defines,
   String enableExperiment = '',
   bool enableAsserts = false,
-  bool soundNullSafety,
+  bool? soundNullSafety,
   bool verbose = false,
   String verbosity = 'all',
   List<String> extraOptions = const [],
@@ -42,13 +42,13 @@
     final Kind outputKind = {
       'aot': Kind.aot,
       'exe': Kind.exe,
-    }[kind];
+    }[kind]!;
     final sourceWithoutDart = sourcePath.replaceFirst(RegExp(r'\.dart$'), '');
     final outputPath = path.canonicalize(path.normalize(outputFile ??
         {
           Kind.aot: '$sourceWithoutDart.aot',
           Kind.exe: '$sourceWithoutDart.exe',
-        }[outputKind]));
+        }[outputKind]!));
     final debugPath =
         debugFile != null ? path.canonicalize(path.normalize(debugFile)) : null;
 
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index 1e858a5..439a0cb 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: "^2.7.0"
+  sdk: '>=2.12.0 <3.0.0'
 
 # Add the bin/dart2native.dart script to the scripts pub installs.
 executables:
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index e811ba1..b8d1d74 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -241,3 +241,23 @@
 // TODO(sigmund): Delete this API once `member.isRedirectingFactory`
 // is implemented correctly for patch files (Issue #33495).
 bool isRedirectingFactory(ir.Procedure member) => member.isRedirectingFactory;
+
+/// Determines what `ProcedureKind` the given extension [member] is based on
+/// the member name.
+///
+/// Note: classifies operators as `ProcedureKind.Method`.
+ir.ProcedureKind getExtensionMemberKind(ir.Procedure member) {
+  assert(member.isExtensionMember);
+  String name = member.name.text;
+  int pipeIndex = name.indexOf('|');
+  int poundIndex = name.indexOf('#');
+  assert(pipeIndex >= 0);
+  if (poundIndex >= 0) {
+    String getOrSet = name.substring(pipeIndex + 1, poundIndex);
+    return getOrSet == 'get'
+        ? ir.ProcedureKind.Getter
+        : ir.ProcedureKind.Setter;
+  } else {
+    return member.kind;
+  }
+}
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index f8078d1..b74e0bd 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -28,6 +28,7 @@
     await testRedirectingFactoryDirect();
     await testRedirectingFactorySerialized();
     await testRedirectingFactoryPatchFile();
+    await testExtensionMemberKind();
   });
 }
 
@@ -79,3 +80,97 @@
   _B(int x);
 }
 ''';
+
+testExtensionMemberKind() async {
+  var component = await compileUnit(['e.dart'], {'e.dart': extensionSource});
+  var library = component.libraries
+      .firstWhere((l) => l.importUri.path.endsWith('e.dart'));
+  var descriptors =
+      library.extensions.expand((extension) => extension.members).toList();
+
+  // Check generated getters and setters for fields.
+  var fieldGetter =
+      findExtensionField(descriptors, 'field', ir.ExtensionMemberKind.Getter);
+  Expect.equals(
+      api.getExtensionMemberKind(fieldGetter), ir.ProcedureKind.Getter);
+  var fieldSetter =
+      findExtensionField(descriptors, 'field', ir.ExtensionMemberKind.Setter);
+  Expect.equals(
+      api.getExtensionMemberKind(fieldSetter), ir.ProcedureKind.Setter);
+  var staticFieldGetter = findExtensionField(
+      descriptors, 'staticField', ir.ExtensionMemberKind.Getter);
+  Expect.equals(
+      api.getExtensionMemberKind(staticFieldGetter), ir.ProcedureKind.Getter);
+  var staticFieldSetter = findExtensionField(
+      descriptors, 'staticField', ir.ExtensionMemberKind.Setter);
+  Expect.equals(
+      api.getExtensionMemberKind(staticFieldSetter), ir.ProcedureKind.Setter);
+
+  // Check getters and setters.
+  var getter = findExtensionMember(descriptors, 'getter');
+  Expect.equals(api.getExtensionMemberKind(getter), ir.ProcedureKind.Getter);
+  var setter = findExtensionMember(descriptors, 'setter');
+  Expect.equals(api.getExtensionMemberKind(setter), ir.ProcedureKind.Setter);
+  var staticGetter = findExtensionMember(descriptors, 'staticGetter');
+  Expect.equals(
+      api.getExtensionMemberKind(staticGetter), ir.ProcedureKind.Getter);
+  var staticSetter = findExtensionMember(descriptors, 'staticSetter');
+  Expect.equals(
+      api.getExtensionMemberKind(staticSetter), ir.ProcedureKind.Setter);
+
+  // Check methods.
+  var method = findExtensionMember(descriptors, 'method');
+  Expect.equals(api.getExtensionMemberKind(method), ir.ProcedureKind.Method);
+  var methodTearoff = findExtensionTearoff(descriptors, 'get#method');
+  Expect.equals(
+      api.getExtensionMemberKind(methodTearoff), ir.ProcedureKind.Getter);
+  var staticMethod = findExtensionMember(descriptors, 'staticMethod');
+  Expect.equals(
+      api.getExtensionMemberKind(staticMethod), ir.ProcedureKind.Method);
+
+  // Check operators.
+  var operator = findExtensionMember(descriptors, '+');
+  Expect.equals(api.getExtensionMemberKind(operator), ir.ProcedureKind.Method);
+}
+
+ir.Member findExtensionMember(
+    List<ir.ExtensionMemberDescriptor> descriptors, String memberName) {
+  return descriptors
+      .firstWhere((d) => d.name.text == memberName)
+      .member
+      .asMember;
+}
+
+ir.Member findExtensionField(List<ir.ExtensionMemberDescriptor> descriptors,
+    String fieldName, ir.ExtensionMemberKind kind) {
+  return descriptors
+      .firstWhere((d) => d.name.text == fieldName && d.kind == kind)
+      .member
+      .asMember;
+}
+
+ir.Member findExtensionTearoff(
+    List<ir.ExtensionMemberDescriptor> descriptors, String memberName) {
+  return descriptors
+      .map((d) => d.member.asMember)
+      .firstWhere((m) => m.name.text.contains(memberName));
+}
+
+const extensionSource = '''
+class Foo {}
+
+extension Ext on Foo {
+  external int field;
+  external static int staticField;
+
+  external get getter;
+  external set setter(_);
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external int method();
+  external static int staticMethod();
+
+  external operator +(_);
+}
+''';
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index aed39dd..201c0e11 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -391,8 +391,8 @@
 enforced
 enforces
 enforcing
-enters
 engineered
+enters
 enumerates
 env
 eof
@@ -896,6 +896,7 @@
 physically
 pi
 picking
+pipe
 pkg
 play
 player
@@ -911,6 +912,7 @@
 pos
 possibility
 postfix
+pound
 pow
 pragma
 pre
diff --git a/runtime/tests/vm/dart/regress_46799_test.dart b/runtime/tests/vm/dart/regress_46799_test.dart
new file mode 100644
index 0000000..0d44c95
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_46799_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Reduced from
+// The Dart Project Fuzz Tester (1.91).
+// Program generated as:
+//   dart dartfuzz.dart --seed 1052527605 --no-fp --no-ffi --flat
+
+bool var31 = bool.hasEnvironment('z');
+
+@pragma('vm:never-inline')
+num foo0() {
+  print(var31);
+  return -4294967296;
+}
+
+main() {
+  print(((-67) ~/ (var31 ? -83 : foo0())));
+}
diff --git a/runtime/tests/vm/dart_2/regress_46799_test.dart b/runtime/tests/vm/dart_2/regress_46799_test.dart
new file mode 100644
index 0000000..0d44c95
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_46799_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Reduced from
+// The Dart Project Fuzz Tester (1.91).
+// Program generated as:
+//   dart dartfuzz.dart --seed 1052527605 --no-fp --no-ffi --flat
+
+bool var31 = bool.hasEnvironment('z');
+
+@pragma('vm:never-inline')
+num foo0() {
+  print(var31);
+  return -4294967296;
+}
+
+main() {
+  print(((-67) ~/ (var31 ? -83 : foo0())));
+}
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 2b984a0..c531f98 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -59,7 +59,7 @@
 // StorageTrait for HashTable which allows to create hash tables backed by
 // zone memory. Used to compute cluster order for canonical clusters.
 struct GrowableArrayStorageTraits {
-  class Array {
+  class Array : public ZoneAllocated {
    public:
     explicit Array(Zone* zone, intptr_t length)
         : length_(length), array_(zone->Alloc<ObjectPtr>(length)) {}
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 06edf78..acb00ca 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1348,8 +1348,9 @@
   // TODO(alexmarkov): calculate type of InstanceCallInstr eagerly
   // (in optimized mode) and avoid keeping separate result_type.
   CompileType* inferred_type = result_type();
-  if ((inferred_type != NULL) &&
-      (inferred_type->ToNullableCid() != kDynamicCid)) {
+  if ((inferred_type != nullptr) &&
+      ((inferred_type->ToNullableCid() != kDynamicCid) ||
+       (!inferred_type->ToAbstractType()->IsDynamicType()))) {
     TraceStrongModeType(this, inferred_type);
     return *inferred_type;
   }
@@ -1441,8 +1442,11 @@
   if (is_known_list_constructor()) {
     return ComputeListFactoryType(inferred_type, ArgumentValueAt(0));
   }
-  if ((inferred_type != NULL) &&
-      (inferred_type->ToNullableCid() != kDynamicCid)) {
+
+  if ((inferred_type != nullptr) &&
+      ((inferred_type->ToNullableCid() != kDynamicCid) ||
+       (!inferred_type->ToAbstractType()->IsDynamicType()))) {
+    TraceStrongModeType(this, inferred_type);
     return *inferred_type;
   }
 
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 182c090..999790d 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -2274,7 +2274,10 @@
       instance_ ^= value.ptr();
       if (!instance_.IsAssignableTo(type_, instantiator_type_arguments_,
                                     function_type_arguments_)) {
-        ASSERT(!FLAG_identity_reload);
+        // Even if doing an identity reload, type check can fail if hot reload
+        // happens while constructor is still running and field is not
+        // initialized yet, so it has a null value.
+        ASSERT(!FLAG_identity_reload || instance_.IsNull());
         field.set_needs_load_guard(true);
       } else {
         cache_.AddCheck(instance_cid_or_signature_, type_,
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index 1c5e2db..b9400ee 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -780,13 +780,17 @@
     objects_.Add(instance);
 
     const intptr_t next_field_offset = next_field_offset_;
+#if defined(DART_PRECOMPILED_RUNTIME)
     const auto unboxed_fields_bitmap =
         s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+#endif
     for (intptr_t offset = Instance::NextFieldOffset();
          offset < next_field_offset; offset += kCompressedWordSize) {
+#if defined(DART_PRECOMPILED_RUNTIME)
       if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
         continue;
       }
+#endif
       s->Push(reinterpret_cast<CompressedObjectPtr*>(
                   reinterpret_cast<uword>(instance->untag()) + offset)
                   ->Decompress(instance->untag()->heap_base()));
@@ -810,20 +814,24 @@
       Instance* instance = objects_[i];
 
       const intptr_t next_field_offset = next_field_offset_;
+#if defined(DART_PRECOMPILED_RUNTIME)
       const auto unboxed_fields_bitmap =
           s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+#endif
       for (intptr_t offset = Instance::NextFieldOffset();
            offset < next_field_offset; offset += kCompressedWordSize) {
+#if defined(DART_PRECOMPILED_RUNTIME)
         if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
           // Writes 32 bits of the unboxed value at a time
           const uword value = *reinterpret_cast<compressed_uword*>(
               reinterpret_cast<uword>(instance->untag()) + offset);
           s->WriteWordWith32BitWrites(value);
-        } else {
-          s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
-                          reinterpret_cast<uword>(instance->untag()) + offset)
-                          ->Decompress(instance->untag()->heap_base()));
+          continue;
         }
+#endif
+        s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
+                        reinterpret_cast<uword>(instance->untag()) + offset)
+                        ->Decompress(instance->untag()->heap_base()));
       }
     }
   }
@@ -853,37 +861,44 @@
 
   void ReadEdges(MessageDeserializer* d) {
     const intptr_t next_field_offset = cls_.host_next_field_offset();
-    const intptr_t type_argument_field_offset =
-        cls_.host_type_arguments_field_offset();
+#if defined(DART_PRECOMPILED_RUNTIME)
     const auto unboxed_fields_bitmap =
         d->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
             cls_.id());
+#else
+    const intptr_t type_argument_field_offset =
+        cls_.host_type_arguments_field_offset();
     const bool use_field_guards = d->isolate_group()->use_field_guards();
     const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap());
+    Field& field = Field::Handle(d->zone());
+#endif
     Instance& instance = Instance::Handle(d->zone());
     Object& value = Object::Handle(d->zone());
-    Field& field = Field::Handle(d->zone());
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       instance ^= d->Ref(id);
       for (intptr_t offset = Instance::NextFieldOffset();
            offset < next_field_offset; offset += kCompressedWordSize) {
+#if defined(DART_PRECOMPILED_RUNTIME)
         if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
           compressed_uword* p = reinterpret_cast<compressed_uword*>(
               reinterpret_cast<uword>(instance.untag()) + offset);
           // Reads 32 bits of the unboxed value at a time
           *p = d->ReadWordWith32BitReads();
-        } else {
-          value = d->ReadRef();
-          instance.SetFieldAtOffset(offset, value);
-          if (use_field_guards && (offset != type_argument_field_offset) &&
-              (value.ptr() != Object::sentinel().ptr())) {
-            field ^= field_map.At(offset >> kCompressedWordSizeLog2);
-            ASSERT(!field.IsNull());
-            ASSERT(field.HostOffset() == offset);
-            field.RecordStore(value);
-          }
+          continue;
         }
+#endif
+        value = d->ReadRef();
+        instance.SetFieldAtOffset(offset, value);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        if (use_field_guards && (offset != type_argument_field_offset) &&
+            (value.ptr() != Object::sentinel().ptr())) {
+          field ^= field_map.At(offset >> kCompressedWordSizeLog2);
+          ASSERT(!field.IsNull());
+          ASSERT(field.HostOffset() == offset);
+          field.RecordStore(value);
+        }
+#endif
       }
     }
   }
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index a671373..51029ae 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "include/dart_api.h"
 #include "platform/utils.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
@@ -40,6 +41,8 @@
 Dart_Port PortMap::AllocatePort() {
   Dart_Port result;
 
+  ASSERT(mutex_->IsOwnedByCurrentThread());
+
   // Keep getting new values while we have an illegal port number or the port
   // number is already in use.
   do {
@@ -68,6 +71,9 @@
 
 void PortMap::SetPortState(Dart_Port port, PortState state) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return;
+  }
 
   auto it = ports_->TryLookup(port);
   ASSERT(it != ports_->end());
@@ -93,6 +99,10 @@
 Dart_Port PortMap::CreatePort(MessageHandler* handler) {
   ASSERT(handler != NULL);
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return ILLEGAL_PORT;
+  }
+
 #if defined(DEBUG)
   handler->CheckAccess();
 #endif
@@ -126,6 +136,9 @@
   MessageHandler* handler = NULL;
   {
     MutexLocker ml(mutex_);
+    if (ports_ == nullptr) {
+      return false;
+    }
     auto it = ports_->TryLookup(port);
     if (it == ports_->end()) {
       return false;
@@ -165,6 +178,9 @@
 void PortMap::ClosePorts(MessageHandler* handler) {
   {
     MutexLocker ml(mutex_);
+    if (ports_ == nullptr) {
+      return;
+    }
     // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
     // by the [PortMap::mutex_] we already hold.
     for (auto isolate_it = handler->ports_.begin();
@@ -189,6 +205,9 @@
 bool PortMap::PostMessage(std::unique_ptr<Message> message,
                           bool before_events) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return false;
+  }
   auto it = ports_->TryLookup(message->dest_port());
   if (it == ports_->end()) {
     // Ownership of external data remains with the poster.
@@ -203,6 +222,9 @@
 
 bool PortMap::IsLocalPort(Dart_Port id) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return false;
+  }
   auto it = ports_->TryLookup(id);
   if (it == ports_->end()) {
     // Port does not exist.
@@ -216,6 +238,9 @@
 
 bool PortMap::IsLivePort(Dart_Port id) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return false;
+  }
   auto it = ports_->TryLookup(id);
   if (it == ports_->end()) {
     // Port does not exist.
@@ -228,6 +253,9 @@
 
 Isolate* PortMap::GetIsolate(Dart_Port id) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return nullptr;
+  }
   auto it = ports_->TryLookup(id);
   if (it == ports_->end()) {
     // Port does not exist.
@@ -241,6 +269,9 @@
 bool PortMap::IsReceiverInThisIsolateGroup(Dart_Port receiver,
                                            IsolateGroup* group) {
   MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return false;
+  }
   auto it = ports_->TryLookup(receiver);
   if (it == ports_->end()) return false;
   auto isolate = (*it).handler->isolate();
@@ -249,7 +280,6 @@
 }
 
 void PortMap::Init() {
-  // TODO(bkonyi): don't keep ports_ after Dart_Cleanup.
   if (mutex_ == NULL) {
     mutex_ = new Mutex();
   }
@@ -276,11 +306,12 @@
   }
   ports_->Rebalance();
 
+  // Grab the mutex and delete the port set.
+  MutexLocker ml(mutex_);
   delete prng_;
   prng_ = NULL;
-  // TODO(bkonyi): find out why deleting map_ sometimes causes crashes.
-  // delete ports_;
-  // ports_ = nullptr;
+  delete ports_;
+  ports_ = nullptr;
 }
 
 void PortMap::PrintPortsForMessageHandler(MessageHandler* handler,
@@ -292,6 +323,9 @@
   {
     JSONArray ports(&jsobj, "ports");
     SafepointMutexLocker ml(mutex_);
+    if (ports_ == nullptr) {
+      return;
+    }
     for (auto& entry : *ports_) {
       if (entry.handler == handler) {
         if (entry.state == kLivePort) {
@@ -309,6 +343,9 @@
 
 void PortMap::DebugDumpForMessageHandler(MessageHandler* handler) {
   SafepointMutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    return;
+  }
   Object& msg_handler = Object::Handle();
   for (auto& entry : *ports_) {
     if (entry.handler == handler) {
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 1679e2c..744c8a5 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -163,23 +163,23 @@
 // is created within a new thread or ApiNativeScope when calculating high
 // watermarks or memory consumption.
 Zone::Zone()
-    : initial_buffer_(buffer_, kInitialChunkSize),
-      position_(initial_buffer_.start()),
-      limit_(initial_buffer_.end()),
+    : canary_(kCanary),
+      position_(reinterpret_cast<uword>(&buffer_)),
+      limit_(position_ + kInitialChunkSize),
       head_(NULL),
       large_segments_(NULL),
-      handles_(),
-      previous_(NULL) {
+      previous_(NULL),
+      handles_() {
   ASSERT(Utils::IsAligned(position_, kAlignment));
   Segment::IncrementMemoryCapacity(kInitialChunkSize);
 #ifdef DEBUG
   // Zap the entire initial buffer.
-  memset(initial_buffer_.pointer(), kZapUninitializedByte,
-         initial_buffer_.size());
+  memset(&buffer_, kZapUninitializedByte, kInitialChunkSize);
 #endif
 }
 
 Zone::~Zone() {
+  ASSERT(canary_ == kCanary);
   if (FLAG_trace_zones) {
     DumpZoneSizes();
   }
@@ -198,10 +198,10 @@
   }
 // Reset zone state.
 #ifdef DEBUG
-  memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size());
+  memset(&buffer_, kZapDeletedByte, kInitialChunkSize);
 #endif
-  position_ = initial_buffer_.start();
-  limit_ = initial_buffer_.end();
+  position_ = reinterpret_cast<uword>(&buffer_);
+  limit_ = position_ + kInitialChunkSize;
   small_segment_capacity_ = 0;
   head_ = NULL;
   large_segments_ = NULL;
@@ -215,9 +215,9 @@
     size += s->size();
   }
   if (head_ == NULL) {
-    return size + (position_ - initial_buffer_.start());
+    return size + (position_ - reinterpret_cast<uword>(&buffer_));
   }
-  size += initial_buffer_.size();
+  size += kInitialChunkSize;
   for (Segment* s = head_->next(); s != NULL; s = s->next()) {
     size += s->size();
   }
@@ -230,9 +230,9 @@
     size += s->size();
   }
   if (head_ == NULL) {
-    return size + initial_buffer_.size();
+    return size + kInitialChunkSize;
   }
-  size += initial_buffer_.size();
+  size += kInitialChunkSize;
   for (Segment* s = head_; s != NULL; s = s->next()) {
     size += s->size();
   }
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index cb45741..e4a0030 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -141,13 +141,9 @@
   template <class ElementType>
   static inline void CheckLength(intptr_t len);
 
-  // This buffer is used for allocation before any segments.
-  // This would act as the initial stack allocated chunk so that we don't
-  // end up calling malloc/free on zone scopes that allocate less than
-  // kChunkSize
-  COMPILE_ASSERT(kAlignment <= 8);
-  ALIGN8 uint8_t buffer_[kInitialChunkSize];
-  MemoryRegion initial_buffer_;
+  // Guard against `new (zone) DoesNotExtendZoneAllocated()`.
+  static constexpr uint64_t kCanary = 0x656e6f7a74726164ull;  // "dartzone"
+  uint64_t canary_;
 
   // The free region in the current (head) segment or the initial buffer is
   // represented as the half-open interval [position, limit). The 'position'
@@ -169,11 +165,18 @@
   // List of large segments allocated in this zone; may be NULL.
   Segment* large_segments_;
 
+  // Used for chaining zones in order to allow unwinding of stacks.
+  Zone* previous_;
+
   // Structure for managing handles allocation.
   VMHandles handles_;
 
-  // Used for chaining zones in order to allow unwinding of stacks.
-  Zone* previous_;
+  // This buffer is used for allocation before any segments.
+  // This would act as the initial stack allocated chunk so that we don't
+  // end up calling malloc/free on zone scopes that allocate less than
+  // kChunkSize
+  COMPILE_ASSERT(kAlignment <= 8);
+  ALIGN8 uint8_t buffer_[kInitialChunkSize];
 
   friend class StackZone;
   friend class ApiZone;
@@ -274,23 +277,26 @@
                                   intptr_t new_len) {
   CheckLength<ElementType>(new_len);
   const intptr_t kElementSize = sizeof(ElementType);
-  uword old_end = reinterpret_cast<uword>(old_data) + (old_len * kElementSize);
-  // Resize existing allocation if nothing was allocated in between...
-  if (Utils::RoundUp(old_end, kAlignment) == position_) {
-    uword new_end =
-        reinterpret_cast<uword>(old_data) + (new_len * kElementSize);
-    // ...and there is sufficient space.
-    if (new_end <= limit_) {
-      ASSERT(new_len >= old_len);
-      position_ = Utils::RoundUp(new_end, kAlignment);
+  if (old_data != nullptr) {
+    uword old_end =
+        reinterpret_cast<uword>(old_data) + (old_len * kElementSize);
+    // Resize existing allocation if nothing was allocated in between...
+    if (Utils::RoundUp(old_end, kAlignment) == position_) {
+      uword new_end =
+          reinterpret_cast<uword>(old_data) + (new_len * kElementSize);
+      // ...and there is sufficient space.
+      if (new_end <= limit_) {
+        ASSERT(new_len >= old_len);
+        position_ = Utils::RoundUp(new_end, kAlignment);
+        return old_data;
+      }
+    }
+    if (new_len <= old_len) {
       return old_data;
     }
   }
-  if (new_len <= old_len) {
-    return old_data;
-  }
   ElementType* new_data = Alloc<ElementType>(new_len);
-  if (old_data != 0) {
+  if (old_data != nullptr) {
     memmove(reinterpret_cast<void*>(new_data),
             reinterpret_cast<void*>(old_data), old_len * kElementSize);
   }
diff --git a/tools/VERSION b/tools/VERSION
index 3cb9897..c9d32db 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 385
+PRERELEASE 386
 PRERELEASE_PATCH 0
\ No newline at end of file