Version 2.18.0-225.0.dev

Merge commit 'c97f7b7fadca5b6a3e220a20dbefd4eaa3b442ba' into 'dev'
diff --git a/DEPS b/DEPS
index 1c07751..9821742 100644
--- a/DEPS
+++ b/DEPS
@@ -109,7 +109,7 @@
   "dart_style_rev": "d7b73536a8079331c888b7da539b80e6825270ea", # manually rev'd
 
   "dartdoc_rev": "58348a98b992ce99b95d23131b67227bdb2b4875",
-  "devtools_rev": "51ac983d2db7eb19b3ce5956cb70b769d74fe784",
+  "devtools_rev": "0aa619c42a68d6db4c94a7838121811aba8f5eb1",
   "ffi_rev": "18b2b549d55009ff594600b04705ff6161681e07",
   "file_rev": "0132eeedea2933513bf230513a766a8baeab0c4f",
   "fixnum_rev": "164712f6547cdfb2709b752188186baf31fd1730",
diff --git a/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
index a2fe460..e3af6d6 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_completion_benchmark.dart
@@ -95,7 +95,7 @@
     );
 
     if (!quick) {
-      // This scenario is relatively easy - the file is small, less then 3KB.
+      // This scenario is relatively easy - the file is small, less than 3KB.
       // But we don't have any prefix to filter, so if we don't restrict the
       // number of suggestions, we might spend too much time serializing into
       // JSON in the server, and deserializing on the client.
diff --git a/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
index d9f99f0..d3907ec 100644
--- a/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
+++ b/pkg/analysis_server/lib/src/analytics/google_analytics_manager.dart
@@ -41,6 +41,11 @@
   /// was enabled.
   final Map<String, int> _lintUsageCounts = {};
 
+  /// A map from the name of a diagnostic to a map whose values are the number
+  /// of times that the severity of the diagnostic was changed to the severity
+  /// represented by the key.
+  final Map<String, Map<String, int>> _severityAdjustments = {};
+
   /// Initialize a newly created analytics manager to report to the [analytics]
   /// service.
   GoogleAnalyticsManager(this.analytics);
@@ -66,12 +71,12 @@
         var name = rule.name;
         _lintUsageCounts[name] = (_lintUsageCounts[name] ?? 0) + 1;
       }
-      // TODO(brianwilkerson) Collect other context-dependent information, such
-      //  as which codes have a different severity assigned to them:
-      // for (var processor in context.analysisOptions.errorProcessors) {
-      //   processor.code;
-      //   processor.severity;
-      // }
+      for (var processor in context.analysisOptions.errorProcessors) {
+        var severity = processor.severity?.name ?? 'ignore';
+        var severityCounts =
+            _severityAdjustments.putIfAbsent(processor.code, () => {});
+        severityCounts[severity] = (severityCounts[severity] ?? 0) + 1;
+      }
     }
   }
 
@@ -140,6 +145,7 @@
     _sendPluginResponseTimes();
     _sendNotificationHandlingTimes();
     _sendLintUsageCounts();
+    _sendSeverityAdjustments();
 
     analytics.waitForLastPing(timeout: Duration(milliseconds: 200)).then((_) {
       analytics.close();
@@ -227,9 +233,11 @@
   }
 
   void _sendLintUsageCounts() {
-    analytics.sendEvent('language_server', 'lintUsageCounts', parameters: {
-      'usageCounts': _lintUsageCounts.toString(),
-    });
+    if (_lintUsageCounts.isNotEmpty) {
+      analytics.sendEvent('language_server', 'lintUsageCounts', parameters: {
+        'usageCounts': json.encode(_lintUsageCounts),
+      });
+    }
   }
 
   /// Send information about the notifications handled by the server.
@@ -286,6 +294,15 @@
       'plugins': _pluginData.usageCountData,
     });
   }
+
+  void _sendSeverityAdjustments() {
+    if (_severityAdjustments.isNotEmpty) {
+      analytics
+          .sendEvent('language_server', 'severityAdjustments', parameters: {
+        'adjustmentCounts': json.encode(_severityAdjustments),
+      });
+    }
+  }
 }
 
 /// Data about a request that was received and is being handled.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart b/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
index 9bf265c..d95deb7 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
@@ -88,6 +88,8 @@
     } else if (node is VariableDeclaration &&
         parent is VariableDeclarationList) {
       list = parent;
+    } else if (node is VariableDeclarationList) {
+      list = node;
     } else {
       return;
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart
new file mode 100644
index 0000000..73078a5
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryFinal extends CorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_FINAL;
+
+  @override
+  FixKind get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_FINAL_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var node = this.node;
+    Token? keyword;
+    if (node is FieldFormalParameter) {
+      keyword = node.keyword;
+    } else if (node is SuperFormalParameter) {
+      keyword = node.keyword;
+    }
+    if (keyword == null) return;
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addDeletion(range.startStart(keyword!, keyword.next!));
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 5adb652..cba9147 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1456,7 +1456,7 @@
 HintCode.UNNECESSARY_CAST:
   status: hasFix
 HintCode.UNNECESSARY_FINAL:
-  status: needsEvaluation
+  status: hasFix
 HintCode.UNNECESSARY_IGNORE:
   status: needsEvaluation
 HintCode.UNNECESSARY_IMPORT:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index ed8f791..e5e3585 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1128,6 +1128,16 @@
     DartFixKindPriority.IN_FILE,
     'Remove all unnecessary casts in file',
   );
+  static const REMOVE_UNNECESSARY_FINAL = FixKind(
+    'dart.fix.remove.unnecessaryFinal',
+    DartFixKindPriority.DEFAULT,
+    "Remove unnecessary 'final'",
+  );
+  static const REMOVE_UNNECESSARY_FINAL_MULTI = FixKind(
+    'dart.fix.remove.unnecessaryFinal.multi',
+    DartFixKindPriority.IN_FILE,
+    "Remove all unnecessary 'final's in file",
+  );
   static const REMOVE_UNNECESSARY_CONST = FixKind(
     'dart.fix.remove.unnecessaryConst',
     DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index c79ab5f..61583a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -139,6 +139,7 @@
 import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_final.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
@@ -1326,6 +1327,9 @@
     HintCode.UNNECESSARY_CAST: [
       RemoveUnnecessaryCast.new,
     ],
+    HintCode.UNNECESSARY_FINAL: [
+      RemoveUnnecessaryFinal.new,
+    ],
     HintCode.UNNECESSARY_IMPORT: [
       RemoveUnusedImport.new,
     ],
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 5867145..ac4fb50 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -230,7 +230,7 @@
     }
     if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
-          'The selection end offset must be less then the length of the file.');
+          'The selection end offset must be less than the length of the file.');
     }
 
     var selectionStr = utils.getRangeText(selectionRange);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 5b43952..44e901d 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -458,7 +458,7 @@
     }
     if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
-          'The selection end offset must be less then the length of the file.');
+          'The selection end offset must be less than the length of the file.');
     }
 
     // Check for implicitly selected closure.
@@ -989,10 +989,19 @@
       if (element is FunctionElement || element is MethodElement) {
         invalidSelection('Cannot extract a single method name.');
       }
-      // name in property access
-      if (node.parent is PrefixedIdentifier &&
-          (node.parent as PrefixedIdentifier).identifier == node) {
-        invalidSelection('Can not extract name part of a property access.');
+      var parent = node.parent;
+      if (parent is PrefixedIdentifier) {
+        if (parent.identifier == node) {
+          // name in property access
+          invalidSelection('Cannot extract name part of a property access.');
+        } else if (parent.prefix == node && parent.parent is NamedType) {
+          // prefix in a named type (for example `io` in `io.File`)
+          invalidSelection('Cannot extract prefix part of a type reference.');
+        }
+      }
+      // part of a named type (for example `int` in `int?`)
+      if (node.parent is NamedType) {
+        invalidSelection('Cannot extract a single type reference.');
       }
     }
   }
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index d580d4e..06ad142b 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -364,6 +364,22 @@
     expect(codeAction, isNull);
   }
 
+  Future<void> test_invalidLocation_importPrefix() async {
+    const content = '''
+import 'dart:io' as io;
+
+i^o.File a;
+    ''';
+    newFile(mainFilePath, withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    expect(codeAction, isNull);
+  }
+
   Future<void> test_progress_clientProvided() async {
     const content = '''
 void f() {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index 865fbcb..b6ae4c4 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -438,7 +438,7 @@
 ''');
     _createRefactoringWithSuffix('fff', ' = 1');
     return _assertConditionsFatal(
-        'Can not extract name part of a property access.');
+        'Cannot extract name part of a property access.');
   }
 
   Future<void> test_bad_newMethodName_notIdentifier() async {
@@ -752,6 +752,27 @@
     return _assertConditionsFatal('Cannot extract a single type reference.');
   }
 
+  Future<void> test_bad_typeReference_nullable() async {
+    await indexTestUnit('''
+// Dummy comment ("The selection offset must be greater than zero")
+int? f;
+''');
+    _createRefactoringForString('int');
+    return _assertConditionsFatal('Cannot extract a single type reference.');
+  }
+
+  Future<void> test_bad_typeReference_prefix() async {
+    await indexTestUnit('''
+import 'dart:io' as io;
+void f() {
+  io.File f = io.File('');
+}
+''');
+    _createRefactoringWithSuffix('io', '.File f');
+    return _assertConditionsFatal(
+        'Cannot extract prefix part of a type reference.');
+  }
+
   Future<void> test_bad_variableDeclarationFragment() async {
     await indexTestUnit('''
 void f() {
@@ -1251,6 +1272,29 @@
     expect(refactoring.lengths, unorderedEquals([5, 6]));
   }
 
+  Future<void> test_prefixPartOfQualified() async {
+    await indexTestUnit('''
+class A {
+  var fff;
+}
+void f(A a) {
+  a.fff = 5;
+}
+''');
+    _createRefactoringForStringOffset('a.fff');
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+class A {
+  var fff;
+}
+void f(A a) {
+  res(a).fff = 5;
+}
+
+A res(A a) => a;
+''');
+  }
+
   Future<void> test_returnType_closure() async {
     await indexTestUnit('''
 process(f(x)) {}
diff --git a/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart b/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
index 32a5783..1f8dba5 100644
--- a/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
+++ b/pkg/analysis_server/test/src/analytics/google_analytics_manager_test.dart
@@ -12,7 +12,10 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/context_root.dart' as analyzer;
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:linter/src/rules.dart';
 import 'package:telemetry/telemetry.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -28,23 +31,43 @@
   final analytics = _MockAnalytics();
   late final manager = GoogleAnalyticsManager(analytics);
 
-  String get testPackageRootPath => '/home/package';
+  Folder get testPackageRoot => getFolder('/home/package');
 
-  void test_createAnalysisContexts_single() {
+  String get testPackageRootPath => testPackageRoot.path;
+
+  void test_createAnalysisContexts_lints() {
     _createAnalysisOptionsFile(lints: [
       'avoid_dynamic_calls',
       'await_only_futures',
       'unawaited_futures'
     ]);
-    var collection =
-        AnalysisContextCollection(includedPaths: [testPackageRootPath]);
+    var collection = _createContexts();
     _defaultStartup();
     manager.createdAnalysisContexts(collection.contexts);
     manager.shutdown();
     analytics.assertEvents([
       _ExpectedEvent.session(),
       _ExpectedEvent.lintUsageCounts(parameters: {
-        'usageCounts': '{}',
+        'usageCounts':
+            '{"avoid_dynamic_calls":1,"await_only_futures":1,"unawaited_futures":1}',
+      }),
+    ]);
+  }
+
+  void test_createAnalysisContexts_severityAdjustments() {
+    _createAnalysisOptionsFile(errors: {
+      'avoid_dynamic_calls': 'error',
+      'await_only_futures': 'ignore',
+    });
+    var collection = _createContexts();
+    _defaultStartup();
+    manager.createdAnalysisContexts(collection.contexts);
+    manager.shutdown();
+    analytics.assertEvents([
+      _ExpectedEvent.session(),
+      _ExpectedEvent.severityAdjustments(parameters: {
+        'adjustmentCounts':
+            '{"AVOID_DYNAMIC_CALLS":{"ERROR":1},"AWAIT_ONLY_FUTURES":{"ignore":1}}',
       }),
     ]);
   }
@@ -62,7 +85,6 @@
         'method': 'analysis.getNavigation',
         'duration': _IsPercentiles(),
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
     PluginManager.pluginResponseTimes.clear();
   }
@@ -84,7 +106,6 @@
         'method': Method.workspace_didCreateFiles.toString(),
         'duration': _IsPercentiles(),
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -114,7 +135,6 @@
         'removed':
             '{"count":1,"percentiles":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]}',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -138,7 +158,6 @@
         ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_EXCLUDED:
             '{"count":1,"percentiles":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]}',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -160,7 +179,6 @@
         ANALYSIS_REQUEST_SET_PRIORITY_FILES_FILES:
             '{"count":1,"percentiles":[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]}',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -181,7 +199,6 @@
         'duration': _IsPercentiles(),
         EDIT_REQUEST_GET_REFACTORING_KIND: '{"RENAME":1}',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -201,7 +218,6 @@
         'parameters':
             'closingLabels,onlyAnalyzeProjectsWithOpenFiles,suggestFromUnimportedLibraries',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -227,7 +243,6 @@
         'openWorkspacePaths':
             '{"count":1,"percentiles":[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]}',
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -244,7 +259,6 @@
         'method': SERVER_REQUEST_SHUTDOWN,
         'duration': _IsPercentiles(),
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -272,7 +286,6 @@
         'sdkVersion': sdkVersion,
         'duration': _IsStringEncodedPositiveInt(),
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -289,7 +302,6 @@
       _ExpectedEvent.session(parameters: {
         'plugins': '{"recordCount":1,"rootCounts":{"a":$counts,"b":$counts}}'
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
@@ -314,13 +326,13 @@
         'sdkVersion': sdkVersion,
         'duration': _IsStringEncodedPositiveInt(),
       }),
-      _ExpectedEvent.lintUsageCounts(),
     ]);
   }
 
   /// Create an analysis options file based on the given arguments.
   void _createAnalysisOptionsFile({
     String? path,
+    Map<String, String>? errors,
     List<String>? experiments,
     bool? implicitCasts,
     List<String>? lints,
@@ -328,10 +340,17 @@
     path ??= '$testPackageRootPath/analysis_options.yaml';
     var buffer = StringBuffer();
 
-    if (experiments != null || implicitCasts != null) {
+    if (errors != null || experiments != null || implicitCasts != null) {
       buffer.writeln('analyzer:');
     }
 
+    if (errors != null) {
+      buffer.writeln('  errors:');
+      for (var entry in errors.entries) {
+        buffer.writeln('    ${entry.key}: ${entry.value}');
+      }
+    }
+
     if (experiments != null) {
       buffer.writeln('  enable-experiment:');
       for (var experiment in experiments) {
@@ -355,6 +374,16 @@
     newFile(path, buffer.toString());
   }
 
+  AnalysisContextCollection _createContexts() {
+    var sdkRoot = getFolder('/sdk');
+    createMockSdk(resourceProvider: resourceProvider, root: sdkRoot);
+    registerLintRules();
+    return AnalysisContextCollection(
+        resourceProvider: resourceProvider,
+        includedPaths: [testPackageRootPath],
+        sdkPath: sdkRoot.path);
+  }
+
   void _defaultStartup() {
     manager.startUp(
         time: DateTime.now(),
@@ -406,6 +435,9 @@
   _ExpectedEvent.session({Map<String, Object>? parameters})
       : this('language_server', 'session', parameters: parameters);
 
+  _ExpectedEvent.severityAdjustments({Map<String, Object>? parameters})
+      : this('language_server', 'severityAdjustments', parameters: parameters);
+
   /// Compare the expected event with the [actual] event, failing if the actual
   /// doesn't match the expected.
   void matches(_Event actual) {
@@ -430,6 +462,27 @@
       }
     }
   }
+
+  @override
+  String toString() {
+    var buffer = StringBuffer();
+    buffer.write('category: ');
+    buffer.writeln(category);
+    buffer.write('action: ');
+    buffer.writeln(action);
+    buffer.write('label: ');
+    buffer.writeln(label);
+    buffer.write('value: ');
+    buffer.writeln(value);
+    var parameterMap = parameters;
+    if (parameterMap != null) {
+      for (var entry in parameterMap.entries) {
+        buffer.write('value: ');
+        buffer.writeln('${entry.key}: ${entry.value}');
+      }
+    }
+    return buffer.toString();
+  }
 }
 
 /// A matcher for strings containing positive integer values.
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart
new file mode 100644
index 0000000..70f9035f
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart
@@ -0,0 +1,122 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnnecessaryFinalBulkTest);
+    defineReflectiveTests(RemoveUnnecessaryFinalMultiTest);
+    defineReflectiveTests(RemoveUnnecessaryFinalTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalBulkTest extends BulkFixProcessorTest {
+  Future<void> test_assignment() async {
+    await resolveTestCode('''
+class A {
+  A(final this.value);
+  int value;
+}
+class B extends A {
+  B(final super.value);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(this.value);
+  int value;
+}
+class B extends A {
+  B(super.value);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalMultiTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_FINAL_MULTI;
+
+  Future<void> test_multi() async {
+    await resolveTestCode('''
+class A {
+  A(final this.v1, final this.v2);
+  int v1;
+  int v2;
+}
+''');
+    await assertHasFixAllFix(HintCode.UNNECESSARY_FINAL, '''
+class A {
+  A(this.v1, this.v2);
+  int v1;
+  int v2;
+}
+''');
+  }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_FINAL;
+
+  Future<void> test_positional() async {
+    await resolveTestCode('''
+class C {
+  C([final this.value = 0]);
+  int value;
+}
+''');
+    await assertHasFix('''
+class C {
+  C([this.value = 0]);
+  int value;
+}
+''');
+  }
+
+  Future<void> test_super() async {
+    await resolveTestCode('''
+class A {
+  A(this.value);
+  int value;
+}
+class B extends A {
+  B(final super.value);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(this.value);
+  int value;
+}
+class B extends A {
+  B(super.value);
+}
+''');
+  }
+
+  Future<void> test_this() async {
+    await resolveTestCode('''
+class C {
+  C(final this.value);
+  int value;
+}
+''');
+    await assertHasFix('''
+class C {
+  C(this.value);
+  int value;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 768c4c6..291306b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -169,6 +169,7 @@
 import 'remove_type_arguments_test.dart' as remove_type_arguments;
 import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
 import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
+import 'remove_unnecessary_final_test.dart' as remove_unnecessary_final;
 import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
 import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
 import 'remove_unnecessary_parentheses_test.dart'
@@ -383,6 +384,7 @@
     remove_type_arguments.main();
     remove_unnecessary_cast.main();
     remove_unnecessary_const.main();
+    remove_unnecessary_final.main();
     remove_unnecessary_late.main();
     remove_unnecessary_new.main();
     remove_unnecessary_parentheses.main();
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index d40a6e6..ed113f0 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -2,6 +2,7 @@
 * Update SDK constraints to `>=2.17.0 <3.0.0`.
 * Deprecated `ImportDirective.COMPARATOR`, use appropriate custom logic, if necessary.
 * Deprecated `Element.isAccessibleIn()`, use `isAccessibleIn2()` instead.
+* Bug fixes: 49225. 
 
 ## 4.1.0
 * Deprecated `ParameterElement.isNotOptional`, use `isRequired` instead.
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 679555e..07c1d2a 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -1084,8 +1084,7 @@
       return null;
     }
 
-    return ParameterMember(
-        _typeProvider, superConstructorParameter, _substitution, isLegacy);
+    return ParameterMember.from(superConstructorParameter, substitution);
   }
 
   @override
diff --git a/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
index 42db1a5..1e9388a 100644
--- a/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -16,6 +17,50 @@
 
 @reflectiveTest
 class SuperFormalParameterTest extends PubPackageResolutionTest {
+  test_element_typeParameterSubstitution_chained() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  A({int? key});
+}
+
+class B<U> extends A<U> {
+  B({super.key});
+}
+
+class C<V> extends B<V> {
+  C({super.key});
+}
+''');
+
+    final C = findElement.unnamedConstructor('C');
+    final C_key = C.superFormalParameter('key');
+
+    final B_key_member = C_key.superConstructorParameter;
+    B_key_member as SuperFormalParameterMember;
+
+    final B = findElement.unnamedConstructor('B');
+    final B_key = B.superFormalParameter('key');
+    assertElement2(
+      B_key_member,
+      declaration: B_key,
+      substitution: {'U': 'V'},
+    );
+
+    final A_key_member = B_key_member.superConstructorParameter;
+    A_key_member as ParameterMember;
+
+    final A = findElement.unnamedConstructor('A');
+    final A_key = A.parameter('key');
+    assertElement2(
+      A_key_member,
+      declaration: A_key,
+      substitution: {
+        'T': 'V',
+        'U': 'V',
+      },
+    );
+  }
+
   test_functionTyped() async {
     await assertNoErrorsInCode(r'''
 class A {
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index aee4e69..08df41c 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -7,7 +7,7 @@
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import 'class_relation.dart';
 import 'constants.dart';
 import 'impact_data.dart';
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 25cb12d..8453739 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -13,9 +13,9 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../ir/scope.dart';
-import '../kernel/element_map.dart';
+import '../kernel/element_map.dart' show KernelToElementMap;
 import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../util/enumset.dart';
 import 'class_relation.dart';
 import 'constants.dart';
@@ -1103,12 +1103,12 @@
     _typeUses = source.readListOrNull(() => _TypeUse.fromDataSource(source));
     _redirectingInitializers = source
         .readListOrNull(() => _RedirectingInitializer.fromDataSource(source));
-    _fieldInitializers = source.readMemberNodes<ir.Field>(emptyAsNull: true);
+    _fieldInitializers = source.readMemberNodesOrNull<ir.Field>();
     _fieldConstantInitializers =
-        source.readMemberNodeMap(source.readTreeNodes, emptyAsNull: true);
+        source.readMemberNodeMapOrNull(source.readTreeNodes);
     _typeLiterals =
         source.readListOrNull(() => _TypeLiteral.fromDataSource(source));
-    _localFunctions = source.readTreeNodes(emptyAsNull: true);
+    _localFunctions = source.readTreeNodesOrNull();
     _genericInstantiations = source
         .readListOrNull(() => _GenericInstantiation.fromDataSource(source));
     _staticSets =
@@ -1135,14 +1135,11 @@
     _forInData = source.readListOrNull(() => _ForInData.fromDataSource(source));
 
     // TODO(johnniwinther): Remove these when CFE provides constants.
-    _constructorNodes =
-        source.readMemberNodes<ir.Constructor>(emptyAsNull: true);
-    _fieldNodes = source.readMemberNodes<ir.Field>(emptyAsNull: true);
-    _procedureNodes = source.readMemberNodes<ir.Procedure>(emptyAsNull: true);
-    _switchStatementNodes =
-        source.readTreeNodes<ir.SwitchStatement>(emptyAsNull: true);
-    _staticInvocationNodes =
-        source.readTreeNodes<ir.StaticInvocation>(emptyAsNull: true);
+    _constructorNodes = source.readMemberNodesOrNull<ir.Constructor>();
+    _fieldNodes = source.readMemberNodesOrNull<ir.Field>();
+    _procedureNodes = source.readMemberNodesOrNull<ir.Procedure>();
+    _switchStatementNodes = source.readTreeNodesOrNull<ir.SwitchStatement>();
+    _staticInvocationNodes = source.readTreeNodesOrNull<ir.StaticInvocation>();
     _hasConstSymbolConstructorInvocation = source.readBool();
     source.end(tag);
   }
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 9b41b8e..37662b2 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -2,14 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.10
-
 import '../common.dart';
 import '../common/elements.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../ir/runtime_type_analysis.dart';
-import '../kernel/kernel_strategy.dart' show KernelFrontendStrategy;
+import '../kernel/kernel_strategy_migrated.dart'
+    show KernelFrontendStrategyForBackendUsage;
 import '../serialization/serialization_interfaces.dart';
 import '../universe/feature.dart';
 import '../util/util.dart' show Setlet;
@@ -23,8 +22,8 @@
   /// Serializes this [BackendUsage] to [sink].
   void writeToDataSink(DataSinkWriter sink);
 
-  bool needToInitializeIsolateAffinityTag;
-  bool needToInitializeDispatchProperty;
+  abstract bool needToInitializeIsolateAffinityTag;
+  abstract bool needToInitializeDispatchProperty;
 
   /// Returns `true` if [element] is a function called by the backend.
   bool isFunctionUsedByBackend(FunctionEntity element);
@@ -94,10 +93,10 @@
   void registerRuntimeTypeUse(RuntimeTypeUse runtimeTypeUse);
 
   /// `true` if `Function.apply` is used.
-  bool isFunctionApplyUsed;
+  abstract bool isFunctionApplyUsed;
 
   /// `true` if `noSuchMethod` is used.
-  bool isNoSuchMethodUsed;
+  abstract bool isNoSuchMethodUsed;
 
   /// Register that `dart:html` is loaded.
   void registerHtmlIsLoaded();
@@ -106,10 +105,10 @@
 }
 
 class BackendUsageBuilderImpl implements BackendUsageBuilder {
-  final KernelFrontendStrategy _frontendStrategy;
+  final KernelFrontendStrategyForBackendUsage _frontendStrategy;
   // TODO(johnniwinther): Remove the need for these.
-  Setlet<FunctionEntity> _globalFunctionDependencies;
-  Setlet<ClassEntity> _globalClassDependencies;
+  Setlet<FunctionEntity>? _globalFunctionDependencies;
+  Setlet<ClassEntity>? _globalClassDependencies;
 
   /// List of methods that the backend may use.
   final Set<FunctionEntity> _helperFunctionsUsed = {};
@@ -210,11 +209,11 @@
   @override
   void processBackendImpact(BackendImpact backendImpact) {
     for (FunctionEntity staticUse in backendImpact.staticUses) {
-      assert(staticUse != null);
+      assert((staticUse as dynamic) != null); // TODO(48820): Remove when sound.
       _processBackendStaticUse(staticUse);
     }
     for (FunctionEntity staticUse in backendImpact.globalUses) {
-      assert(staticUse != null);
+      assert((staticUse as dynamic) != null); // TODO(48820): Remove when sound.
       _processBackendStaticUse(staticUse, isGlobal: true);
     }
     for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) {
@@ -258,16 +257,16 @@
 
   @override
   void registerGlobalFunctionDependency(FunctionEntity element) {
-    assert(element != null);
+    assert((element as dynamic) != null); // TODO(48820): Remove when sound.
     _globalFunctionDependencies ??= Setlet();
-    _globalFunctionDependencies.add(element);
+    _globalFunctionDependencies!.add(element);
   }
 
   @override
   void registerGlobalClassDependency(ClassEntity element) {
-    assert(element != null);
+    assert((element as dynamic) != null); // TODO(48820): Remove when sound.
     _globalClassDependencies ??= Setlet();
-    _globalClassDependencies.add(element);
+    _globalClassDependencies!.add(element);
   }
 
   @override
@@ -305,8 +304,8 @@
   static const String tag = 'backend-usage';
 
   // TODO(johnniwinther): Remove the need for these.
-  final Set<FunctionEntity> _globalFunctionDependencies;
-  final Set<ClassEntity> _globalClassDependencies;
+  final Set<FunctionEntity>? _globalFunctionDependencies;
+  final Set<ClassEntity>? _globalClassDependencies;
 
   /// Set of functions called by the backend.
   final Set<FunctionEntity> _helperFunctionsUsed;
@@ -340,19 +339,19 @@
   final bool isHtmlLoaded;
 
   BackendUsageImpl(
-      {Set<FunctionEntity> globalFunctionDependencies,
-      Set<ClassEntity> globalClassDependencies,
-      Set<FunctionEntity> helperFunctionsUsed,
-      Set<ClassEntity> helperClassesUsed,
-      this.needToInitializeIsolateAffinityTag,
-      this.needToInitializeDispatchProperty,
-      this.requiresPreamble,
-      this.requiresStartupMetrics,
-      Set<RuntimeTypeUse> runtimeTypeUses,
-      this.isFunctionApplyUsed,
-      this.isMirrorsUsed,
-      this.isNoSuchMethodUsed,
-      this.isHtmlLoaded})
+      {required Set<FunctionEntity>? globalFunctionDependencies,
+      required Set<ClassEntity>? globalClassDependencies,
+      required Set<FunctionEntity> helperFunctionsUsed,
+      required Set<ClassEntity> helperClassesUsed,
+      required this.needToInitializeIsolateAffinityTag,
+      required this.needToInitializeDispatchProperty,
+      required this.requiresPreamble,
+      required this.requiresStartupMetrics,
+      required Set<RuntimeTypeUse> runtimeTypeUses,
+      required this.isFunctionApplyUsed,
+      required this.isMirrorsUsed,
+      required this.isNoSuchMethodUsed,
+      required this.isHtmlLoaded})
       : this._globalFunctionDependencies = globalFunctionDependencies,
         this._globalClassDependencies = globalClassDependencies,
         this._helperFunctionsUsed = helperFunctionsUsed,
@@ -370,7 +369,7 @@
     Set<RuntimeTypeUse> runtimeTypeUses = source.readList(() {
       RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
       DartType receiverType = source.readDartType();
-      DartType /*?*/ argumentType = source.readDartTypeOrNull();
+      DartType? argumentType = source.readDartTypeOrNull();
       return RuntimeTypeUse(kind, receiverType, argumentType);
     }).toSet();
     bool needToInitializeIsolateAffinityTag = source.readBool();
@@ -401,8 +400,8 @@
   @override
   void writeToDataSink(DataSinkWriter sink) {
     sink.begin(tag);
-    sink.writeMembers(_globalFunctionDependencies);
-    sink.writeClasses(_globalClassDependencies);
+    sink.writeMembers(_globalFunctionDependencies, allowNull: true);
+    sink.writeClasses(_globalClassDependencies, allowNull: true);
     sink.writeMembers(_helperFunctionsUsed);
     sink.writeClasses(_helperClassesUsed);
     sink.writeList(runtimeTypeUses, (RuntimeTypeUse runtimeTypeUse) {
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index f2ba357..976fbf3 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -15,8 +15,7 @@
 import '../ir/scope_visitor.dart';
 import '../js_model/elements.dart' show JField;
 import '../js_model/js_to_frontend_map.dart' show JsToFrontendMap;
-import '../kernel/element_map.dart';
-import '../kernel/kernel_strategy.dart';
+import '../kernel/element_map.dart' show KernelToElementMap;
 import '../kernel/kelements.dart' show KClass, KField, KConstructor;
 import '../kernel/kernel_world.dart';
 import '../options.dart';
@@ -45,8 +44,7 @@
   final Map<KClass, ClassData> _classData = {};
   final Map<KField, StaticFieldData> _staticFieldData = {};
 
-  KFieldAnalysis(KernelFrontendStrategy kernelStrategy)
-      : _elementMap = kernelStrategy.elementMap;
+  KFieldAnalysis(this._elementMap);
 
   // Register class during resolution. Use simple syntactic analysis to find
   // null-initialized fields.
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index a08b941..23de9f0 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -1361,51 +1361,6 @@
       ClassTypeVariableAccess.none;
 }
 
-class ClosureMemberDefinition implements MemberDefinition {
-  /// Tag used for identifying serialized [ClosureMemberDefinition] objects in a
-  /// debugging data stream.
-  static const String tag = 'closure-member-definition';
-
-  @override
-  final SourceSpan location;
-  @override
-  final MemberKind kind;
-  @override
-  ir.TreeNode get node => _node.loaded();
-  final Deferrable<ir.TreeNode> _node;
-
-  ClosureMemberDefinition(this.location, this.kind, ir.TreeNode node)
-      : _node = Deferrable.eager(node),
-        assert(
-            kind == MemberKind.closureCall || kind == MemberKind.closureField);
-
-  ClosureMemberDefinition._deserialized(this.location, this.kind, this._node)
-      : assert(
-            kind == MemberKind.closureCall || kind == MemberKind.closureField);
-
-  factory ClosureMemberDefinition.readFromDataSource(
-      DataSourceReader source, MemberKind kind) {
-    source.begin(tag);
-    SourceSpan location = source.readSourceSpan();
-    Deferrable<ir.TreeNode> node =
-        source.readDeferrable(() => source.readTreeNode());
-    source.end(tag);
-    return ClosureMemberDefinition._deserialized(location, kind, node);
-  }
-
-  @override
-  void writeToDataSink(DataSinkWriter sink) {
-    sink.writeEnum(kind);
-    sink.begin(tag);
-    sink.writeSourceSpan(location);
-    sink.writeDeferrable(() => sink.writeTreeNode(node));
-    sink.end(tag);
-  }
-
-  @override
-  String toString() => 'ClosureMemberDefinition(kind:$kind,location:$location)';
-}
-
 class RecordContainerDefinition implements ClassDefinition {
   /// Tag used for identifying serialized [RecordContainerDefinition] objects in
   /// a debugging data stream.
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 5de2c8d..7ec2a72 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -422,6 +422,11 @@
   SpecialMemberDefinition(ir.TreeNode node, this.kind)
       : _node = Deferrable.eager(node);
 
+  SpecialMemberDefinition.from(MemberDefinition baseMember, this.kind)
+      : _node = baseMember is ClosureMemberDefinition
+            ? baseMember._node
+            : Deferrable.eager(baseMember.node);
+
   SpecialMemberDefinition._deserialized(this._node, this.kind);
 
   factory SpecialMemberDefinition.readFromDataSource(
@@ -449,6 +454,51 @@
       'node:$node,location:$location)';
 }
 
+class ClosureMemberDefinition implements MemberDefinition {
+  /// Tag used for identifying serialized [ClosureMemberDefinition] objects in a
+  /// debugging data stream.
+  static const String tag = 'closure-member-definition';
+
+  @override
+  final SourceSpan location;
+  @override
+  final MemberKind kind;
+  @override
+  ir.TreeNode get node => _node.loaded();
+  final Deferrable<ir.TreeNode> _node;
+
+  ClosureMemberDefinition(this.location, this.kind, ir.TreeNode node)
+      : _node = Deferrable.eager(node),
+        assert(
+            kind == MemberKind.closureCall || kind == MemberKind.closureField);
+
+  ClosureMemberDefinition._deserialized(this.location, this.kind, this._node)
+      : assert(
+            kind == MemberKind.closureCall || kind == MemberKind.closureField);
+
+  factory ClosureMemberDefinition.readFromDataSource(
+      DataSourceReader source, MemberKind kind) {
+    source.begin(tag);
+    SourceSpan location = source.readSourceSpan();
+    Deferrable<ir.TreeNode> node =
+        source.readDeferrable(() => source.readTreeNode());
+    source.end(tag);
+    return ClosureMemberDefinition._deserialized(location, kind, node);
+  }
+
+  @override
+  void writeToDataSink(DataSinkWriter sink) {
+    sink.writeEnum(kind);
+    sink.begin(tag);
+    sink.writeSourceSpan(location);
+    sink.writeDeferrable(() => sink.writeTreeNode(node));
+    sink.end(tag);
+  }
+
+  @override
+  String toString() => 'ClosureMemberDefinition(kind:$kind,location:$location)';
+}
+
 /// Definition information for a [ClassEntity].
 abstract class ClassDefinition {
   /// The kind of the defined class. This determines the semantics of [node].
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 d23fd743..aa4e6c3 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -1380,7 +1380,7 @@
     return lookup;
   }
 
-  String /*?*/ _getStringArgument(ir.StaticInvocation node, int index) {
+  String _getStringArgument(ir.StaticInvocation node, int index) {
     return node.arguments.positional[index].accept(Stringifier());
   }
 
@@ -2161,14 +2161,15 @@
     JGeneratorBody generatorBody = _generatorBodies[function];
     if (generatorBody == null) {
       FunctionData functionData = members.getData(function);
-      ir.TreeNode node = functionData.definition.node;
       DartType elementType =
           elementEnvironment.getFunctionAsyncOrSyncStarElementType(function);
       generatorBody = createGeneratorBody(function, elementType);
       members.register<IndexedFunction, FunctionData>(
           generatorBody,
-          GeneratorBodyFunctionData(functionData,
-              SpecialMemberDefinition(node, MemberKind.generatorBody)));
+          GeneratorBodyFunctionData(
+              functionData,
+              SpecialMemberDefinition.from(
+                  functionData.definition, MemberKind.generatorBody)));
 
       if (function.enclosingClass != null) {
         // TODO(sra): Integrate this with ClassEnvImpl.addConstructorBody ?
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index 7cdd82c..7412239 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -15,7 +15,7 @@
 import '../elements/jumps.dart';
 import '../elements/types.dart';
 import '../serialization/deferrable.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 
 import 'element_map.dart';
 import 'elements.dart' show JGeneratorBody;
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index cd1467f..80486a8 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -46,11 +46,12 @@
 import '../util/enumset.dart';
 import 'element_map.dart';
 import 'element_map_impl.dart';
+import 'kernel_strategy_migrated.dart'; // TODO(48820): Remove when migrated.
 import 'native_basic_data.dart';
 
 /// Front end strategy that loads '.dill' files and builds a resolved element
 /// model from kernel IR nodes.
-class KernelFrontendStrategy {
+class KernelFrontendStrategy implements KernelFrontendStrategyForBackendUsage {
   final CompilerOptions _options;
   final CompilerTask _compilerTask;
   /*late*/ KernelToElementMap _elementMap;
@@ -146,7 +147,7 @@
         commonElements,
         nativeBasicData,
         _backendUsageBuilder);
-    _fieldAnalysis = KFieldAnalysis(this);
+    _fieldAnalysis = KFieldAnalysis(elementMap);
     ClassHierarchyBuilder classHierarchyBuilder =
         ClassHierarchyBuilder(commonElements, elementMap);
     AnnotationsDataBuilder annotationsDataBuilder = AnnotationsDataBuilder();
@@ -249,6 +250,7 @@
 
   /// Returns the [CommonElements] for the element model used in this
   /// strategy.
+  @override
   KCommonElements get commonElements => _elementMap.commonElements;
 
   KernelToElementMap get elementMap => _elementMap;
@@ -273,6 +275,7 @@
       _runtimeTypesNeedBuilder;
 
   /// Creates a [SourceSpan] from [spannable] in context of [currentElement].
+  @override
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement) {
     return _elementMap.getSourceSpan(spannable, currentElement);
   }
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy_migrated.dart b/pkg/compiler/lib/src/kernel/kernel_strategy_migrated.dart
new file mode 100644
index 0000000..25dfcf4
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy_migrated.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Facades for kernel_strategy.dart.
+// TODO(48820): Remove when frontend_strategy.dart is migrated.
+library dart2js.kernel.frontend_strategy.facades;
+
+import '../common.dart' show SourceSpan, Spannable;
+import '../common/elements.dart' show KCommonElements;
+import '../elements/entities.dart' show Entity;
+
+/// Facade interface for KernelFrontendStrategy.
+abstract class KernelFrontendStrategyForBackendUsage {
+  KCommonElements get commonElements;
+  SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
+}
diff --git a/pkg/compiler/lib/src/serialization/deferrable.dart b/pkg/compiler/lib/src/serialization/deferrable.dart
index 9b84e93..a2074aa 100644
--- a/pkg/compiler/lib/src/serialization/deferrable.dart
+++ b/pkg/compiler/lib/src/serialization/deferrable.dart
@@ -55,7 +55,6 @@
 /// }
 abstract class Deferrable<E> {
   E loaded();
-  static int count = 0;
 
   factory Deferrable.deferred(DataSourceReader reader, E f(), int offset,
           {bool cacheData = true}) =>
diff --git a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
index dfc601b..9f36a86 100644
--- a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:kernel/ast.dart' as ir show DartType, Member, TreeNode;
+import 'package:kernel/ast.dart' as ir
+    show DartType, LibraryDependency, Member, Name, TreeNode;
 
 import '../constants/values.dart' show ConstantValue;
 import '../elements/entities.dart';
@@ -49,6 +50,19 @@
   void writeEnum(dynamic value);
   void writeUri(Uri value);
 
+  void writeMemberNode(ir.Member nvalue);
+  void writeMemberNodes(Iterable<ir.Member>? values, {bool allowNull = false});
+  void writeMemberNodeMap<V>(Map<ir.Member, V>? map, void f(V value),
+      {bool allowNull = false});
+
+  void writeName(ir.Name value);
+  void writeLibraryDependencyNode(ir.LibraryDependency value);
+  void writeLibraryDependencyNodeOrNull(ir.LibraryDependency? value);
+
+  void writeTreeNode(ir.TreeNode value);
+  void writeTreeNodeOrNull(ir.TreeNode value);
+  void writeTreeNodes(Iterable<ir.TreeNode>? values, {bool allowNull = false});
+
   // TODO(48820): 'covariant ClassEntity' is used below because the
   // implementation takes IndexedClass. What this means is that in pre-NNBD
   // code, the call site to the implementation DataSinkWriter has an implicit
@@ -63,7 +77,7 @@
 
   void writeClass(covariant ClassEntity value); // IndexedClass
   void writeClassOrNull(covariant ClassEntity? value); // IndexedClass
-  void writeClasses(Iterable<ClassEntity> values, {bool allowNull = false});
+  void writeClasses(Iterable<ClassEntity>? values, {bool allowNull = false});
   void writeClassMap<V>(Map<ClassEntity, V>? map, void f(V value),
       {bool allowNull = false});
 
@@ -85,6 +99,8 @@
 
   void writeDartTypeNode(ir.DartType value);
   void writeDartTypeNodeOrNull(ir.DartType? value);
+  void writeDartTypeNodes(Iterable<ir.DartType>? values,
+      {bool allowNull = false});
 
   void writeDartType(DartType value);
   void writeDartTypeOrNull(DartType? value);
@@ -107,6 +123,9 @@
 
   void writeValueOrNull<E>(E? value, void f(E value));
 
+  void writeDoubleValue(double value);
+  void writeIntegerValue(int value);
+
   void writeImport(ImportEntity import);
   void writeImportOrNull(ImportEntity? import);
   void writeImports(Iterable<ImportEntity>? values, {bool allowNull = false});
@@ -137,6 +156,21 @@
   E readEnum<E>(List<E> values);
   Uri readUri();
 
+  ir.Member readMemberNode();
+  List<E> readMemberNodes<E extends ir.Member>();
+  List<E>? readMemberNodesOrNull<E extends ir.Member>();
+  Map<K, V> readMemberNodeMap<K extends ir.Member, V>(V f());
+  Map<K, V>? readMemberNodeMapOrNull<K extends ir.Member, V>(V f());
+
+  ir.Name readName();
+  ir.LibraryDependency readLibraryDependencyNode();
+  ir.LibraryDependency readLibraryDependencyNodeOrNull();
+
+  ir.TreeNode readTreeNode();
+  ir.TreeNode? readTreeNodeOrNull();
+  List<E> readTreeNodes<E extends ir.TreeNode>();
+  List<E>? readTreeNodesOrNull<E extends ir.TreeNode>();
+
   ClassEntity readClass(); // IndexedClass
   ClassEntity? readClassOrNull(); // IndexedClass
   List<E> readClasses<E extends ClassEntity>();
@@ -161,6 +195,8 @@
 
   ir.DartType readDartTypeNode();
   ir.DartType? readDartTypeNodeOrNull();
+  List<ir.DartType> readDartTypeNodes();
+  List<ir.DartType>? readDartTypeNodesOrNull();
 
   DartType readDartType();
   DartType? readDartTypeOrNull();
@@ -184,6 +220,9 @@
 
   E? readValueOrNull<E>(E f());
 
+  double readDoubleValue();
+  int readIntegerValue();
+
   ImportEntity readImport();
   ImportEntity? readImportOrNull();
   List<ImportEntity> readImports();
diff --git a/pkg/compiler/lib/src/serialization/sink.dart b/pkg/compiler/lib/src/serialization/sink.dart
index f1ae16d..dd92d56 100644
--- a/pkg/compiler/lib/src/serialization/sink.dart
+++ b/pkg/compiler/lib/src/serialization/sink.dart
@@ -340,6 +340,7 @@
   }
 
   /// Writes a reference to the kernel member node [value] to this data sink.
+  @override
   void writeMemberNode(ir.Member value) {
     _writeDataKind(DataKind.memberNode);
     _writeMemberNode(value);
@@ -367,6 +368,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readMemberNodes].
+  @override
   void writeMemberNodes(Iterable<ir.Member> values, {bool allowNull = false}) {
     if (values == null) {
       assert(allowNull);
@@ -385,6 +387,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readMemberNodeMap].
+  @override
   void writeMemberNodeMap<V>(Map<ir.Member, V> map, void f(V value),
       {bool allowNull = false}) {
     if (map == null) {
@@ -400,12 +403,14 @@
   }
 
   /// Writes a kernel name node to this data sink.
+  @override
   void writeName(ir.Name value) {
     writeString(value.text);
     writeValueOrNull(value.library, writeLibraryNode);
   }
 
   /// Writes a kernel library dependency node [value] to this data sink.
+  @override
   void writeLibraryDependencyNode(ir.LibraryDependency value) {
     ir.Library library = value.parent;
     writeLibraryNode(library);
@@ -414,11 +419,13 @@
 
   /// Writes a potentially `null` kernel library dependency node [value] to
   /// this data sink.
+  @override
   void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value) {
     writeValueOrNull(value, writeLibraryDependencyNode);
   }
 
   /// Writes a reference to the kernel tree node [value] to this data sink.
+  @override
   void writeTreeNode(ir.TreeNode value) {
     _writeDataKind(DataKind.treeNode);
     _writeTreeNode(value, null);
@@ -465,6 +472,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readTreeNodeOrNull].
+  @override
   void writeTreeNodeOrNull(ir.TreeNode value) {
     writeBool(value != null);
     if (value != null) {
@@ -477,6 +485,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readTreeNodes].
+  @override
   void writeTreeNodes(Iterable<ir.TreeNode> values, {bool allowNull = false}) {
     if (values == null) {
       assert(allowNull);
@@ -692,6 +701,7 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readDartTypeNodes].
+  @override
   void writeDartTypeNodes(Iterable<ir.DartType> values,
       {bool allowNull = false}) {
     if (values == null) {
@@ -1112,6 +1122,7 @@
   }
 
   /// Writes a double value to this data sink.
+  @override
   void writeDoubleValue(double value) {
     _writeDataKind(DataKind.double);
     _writeDoubleValue(value);
@@ -1130,6 +1141,7 @@
   ///
   /// This is should only when the value is not known to be a non-negative
   /// 30 bit integer. Otherwise [writeInt] should be used.
+  @override
   void writeIntegerValue(int value) {
     _writeDataKind(DataKind.int);
     _writeBigInt(BigInt.from(value));
diff --git a/pkg/compiler/lib/src/serialization/source.dart b/pkg/compiler/lib/src/serialization/source.dart
index c512786..e2d1e6b 100644
--- a/pkg/compiler/lib/src/serialization/source.dart
+++ b/pkg/compiler/lib/src/serialization/source.dart
@@ -481,6 +481,7 @@
   }
 
   /// Reads a reference to a kernel member node from this data source.
+  @override
   ir.Member readMemberNode() {
     _checkDataKind(DataKind.memberNode);
     return _readMemberData().node;
@@ -506,31 +507,47 @@
   }
 
   /// Reads a list of references to kernel member nodes from this data source.
-  /// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeMemberNodes].
-  List<E> readMemberNodes<E extends ir.Member>({bool emptyAsNull = false}) {
+  @override
+  List<E> readMemberNodes<E extends ir.Member>() {
+    return readMemberNodesOrNull<E>() ?? List.empty();
+  }
+
+  /// Reads a list of references to kernel member nodes from this data source.
+  /// `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeMemberNodes].
+  @override
+  List<E> readMemberNodesOrNull<E extends ir.Member>() {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
-    List<E> list = List<E>.filled(count, null);
-    for (int i = 0; i < count; i++) {
-      ir.Member value = readMemberNode();
-      list[i] = value;
-    }
-    return list;
+    if (count == 0) return null;
+    return List<E>.generate(count, (_) => readMemberNode() as E,
+        growable: false);
   }
 
   /// Reads a map from kernel member nodes to [V] values from this data source,
-  /// calling [f] to read each value from the data source. If [emptyAsNull] is
-  /// `true`, `null` is returned instead of an empty map.
+  /// calling [f] to read each value from the data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeMemberNodeMap].
-  Map<K, V> readMemberNodeMap<K extends ir.Member, V>(V f(),
-      {bool emptyAsNull = false}) {
+  @override
+  Map<K, V> readMemberNodeMap<K extends ir.Member, V>(V f()) {
+    return readMemberNodeMapOrNull<K, V>(f) ?? {};
+  }
+
+  /// Reads a map from kernel member nodes to [V] values from this data source,
+  /// calling [f] to read each value from the data source.  `null` is returned
+  /// instead of an empty map.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeMemberNodeMap].
+  @override
+  Map<K, V> /*?*/ readMemberNodeMapOrNull<K extends ir.Member, V>(V f()) {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     Map<K, V> map = {};
     for (int i = 0; i < count; i++) {
       ir.Member node = readMemberNode();
@@ -541,6 +558,7 @@
   }
 
   /// Reads a kernel name node from this data source.
+  @override
   ir.Name readName() {
     String text = readString();
     ir.Library library = readValueOrNull(readLibraryNode);
@@ -548,6 +566,7 @@
   }
 
   /// Reads a kernel library dependency node from this data source.
+  @override
   ir.LibraryDependency readLibraryDependencyNode() {
     ir.Library library = readLibraryNode();
     int index = readInt();
@@ -556,11 +575,13 @@
 
   /// Reads a potentially `null` kernel library dependency node from this data
   /// source.
+  @override
   ir.LibraryDependency readLibraryDependencyNodeOrNull() {
     return readValueOrNull(readLibraryDependencyNode);
   }
 
   /// Reads a reference to a kernel tree node from this data source.
+  @override
   ir.TreeNode readTreeNode() {
     _checkDataKind(DataKind.treeNode);
     return _readTreeNode(null);
@@ -601,6 +622,7 @@
 
   /// Reads a reference to a potentially `null` kernel tree node from this data
   /// source.
+  @override
   ir.TreeNode readTreeNodeOrNull() {
     bool hasValue = readBool();
     if (hasValue) {
@@ -610,19 +632,24 @@
   }
 
   /// Reads a list of references to kernel tree nodes from this data source.
-  /// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeTreeNodes].
-  List<E> readTreeNodes<E extends ir.TreeNode>({bool emptyAsNull = false}) {
+  @override
+  List<E> readTreeNodes<E extends ir.TreeNode>() {
+    return readTreeNodesOrNull<E>() ?? List.empty();
+  }
+
+  /// Reads a list of references to kernel tree nodes from this data source.
+  /// `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeTreeNodes].
+  @override
+  List<E> readTreeNodesOrNull<E extends ir.TreeNode>() {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
-    List<E> list = List<E>.filled(count, null);
-    for (int i = 0; i < count; i++) {
-      ir.TreeNode node = readTreeNode();
-      list[i] = node;
-    }
-    return list;
+    if (count == 0) return null;
+    return List<E>.generate(count, (i) => readTreeNode() as E, growable: false);
   }
 
   /// Reads a map from kernel tree nodes to [V] values from this data source,
@@ -906,14 +933,24 @@
     throw UnsupportedError("Unexpected DartTypeKind $kind");
   }
 
-  /// Reads a list of kernel type nodes from this data source. If [emptyAsNull]
-  /// is `true`, `null` is returned instead of an empty list.
+  /// Reads a list of kernel type nodes from this data source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeDartTypeNodes].
-  List<ir.DartType> readDartTypeNodes({bool emptyAsNull = false}) {
+  @override
+  List<ir.DartType> readDartTypeNodes() {
+    return readDartTypeNodesOrNull() ?? const [];
+  }
+
+  /// Reads a list of kernel type nodes from this data source. `null` is
+  /// returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeDartTypeNodes].
+  @override
+  List<ir.DartType> readDartTypeNodesOrNull() {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     List<ir.DartType> list = List<ir.DartType>.filled(count, null);
     for (int i = 0; i < count; i++) {
       list[i] = readDartTypeNode();
@@ -1366,6 +1403,7 @@
   }
 
   /// Reads a double value from this data source.
+  @override
   double readDoubleValue() {
     _checkDataKind(DataKind.double);
     return _readDoubleValue();
@@ -1384,6 +1422,7 @@
   ///
   /// This is should only when the value is not known to be a non-negative
   /// 30 bit integer. Otherwise [readInt] should be used.
+  @override
   int readIntegerValue() {
     _checkDataKind(DataKind.int);
     return _readBigInt().toInt();
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 41fe730..df9763b 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -502,8 +502,9 @@
 ///
 /// To handle bazel's special layout:
 ///
-///  * We specify a .packages configuration file that expands packages to their
-///    corresponding bazel location. This way there is no need to create a pub
+///  * We specify a .dart_tool/package_config.json configuration file that
+///    expands packages to their corresponding bazel location.
+///    This way there is no need to create a pub
 ///    cache prior to invoking dart2js.
 ///
 ///  * We provide an implicit mapping that can make all urls relative to the
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f133cca..8dac144 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -186,9 +186,12 @@
   final DartType receiverType;
 
   /// The static type of the argument if [kind] is `RuntimeTypeUseKind.equals`.
-  final DartType argumentType;
+  final DartType? argumentType;
 
-  RuntimeTypeUse(this.kind, this.receiverType, this.argumentType);
+  RuntimeTypeUse(this.kind, this.receiverType, this.argumentType) {
+    // TODO(48820): Remove assertions when sound.
+    (receiverType as dynamic)!;
+  }
 
   @override
   int get hashCode =>
diff --git a/pkg/compiler/test/end_to_end/modular_loader_test.dart b/pkg/compiler/test/end_to_end/modular_loader_test.dart
index 11132f9..1a136a0 100644
--- a/pkg/compiler/test/end_to_end/modular_loader_test.dart
+++ b/pkg/compiler/test/end_to_end/modular_loader_test.dart
@@ -81,13 +81,15 @@
   List<Uri> additionalDills = [
     computePlatformBinariesLocation().resolve("dart2js_platform.dill"),
   ]..addAll(deps.map(toTestUri));
-  fs.entityForUri(toTestUri('.packages')).writeAsStringSync('');
+  fs
+      .entityForUri(toTestUri('.dart_tool/package_config.json'))
+      .writeAsStringSync('{"configVersion": 2, "packages": []}');
   var options = CompilerOptions()
     ..target = Dart2jsTarget("dart2js", TargetFlags(enableNullSafety: true))
     ..fileSystem = TestFileSystem(fs)
     ..nnbdMode = NnbdMode.Strong
     ..additionalDills = additionalDills
-    ..packagesFileUri = toTestUri('.packages')
+    ..packagesFileUri = toTestUri('.dart_tool/package_config.json')
     ..explicitExperimentalFlags = {ExperimentalFlag.nonNullable: true};
   var inputUris = inputs.map(toTestUri).toList();
   var inputUriSet = inputUris.toSet();
diff --git a/pkg/compiler/test/equivalence/id_equivalence_helper.dart b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
index f0e6458..1f740d3 100644
--- a/pkg/compiler/test/equivalence/id_equivalence_helper.dart
+++ b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
@@ -135,7 +135,8 @@
   OutputCollector outputCollector = new OutputCollector();
   DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
   Uri packageConfig;
-  Uri wantedPackageConfig = createUriForFileName(".packages");
+  Uri wantedPackageConfig =
+      createUriForFileName(".dart_tool/package_config.json");
   for (String key in memorySourceFiles.keys) {
     if (key == wantedPackageConfig.path) {
       packageConfig = wantedPackageConfig;
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index d1f139e..8885b43 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 2.2.5
+- Updated `devtools_shared` version to 2.14.1.
+
 # 2.2.4
 - Fix an issue where DAP adapters could try to remove the same breakpoint multiple times.
 
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index bf4a249..b8b0c65 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dds
-version: 2.2.4
+version: 2.2.5
 description: >-
   A library used to spawn the Dart Developer Service, used to communicate with
   a Dart VM Service instance.
@@ -14,7 +14,7 @@
   browser_launcher: ^1.0.0
   collection: ^1.15.0
   dds_service_extensions: ^1.3.0
-  devtools_shared: ^2.12.1
+  devtools_shared: ^2.14.1
   http_multi_server: ^3.0.0
   json_rpc_2: ^3.0.0
   meta: ^1.1.8
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index becb100..e0a61f3 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -235,7 +235,7 @@
     }
   }
 
-  /// The .packages file path provided by the user.
+  /// The .dart_tool/package_config.json file path provided by the user.
   //
   // TODO(jmesserly): the default location is based on the current working
   // directory, to match the behavior of dartanalyzer/dartdevc. However the
@@ -244,8 +244,9 @@
   // Ultimately this is just the default behavior; in practice users call DDC
   // through a build tool, which generally passes in `--packages=`.
   //
-  // TODO(jmesserly): conceptually CFE should not need a .packages file to
-  // resolve package URIs that are in the input summaries, but it seems to.
+  // TODO(jmesserly): conceptually CFE should not need a
+  // .dart_tool/package_config.json file to resolve package URIs that are in the
+  // input summaries, but it seems to.
   // This needs further investigation.
   var packageFile =
       argResults['packages'] as String? ?? _findPackagesFilePath();
@@ -856,7 +857,8 @@
 String? _findPackagesFilePath() {
   // TODO(jmesserly): this was copied from package:package_config/discovery.dart
   // Unfortunately the relevant function is not public. CFE APIs require a URI
-  // to the .packages file, rather than letting us provide the package map data.
+  // to the .dart_tool/package_config.json file, rather than letting us provide
+  // the package map data.
   var dir = Directory.current;
   if (!dir.isAbsolute) dir = dir.absolute;
   if (!dir.existsSync()) return null;
diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart
index dee5a05..6113349 100644
--- a/pkg/dev_compiler/test/modular_suite.dart
+++ b/pkg/dev_compiler/test/modular_suite.dart
@@ -92,7 +92,10 @@
       assert(transitiveDependencies.isEmpty);
     } else {
       sources = module.sources.map(sourceToImportUri).toList();
-      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+      extraArgs = [
+        '--packages-file',
+        '$rootScheme:/.dart_tool/package_config.json'
+      ];
     }
 
     var sdkModule =
@@ -185,14 +188,14 @@
         '--dart-sdk-summary',
         '${toUri(sdkModule, dillId)}',
         '--packages',
-        '.packages',
+        '.dart_tool/package_config.json',
       ];
     }
 
     var output = toUri(module, jsId);
 
     var args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
+      '--packages=${sdkRoot.toFilePath()}/.dart_tool/package_config.json',
       _dartdevcScript,
       '--kernel',
       '--modules=es6',
diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart
index c5c0567..5b3b5f7 100644
--- a/pkg/dev_compiler/test/modular_suite_nnbd.dart
+++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart
@@ -91,7 +91,10 @@
       assert(transitiveDependencies.isEmpty);
     } else {
       sources = module.sources.map(sourceToImportUri).toList();
-      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+      extraArgs = [
+        '--packages-file',
+        '$rootScheme:/.dart_tool/package_config.json'
+      ];
     }
 
     var sdkModule =
@@ -184,14 +187,14 @@
         '--dart-sdk-summary',
         '${toUri(sdkModule, dillId)}',
         '--packages',
-        '.packages',
+        '.dart_tool/package_config.json',
       ];
     }
 
     var output = toUri(module, jsId);
 
     var args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
+      '--packages=${sdkRoot.toFilePath()}/.dart_tool/package_config.json',
       _dartdevcScript,
       '--kernel',
       '--modules=es6',
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index e8b30e9..b8ad050 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert' show jsonEncode;
 import 'dart:io';
 
 import 'package:dev_compiler/src/kernel/command.dart' show getSdkPath;
@@ -665,10 +666,18 @@
     var librariesJson = p.join(getSdkPath(), 'lib', 'libraries.json');
     librariesFile.writeAsBytesSync(File(librariesJson).readAsBytesSync());
   }
-  var packagesUri = Uri.file('/memory/.packages');
+  var packagesUri = Uri.file('/memory/.dart_tool/package_config.json');
   var packagesFile = _fileSystem.entityForUri(packagesUri);
   if (!await packagesFile.exists()) {
-    packagesFile.writeAsStringSync('meta:/memory/meta/lib');
+    packagesFile.writeAsStringSync(jsonEncode({
+      'configVersion': 2,
+      'packages': [
+        {
+          'name': 'meta',
+          'rootUri': '/memory/meta/lib',
+        },
+      ],
+    }));
     _fileSystem
         .entityForUri(Uri.file('/memory/meta/lib/meta.dart'))
         .writeAsStringSync('''
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 3543755..c94d998 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -64,18 +64,16 @@
 
   DiagnosticMessageHandler? onDiagnostic;
 
-  /// URI of the ".dart_tool/package_config.json" or ".packages" file
+  /// URI of the ".dart_tool/package_config.json" file
   /// (typically a "file:" URI).
   ///
-  /// If a ".packages" file is given and a ".dart_tool/package_config.json" file
-  /// exists next to it, the ".dart_tool/package_config.json" file is used
-  /// instead.
-  ///
   /// If `null`, the file will be found via the standard package_config search
   /// algorithm.
   ///
   /// If the URI's path component is empty (e.g. `new Uri()`), no packages file
   /// will be used.
+  ///
+  /// If an old ".packages" file is given an error is issued.
   Uri? packagesFileUri;
 
   /// URIs of additional dill files.
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 2a6e8f6..a6c12a0 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -101,8 +101,9 @@
   /// not been computed yet.
   PackageConfig? _packages;
 
-  /// The uri for .packages derived from the options, or `null` if the package
-  /// map has not been computed yet or there is no .packages in effect.
+  /// The uri for package_config.json derived from the options, or `null` if the
+  /// package map has not been computed yet or there is no package_config.json
+  /// in effect.
   Uri? _packagesUri;
   Uri? get packagesUri => _packagesUri;
 
@@ -541,7 +542,7 @@
 
     if (inputs.length > 1) {
       // TODO(sigmund): consider not reporting an error if we would infer
-      // the same .packages file from all of the inputs.
+      // the same `package_config.json` file from all of the inputs.
       reportWithoutLocation(
           messageCantInferPackagesFromManyInputs, Severity.error);
       return _packages = PackageConfig.empty;
@@ -560,11 +561,10 @@
     return _packages = await _findPackages(input);
   }
 
-  Future<Uint8List?> _readFile(Uri uri, bool reportError) async {
+  Future<Uint8List?> _readFile(Uri uri) async {
     try {
       // TODO(ahe): We need to compute line endings for this file.
       FileSystemEntity entityForUri = fileSystem.entityForUri(uri);
-      if (!reportError && !await entityForUri.exists()) return null;
       List<int> fileContents = await entityForUri.readAsBytes();
       if (fileContents is Uint8List) {
         return fileContents;
@@ -572,10 +572,8 @@
         return new Uint8List.fromList(fileContents);
       }
     } on FileSystemException catch (e) {
-      if (reportError) {
-        reportWithoutLocation(
-            templateCantReadFile.withArguments(uri, e.message), Severity.error);
-      }
+      reportWithoutLocation(
+          templateCantReadFile.withArguments(uri, e.message), Severity.error);
     } catch (e) {
       Message message = templateExceptionReadingFile.withArguments(uri, '$e');
       reportWithoutLocation(message, Severity.error);
@@ -587,22 +585,16 @@
     return null;
   }
 
-  /// Create a [PackageConfig] given the Uri to a `.packages` or
-  /// `package_config.json` file.
+  /// Create a [PackageConfig] given the Uri to a `package_config.json` file.
   ///
-  /// If the file doesn't exist, it returns null (and an error is reported
-  /// based in [forceCreation]).
-  /// If the file does exist but is invalid an error is always reported and an
-  /// empty package config is returned.
-  Future<PackageConfig?> _createPackagesFromFile(
-      Uri requestedUri, bool forceCreation, bool requireJson) async {
-    Uint8List? contents = await _readFile(requestedUri, forceCreation);
+  /// If the file doesn't exist, it returns null (and an error is reported).
+  /// If the file does exist but is invalid (e.g. if it's an old `.packages`
+  /// file) an error is always reported and an empty package config is returned.
+  Future<PackageConfig?> _createPackagesFromFile(Uri requestedUri) async {
+    Uint8List? contents = await _readFile(requestedUri);
     if (contents == null) {
-      if (forceCreation) {
-        _packagesUri = null;
-        return PackageConfig.empty;
-      }
-      return null;
+      _packagesUri = null;
+      return PackageConfig.empty;
     }
 
     _packagesUri = requestedUri;
@@ -620,18 +612,7 @@
               Severity.error);
         }
       };
-      if (requireJson) {
-        return PackageConfig.parseBytes(contents, requestedUri,
-            onError: onError);
-      }
-      return await loadPackageConfigUri(requestedUri, preferNewest: false,
-          loader: (uri) {
-        if (uri != requestedUri) {
-          throw new StateError(
-              "Unexpected request from package config package");
-        }
-        return new Future.value(contents);
-      }, onError: onError);
+      return PackageConfig.parseBytes(contents, requestedUri, onError: onError);
     } on FormatException catch (e) {
       report(
           templatePackagesFileFormat
@@ -647,24 +628,11 @@
     return PackageConfig.empty;
   }
 
-  /// Create a [PackageConfig] given the Uri to a `.packages` or
-  /// `package_config.json` file.
+  /// Create a [PackageConfig] given the Uri to a `package_config.json` file.
   ///
-  /// Note that if a `.packages` file is provided and an appropriately placed
-  /// (relative to the .packages file) `package_config.json` file exists, the
-  /// `package_config.json` file will be used instead.
+  /// Note that if an old `.packages` file is provided an error will be issued.
   Future<PackageConfig> createPackagesFromFile(Uri file) async {
-    // If the input is a ".packages" file we assume the standard layout, and
-    // if a ".dart_tool/package_config.json" exists, we'll use that (and require
-    // it to be a json file).
-    PackageConfig? result;
-    if (file.path.endsWith("/.packages")) {
-      // .packages -> try the package_config first.
-      Uri tryFirst = file.resolve(".dart_tool/package_config.json");
-      result = await _createPackagesFromFile(tryFirst, false, true);
-      if (result != null) return result;
-    }
-    result = await _createPackagesFromFile(file, true, false);
+    PackageConfig? result = await _createPackagesFromFile(file);
     return result ?? PackageConfig.empty;
   }
 
@@ -673,8 +641,8 @@
   /// The [scriptUri] points to a Dart script with a valid scheme accepted by
   /// the [FileSystem].
   ///
-  /// This function first tries to locate a `.dart_tool/package_config.json`
-  /// (then a `.packages`) file in the `scriptUri` directory.
+  /// This function tries to locate a `.dart_tool/package_config.json` file in
+  /// the `scriptUri` directory.
   /// If that is not found, it starts checking parent directories, and stops if
   /// it finds it. Otherwise it gives up and returns [PackageConfig.empty].
   ///
@@ -695,8 +663,6 @@
       try {
         candidate = dir.resolve('.dart_tool/package_config.json');
         if (await fileSystem.entityForUri(candidate).exists()) return candidate;
-        candidate = dir.resolve('.packages');
-        if (await fileSystem.entityForUri(candidate).exists()) return candidate;
         return null;
       } catch (e) {
         Message message =
@@ -709,11 +675,11 @@
       }
     }
 
-    // Check for $cwd/.packages
+    // Check for $cwd/.dart_tool/package_config.json
     Uri? candidate = await checkInDir(dir);
     if (candidate != null) return createPackagesFromFile(candidate);
 
-    // Check for cwd(/..)+/.packages
+    // Check for cwd(/..)+/.dart_tool/package_config.json
     Uri parentDir = dir.resolve('..');
     while (parentDir.path != dir.path) {
       candidate = await checkInDir(parentDir);
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index 496be18..a88180b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -11,6 +11,7 @@
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/reference_from_index.dart' show IndexedClass;
+import 'package:kernel/transformations/flags.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
@@ -800,20 +801,35 @@
     SourceProcedureBuilder toStringBuilder =
         firstMemberNamed("toString") as SourceProcedureBuilder;
 
-    ClassBuilder enumClass =
-        _computeEnumSupertype()!.declaration as ClassBuilder;
-    MemberBuilder? nameFieldBuilder =
-        enumClass.lookupLocalMember("_name") as MemberBuilder?;
-    assert(nameFieldBuilder != null);
-    Field nameField = nameFieldBuilder!.member as Field;
+    Name toStringName = new Name("toString");
+    Member? superToString = cls.superclass != null
+        ? classHierarchy.getDispatchTarget(cls.superclass!, toStringName)
+        : null;
+    Procedure? toStringSuperTarget = superToString is Procedure &&
+            superToString.enclosingClass != classHierarchy.coreTypes.objectClass
+        ? superToString
+        : null;
 
-    toStringBuilder.body = new ReturnStatement(new StringConcatenation([
-      new StringLiteral("${cls.demangledName}."),
-      new InstanceGet.byReference(
-          InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
-          interfaceTargetReference: nameField.getterReference,
-          resultType: nameField.getterType),
-    ]));
+    if (toStringSuperTarget != null) {
+      toStringBuilder.member.transformerFlags |= TransformerFlag.superCalls;
+      toStringBuilder.body = new ReturnStatement(new SuperMethodInvocation(
+          toStringName, new Arguments([]), toStringSuperTarget));
+    } else {
+      ClassBuilder enumClass =
+          _computeEnumSupertype()!.declaration as ClassBuilder;
+      MemberBuilder? nameFieldBuilder =
+          enumClass.lookupLocalMember("_name") as MemberBuilder?;
+      assert(nameFieldBuilder != null);
+      Field nameField = nameFieldBuilder!.member as Field;
+
+      toStringBuilder.body = new ReturnStatement(new StringConcatenation([
+        new StringLiteral("${cls.demangledName}."),
+        new InstanceGet.byReference(
+            InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
+            interfaceTargetReference: nameField.getterReference,
+            resultType: nameField.getterType),
+      ]));
+    }
 
     super.buildOutlineExpressions(
         classHierarchy, delayedActionPerformers, delayedDefaultValueCloners);
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 626c3c3..f7c0b5c 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -547,9 +547,9 @@
 
   /// Set the language version to an explicit major and minor version.
   ///
-  /// The default language version specified by the .packages file is passed
-  /// to the constructor, but the library can have source code that specifies
-  /// another one which should be supported.
+  /// The default language version specified by the `package_config.json` file
+  /// is passed to the constructor, but the library can have source code that
+  /// specifies another one which should be supported.
   ///
   /// Only the first registered language version is used.
   ///
diff --git a/pkg/front_end/lib/src/testing/compiler_common.dart b/pkg/front_end/lib/src/testing/compiler_common.dart
index f8cebf7..4f8a481 100644
--- a/pkg/front_end/lib/src/testing/compiler_common.dart
+++ b/pkg/front_end/lib/src/testing/compiler_common.dart
@@ -81,7 +81,8 @@
 ///   contain either source files (value is [String]) or .dill files (value
 ///   is [List<int>]).
 ///
-///   * define an empty .packages file (if one isn't defined in sources)
+///   * define an empty `package_config.json` file (if one isn't defined in
+///     sources).
 ///
 ///   * specify the location of the sdk summaries.
 Future<Null> setup(CompilerOptions options, Map<String, dynamic> sources,
@@ -95,9 +96,11 @@
       entity.writeAsBytesSync(data);
     }
   });
-  MemoryFileSystemEntity dotPackagesFile =
-      fs.entityForUri(toTestUri('.packages'));
-  if (!await dotPackagesFile.exists()) dotPackagesFile.writeAsStringSync('');
+  MemoryFileSystemEntity packageConfigFile =
+      fs.entityForUri(toTestUri('.dart_tool/package_config.json'));
+  if (!await packageConfigFile.exists()) {
+    packageConfigFile.writeAsStringSync('{"configVersion": 2, "packages": []}');
+  }
   fs
       .entityForUri(invalidCoreLibsSpecUri)
       .writeAsStringSync(_invalidLibrariesSpec);
@@ -106,7 +109,7 @@
     ..fileSystem = new HybridFileSystem(fs)
     ..additionalDills = additionalDills.map(toTestUri).toList();
   if (options.packagesFileUri == null) {
-    options.packagesFileUri = toTestUri('.packages');
+    options.packagesFileUri = toTestUri('.dart_tool/package_config.json');
   }
 
   if (options.sdkSummary == null) {
diff --git a/pkg/front_end/test/hot_reload_e2e_test.dart b/pkg/front_end/test/hot_reload_e2e_test.dart
index aa8e855..0adcb12c 100644
--- a/pkg/front_end/test/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/hot_reload_e2e_test.dart
@@ -73,7 +73,8 @@
     writeFile(fs, 'a.dart', sourceA);
     writeFile(fs, 'b.dart', sourceB);
     writeFile(fs, 'c.dart', sourceC);
-    writeFile(fs, '.packages', '');
+    writeFile(fs, '.dart_tool/package_config.json',
+        '{"configVersion": 2, "packages": []}');
     compiler = createIncrementalCompiler(
         'org-dartlang-test:///a.dart', new HybridFileSystem(fs));
     await rebuild(compiler, outputUri); // this is a full compile.
diff --git a/pkg/front_end/test/id_testing/data/directory_testing/.packages b/pkg/front_end/test/id_testing/data/directory_testing/.packages
deleted file mode 100644
index 554a99c..0000000
--- a/pkg/front_end/test/id_testing/data/directory_testing/.packages
+++ /dev/null
@@ -1 +0,0 @@
-foo:lib/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/.packages b/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/.packages
deleted file mode 100644
index 00d3dbb..0000000
--- a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/.packages
+++ /dev/null
@@ -1 +0,0 @@
-collection:foo/lib/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/bin/bin_file.dart b/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/bin/bin_file.dart
deleted file mode 100644
index 1046332..0000000
--- a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/bin/bin_file.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: 
- languageVersion=2.7,
- packageUri=package:collection
-*/
-
-method1() {}
diff --git a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/lib/foo.dart b/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/lib/foo.dart
deleted file mode 100644
index e72d3b0..0000000
--- a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/lib/foo.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: languageVersion=2.7*/
-
-method2() {}
diff --git a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/test/test_file.dart b/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/test/test_file.dart
deleted file mode 100644
index 4c47d9b..0000000
--- a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/foo/test/test_file.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: 
- languageVersion=2.7,
- packageUri=package:collection
-*/
-
-method3() {}
diff --git a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/main.dart b/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/main.dart
deleted file mode 100644
index cb6feec..0000000
--- a/pkg/front_end/test/language_versioning/data/allowed_experiments_with_packages/main.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: languageVersion=2.8*/
-
-import 'foo/bin/bin_file.dart';
-import 'foo/test/test_file.dart';
-import 'package:collection/foo.dart';
-
-main() {}
diff --git a/pkg/front_end/test/language_versioning/data/language_version_in_packages/.packages b/pkg/front_end/test/language_versioning/data/language_version_in_packages/.packages
deleted file mode 100644
index 6bfeac3..0000000
--- a/pkg/front_end/test/language_versioning/data/language_version_in_packages/.packages
+++ /dev/null
@@ -1 +0,0 @@
-foo:lib//*error: errors=PackagesFileFormat*/#dart=2.6
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/language_version_in_packages/lib/foo.dart b/pkg/front_end/test/language_versioning/data/language_version_in_packages/lib/foo.dart
deleted file mode 100644
index 6d45456..0000000
--- a/pkg/front_end/test/language_versioning/data/language_version_in_packages/lib/foo.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-/*library: languageVersion=2.7*/
-
-String foo() {
-  return "42";
-}
diff --git a/pkg/front_end/test/language_versioning/data/language_version_in_packages/main.dart b/pkg/front_end/test/language_versioning/data/language_version_in_packages/main.dart
deleted file mode 100644
index 13b6127..0000000
--- a/pkg/front_end/test/language_versioning/data/language_version_in_packages/main.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Set version of this file (not technically in package) explicitly to test as
-// much as possibly separately.
-
-// @dart = 2.4
-
-import 'package:foo/foo.dart';
-
-/*library: 
- languageVersion=2.4,
- packageUri=package:foo
-*/
-
-main() {
-  var result = foo();
-  print(result);
-}
diff --git a/pkg/front_end/test/language_versioning/data/library_with_no_version.dart b/pkg/front_end/test/language_versioning/data/library_with_no_version.dart
index 3b64d66..66a962f 100644
--- a/pkg/front_end/test/language_versioning/data/library_with_no_version.dart
+++ b/pkg/front_end/test/language_versioning/data/library_with_no_version.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// If no language version is specified, and none if given in a .packages file,
+// If no language version is specified, and none if given in a
+// .dart_tool/package_config.json file,
 // we default to the most reason one. In the tests this is hard-coded to 2.8.
 
 /*library: languageVersion=2.8*/
diff --git a/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo3.dart b/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo3.dart
index 6ffcfd9..7f23410 100644
--- a/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo3.dart
+++ b/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo3.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// .packages specifies 2.5, this library tries to go above that, which is fine.
+// .dart_tool/package_config.json specifies 2.5, this library tries to go above
+// that, which is fine.
 
 // @dart = 2.6
 
diff --git a/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo4.dart b/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo4.dart
index 3d3297c..c946e69 100644
--- a/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo4.dart
+++ b/pkg/front_end/test/language_versioning/data/package_default_version/lib/foo4.dart
@@ -2,9 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// .packages specifies 2.5, this library tries to go above that, which is fine,
-// except it still has to be within the range of the sdk. The library stays on
-// the .packages specified one (2.5) and an error is issued.
+// .dart_tool/package_config.json specifies 2.5, this library tries to go above
+// that, which is fine, except it still has to be within the range of the sdk.
+// The library stays on the .dart_tool/package_config.json specified one (2.5)
+// and an error is issued.
 
 /*error: errors=LanguageVersionTooHigh*/
 // @dart = 2.9
diff --git a/pkg/front_end/test/language_versioning/data/package_no_default_version/lib/foo.dart b/pkg/front_end/test/language_versioning/data/package_no_default_version/lib/foo.dart
index c5ecb8b..e731015 100644
--- a/pkg/front_end/test/language_versioning/data/package_no_default_version/lib/foo.dart
+++ b/pkg/front_end/test/language_versioning/data/package_no_default_version/lib/foo.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// If no language version is specified, and none if given in a .packages file,
+// If no language version is specified, and none if given in a
+// .dart_tool/package_config.json file,
 // we default to the most reason one. In the tests this is hard-coded to 2.8.
 
 /*library: languageVersion=2.8*/
diff --git a/pkg/front_end/test/language_versioning/data/package_with_test_packages/.packages b/pkg/front_end/test/language_versioning/data/package_with_test_packages/.packages
deleted file mode 100644
index 91fa8dd..0000000
--- a/pkg/front_end/test/language_versioning/data/package_with_test_packages/.packages
+++ /dev/null
@@ -1 +0,0 @@
-foo:foo/lib/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/bin/bin_file.dart b/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/bin/bin_file.dart
deleted file mode 100644
index 8f4889a..0000000
--- a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/bin/bin_file.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: 
- languageVersion=2.7,
- packageUri=package:foo
-*/
-
-method1() {}
diff --git a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/lib/foo.dart b/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/lib/foo.dart
deleted file mode 100644
index e72d3b0..0000000
--- a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/lib/foo.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: languageVersion=2.7*/
-
-method2() {}
diff --git a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/test/test_file.dart b/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/test/test_file.dart
deleted file mode 100644
index f58d00c..0000000
--- a/pkg/front_end/test/language_versioning/data/package_with_test_packages/foo/test/test_file.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: 
- languageVersion=2.7,
- packageUri=package:foo
-*/
-
-method3() {}
diff --git a/pkg/front_end/test/language_versioning/data/package_with_test_packages/main.dart b/pkg/front_end/test/language_versioning/data/package_with_test_packages/main.dart
deleted file mode 100644
index b29bc24..0000000
--- a/pkg/front_end/test/language_versioning/data/package_with_test_packages/main.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*library: languageVersion=2.8*/
-
-import 'foo/bin/bin_file.dart';
-import 'foo/test/test_file.dart';
-import 'package:foo/foo.dart';
-
-main() {}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options
index 9044751..7279cca 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options
@@ -1,2 +1 @@
-# Point to .packages => Standard layout; redirect to .dart_tool/package_config.json
---packages=.packages
+# No packages specified. It finds .dart_tool/package_config.json automatically.
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX b/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX
index a0a43fc..2983e0b 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX
@@ -1 +1 @@
-foo:foo1/
\ No newline at end of file
+/*error: errors=PackagesFileFormat*/foo:foo1/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart
index 2873e02..c434df6 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart
@@ -1,4 +1,4 @@
-/*library: languageVersion=2.7*/
+// This file shouldn't even be compiled.
 
 int notNamedFoo() {
   return 42;
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart
index 449c3f0..c41a2b7 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart
@@ -1,4 +1,4 @@
-// No language version --- this file shouldn't even be compiled.
+// This file shouldn't even be compiled.
 
 String foo() {
   return "42";
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart
index 3dc5e95..b36e8ea 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart
@@ -7,11 +7,11 @@
 
 // @dart = 2.4
 
-import 'package:foo/foo.dart';
+import /*error: errors=UntranslatableUri*/ 'package:foo/foo.dart';
 
 /*library: languageVersion=2.4*/
 
 main() {
-  var result = notNamedFoo();
+  var result = /*error: errors=MethodNotFound*/ notNamedFoo();
   print(result);
 }
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/null b/pkg/front_end/test/language_versioning/data/specified_packages_02/null
new file mode 100644
index 0000000..5b039db
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/null
@@ -0,0 +1 @@
+/*error: errors=PackageNotFound*/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options
index d3ccc47..23d4c8b 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options
@@ -1,2 +1,2 @@
-# Point to .packagesX => non-standard layout; use it directly
+# Point to a non-json file. Try to use it, it should give an error.
 --packages=.packagesX
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options
index 5c8ed21..7279cca 100644
--- a/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options
@@ -1,2 +1 @@
-# Point to .packages => Standard layout; redirect to .dart_tool/package_config.json which in this case isn't a json file. That's an error!
---packages=.packages
+# No packages specified. It finds .dart_tool/package_config.json automatically.
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index a0282ba..512751f 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:convert' show jsonEncode;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/memory_file_system.dart';
 import 'package:front_end/src/base/processed_options.dart';
@@ -20,6 +22,39 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+final String emptyPackageConfig = jsonEncode({
+  "configVersion": 2,
+  "packages": [],
+});
+
+final String fooBarPackageConfig = jsonEncode({
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "bar",
+    },
+  ],
+});
+final String fooBazPackageConfig = jsonEncode({
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "baz",
+    },
+  ],
+});
+final String fooBazDotDotPackageConfig = jsonEncode({
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../baz",
+    },
+  ],
+});
+
 void main() {
   CompilerContext.runWithDefaultOptions((_) {
     defineReflectiveSuite(() {
@@ -117,13 +152,15 @@
 
   Future<void> test_getUriTranslator_explicitLibrariesSpec() async {
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(emptyPackageConfig);
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///libraries.json'))
         .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
     var raw = new CompilerOptions()
-      ..packagesFileUri = Uri.parse('org-dartlang-test:///.packages')
+      ..packagesFileUri =
+          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
       ..fileSystem = fileSystem
       ..librariesSpecificationUri =
           Uri.parse('org-dartlang-test:///libraries.json');
@@ -135,15 +172,17 @@
 
   Future<void> test_getUriTranslator_inferredLibrariesSpec() async {
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(emptyPackageConfig);
     fileSystem
         .entityForUri(
             Uri.parse('org-dartlang-test:///mysdk/lib/libraries.json'))
         .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
-      ..packagesFileUri = Uri.parse('org-dartlang-test:///.packages')
+      ..packagesFileUri =
+          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
       ..compileSdk = true
       ..sdkRoot = Uri.parse('org-dartlang-test:///mysdk/');
     var processed = new ProcessedOptions(options: raw);
@@ -154,15 +193,17 @@
 
   Future<void> test_getUriTranslator_notInferredLibrariesSpec() async {
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(emptyPackageConfig);
     fileSystem
         .entityForUri(
             Uri.parse('org-dartlang-test:///mysdk/lib/libraries.json'))
         .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
-      ..packagesFileUri = Uri.parse('org-dartlang-test:///.packages')
+      ..packagesFileUri =
+          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
       ..compileSdk = false // libraries.json is only inferred if true
       ..sdkRoot = Uri.parse('org-dartlang-test:///mysdk/');
     var processed = new ProcessedOptions(options: raw);
@@ -178,17 +219,18 @@
   }
 
   Future<void> test_getUriTranslator_explicitPackagesFile() async {
-    // This .packages file should be ignored.
+    // This .dart_tool/package_config.json file should be ignored.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
     // This one should be used.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///explicit.packages'))
-        .writeAsStringSync('foo:baz\n');
+        .entityForUri(Uri.parse('org-dartlang-test:///explicit.json'))
+        .writeAsStringSync(fooBazPackageConfig);
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
-      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.packages');
+      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.json');
     var processed = new ProcessedOptions(options: raw);
     var uriTranslator = await processed.getUriTranslator();
     checkPackageExpansion('foo', 'baz', uriTranslator.packages);
@@ -196,36 +238,38 @@
 
   Future<void>
       test_getUriTranslator_explicitPackagesFile_withBaseLocation() async {
-    // This .packages file should be ignored.
+    // This .dart_tool/package_config.json file should be ignored.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
     // This one should be used.
     fileSystem
         .entityForUri(
-            Uri.parse('org-dartlang-test:///base/location/explicit.packages'))
-        .writeAsStringSync('foo:baz\n');
+            Uri.parse('org-dartlang-test:///base/location/explicit.json'))
+        .writeAsStringSync(fooBazPackageConfig);
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
       ..packagesFileUri =
-          Uri.parse('org-dartlang-test:///base/location/explicit.packages');
+          Uri.parse('org-dartlang-test:///base/location/explicit.json');
     var processed = new ProcessedOptions(options: raw);
     var uriTranslator = await processed.getUriTranslator();
     checkPackageExpansion('foo', 'base/location/baz', uriTranslator.packages);
   }
 
   Future<void> test_getUriTranslator_implicitPackagesFile_ambiguous() async {
-    // This .packages file should be ignored.
+    // This .dart_tool/package_config.json file should be ignored.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
     // This one should be used.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///explicit.packages'))
-        .writeAsStringSync('foo:baz\n');
+        .entityForUri(Uri.parse('org-dartlang-test:///explicit.json'))
+        .writeAsStringSync(fooBazPackageConfig);
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
-      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.packages');
+      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.json');
     var processed = new ProcessedOptions(options: raw);
     var uriTranslator = await processed.getUriTranslator();
     checkPackageExpansion('foo', 'baz', uriTranslator.packages);
@@ -236,18 +280,29 @@
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
         .createDirectory();
-    // Packages directory should be ignored (.packages file takes precedence).
+    // Packages directory should be ignored (.dart_tool/package_config.json is
+    // the only one that will be automatically found).
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/packages/'))
         .createDirectory();
     // This .packages file should be ignored.
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
-    // This one should be used.
+        .writeAsStringSync("foo:packages1");
+    // This .packages file should be ignored.
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/.packages'))
-        .writeAsStringSync('foo:baz\n');
+        .writeAsStringSync("foo:packages2");
+    // This .dart_tool/package_config.json file should be ignored.
+    fileSystem
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
+    // This one should be used.
+    fileSystem
+        .entityForUri(Uri.parse(
+            'org-dartlang-test:///base/location/.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBazDotDotPackageConfig);
     var raw = new CompilerOptions()..fileSystem = fileSystem;
     var processed = new ProcessedOptions(
         options: raw,
@@ -261,14 +316,16 @@
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
         .createDirectory();
-    // This .packages file should be ignored.
+    // This .dart_tool/package_config.json file should be ignored.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
     // This one should be used.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///base/.packages'))
-        .writeAsStringSync('foo:baz\n');
+        .entityForUri(Uri.parse(
+            'org-dartlang-test:///base/.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBazDotDotPackageConfig);
     var raw = new CompilerOptions()..fileSystem = fileSystem;
     var processed = new ProcessedOptions(
         options: raw,
@@ -289,12 +346,23 @@
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/packages/'))
         .createDirectory();
 
+    // .packages is deprecated and should be ignored.
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .writeAsStringSync('foo:packages1\n');
     fileSystem
         .entityForUri(Uri.parse('org-dartlang-test:///base/.packages'))
-        .writeAsStringSync('foo:baz\n');
+        .writeAsStringSync('foo:packages2\n');
+
+    // .dart_tool/package_config.json
+    fileSystem
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
+    fileSystem
+        .entityForUri(Uri.parse(
+            'org-dartlang-test:///base/.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBazDotDotPackageConfig);
     var raw = new CompilerOptions()..fileSystem = fileSystem;
     var processed = new ProcessedOptions(
         options: raw,
@@ -309,7 +377,7 @@
         .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
         .createDirectory();
     var errors = [];
-    // .packages file should be ignored.
+    // There is no .dart_tool/package_config.json file.
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
       ..onDiagnostic = errors.add;
@@ -323,10 +391,12 @@
 
   Future<void> test_getUriTranslator_noPackages() async {
     var errors = <DiagnosticMessage>[];
-    // .packages file should be ignored.
+    // .dart_tool/package_config.json file should be ignored when specifying
+    // empty Uri.
     fileSystem
-        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
-        .writeAsStringSync('foo:bar\n');
+        .entityForUri(
+            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
+        .writeAsStringSync(fooBarPackageConfig);
     var raw = new CompilerOptions()
       ..fileSystem = fileSystem
       ..packagesFileUri = new Uri()
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart b/pkg/front_end/testcases/enhanced_enums/issue49236.dart
new file mode 100644
index 0000000..076a34d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+mixin M {
+  String toString() => "M";
+}
+
+abstract class A {
+  String toString() => "A";
+}
+
+abstract class B implements Enum {
+  String toString() => "B";
+}
+
+enum E1 with M {
+  element
+}
+
+enum E2 with M {
+  element;
+
+  String toString() => "E2";
+}
+
+enum E3 {
+  element;
+
+  String toString() => "E3";
+}
+
+enum E4 implements B {
+  element
+}
+
+enum E5 implements B {
+  element;
+
+  String toString() => "E5";
+}
+
+enum E6 with A {
+  element
+}
+
+enum E7 with A {
+  element;
+
+  String toString() => "E7";
+}
+
+checkEqual(x, y) {
+  if (x != y) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+
+main() {
+  checkEqual("${E1.element}", "M");
+  checkEqual("${E2.element}", "E2");
+  checkEqual("${E3.element}", "E3");
+  checkEqual("${E4.element}", "E4.element");
+  checkEqual("${E5.element}", "E5");
+  checkEqual("${E6.element}", "A");
+  checkEqual("${E7.element}", "E7");
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.expect
new file mode 100644
index 0000000..bf8ee4f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    return "M";
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "A";
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "B";
+}
+abstract class _E1&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 element = #C3;
+  const constructor •(core::int #index, core::String #name) → self::E1
+    : super self::_E1&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = #C6;
+  static const field self::E2 element = #C5;
+  const constructor •(core::int #index, core::String #name) → self::E2
+    : super self::_E2&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E2";
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = #C8;
+  static const field self::E3 element = #C7;
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = #C10;
+  static const field self::E4 element = #C9;
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = #C12;
+  static const field self::E5 element = #C11;
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5";
+}
+abstract class _E6&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = #C14;
+  static const field self::E6 element = #C13;
+  const constructor •(core::int #index, core::String #name) → self::E6
+    : super self::_E6&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = #C16;
+  static const field self::E7 element = #C15;
+  const constructor •(core::int #index, core::String #name) → self::E7
+    : super self::_E7&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E7";
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::checkEqual("${#C3}", "M");
+  self::checkEqual("${#C5}", "E2");
+  self::checkEqual("${#C7}", "E3");
+  self::checkEqual("${#C9}", "E4.element");
+  self::checkEqual("${#C11}", "E5");
+  self::checkEqual("${#C13}", "A");
+  self::checkEqual("${#C15}", "E7");
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1>[#C3]
+  #C5 = self::E2 {index:#C1, _name:#C2}
+  #C6 = <self::E2>[#C5]
+  #C7 = self::E3 {index:#C1, _name:#C2}
+  #C8 = <self::E3>[#C7]
+  #C9 = self::E4 {index:#C1, _name:#C2}
+  #C10 = <self::E4>[#C9]
+  #C11 = self::E5 {index:#C1, _name:#C2}
+  #C12 = <self::E5>[#C11]
+  #C13 = self::E6 {index:#C1, _name:#C2}
+  #C14 = <self::E6>[#C13]
+  #C15 = self::E7 {index:#C1, _name:#C2}
+  #C16 = <self::E7>[#C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49236.dart:
+- E1. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _E1&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- _E2&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- E3. (from org-dartlang-testcase:///issue49236.dart:27:6)
+- E4. (from org-dartlang-testcase:///issue49236.dart:33:6)
+- E5. (from org-dartlang-testcase:///issue49236.dart:37:6)
+- E6. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- _E6&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- E7. (from org-dartlang-testcase:///issue49236.dart:47:6)
+- _E7&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:47:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.transformed.expect
new file mode 100644
index 0000000..b1cce1b
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.strong.transformed.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    return "M";
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "A";
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "B";
+}
+abstract class _E1&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "M";
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 element = #C3;
+  const constructor •(core::int #index, core::String #name) → self::E1
+    : super self::_E1&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "M";
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = #C6;
+  static const field self::E2 element = #C5;
+  const constructor •(core::int #index, core::String #name) → self::E2
+    : super self::_E2&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E2";
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = #C8;
+  static const field self::E3 element = #C7;
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = #C10;
+  static const field self::E4 element = #C9;
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = #C12;
+  static const field self::E5 element = #C11;
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5";
+}
+abstract class _E6&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "A";
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = #C14;
+  static const field self::E6 element = #C13;
+  const constructor •(core::int #index, core::String #name) → self::E6
+    : super self::_E6&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "A";
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = #C16;
+  static const field self::E7 element = #C15;
+  const constructor •(core::int #index, core::String #name) → self::E7
+    : super self::_E7&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E7";
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::checkEqual("${#C3}", "M");
+  self::checkEqual("${#C5}", "E2");
+  self::checkEqual("${#C7}", "E3");
+  self::checkEqual("${#C9}", "E4.element");
+  self::checkEqual("${#C11}", "E5");
+  self::checkEqual("${#C13}", "A");
+  self::checkEqual("${#C15}", "E7");
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1>[#C3]
+  #C5 = self::E2 {index:#C1, _name:#C2}
+  #C6 = <self::E2>[#C5]
+  #C7 = self::E3 {index:#C1, _name:#C2}
+  #C8 = <self::E3>[#C7]
+  #C9 = self::E4 {index:#C1, _name:#C2}
+  #C10 = <self::E4>[#C9]
+  #C11 = self::E5 {index:#C1, _name:#C2}
+  #C12 = <self::E5>[#C11]
+  #C13 = self::E6 {index:#C1, _name:#C2}
+  #C14 = <self::E6>[#C13]
+  #C15 = self::E7 {index:#C1, _name:#C2}
+  #C16 = <self::E7>[#C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49236.dart:
+- E1. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _E1&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- _E2&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- E3. (from org-dartlang-testcase:///issue49236.dart:27:6)
+- E4. (from org-dartlang-testcase:///issue49236.dart:33:6)
+- E5. (from org-dartlang-testcase:///issue49236.dart:37:6)
+- E6. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- _E6&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- E7. (from org-dartlang-testcase:///issue49236.dart:47:6)
+- _E7&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:47:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline.expect
new file mode 100644
index 0000000..55f4471
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline.expect
@@ -0,0 +1,44 @@
+mixin M {
+  String toString() => "M";
+}
+
+abstract class A {
+  String toString() => "A";
+}
+
+abstract class B implements Enum {
+  String toString() => "B";
+}
+
+enum E1 with M { element }
+
+enum E2 with M {
+  element;
+
+  String toString() => "E2";
+}
+
+enum E3 {
+  element;
+
+  String toString() => "E3";
+}
+
+enum E4 implements B { element }
+
+enum E5 implements B {
+  element;
+
+  String toString() => "E5";
+}
+
+enum E6 with A { element }
+
+enum E7 with A {
+  element;
+
+  String toString() => "E7";
+}
+
+checkEqual(x, y) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..76eb999
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.textual_outline_modelled.expect
@@ -0,0 +1,44 @@
+abstract class A {
+  String toString() => "A";
+}
+
+abstract class B implements Enum {
+  String toString() => "B";
+}
+
+checkEqual(x, y) {}
+
+enum E1 with M { element }
+
+enum E2 with M {
+  element;
+
+  String toString() => "E2";
+}
+
+enum E3 {
+  element;
+
+  String toString() => "E3";
+}
+
+enum E4 implements B { element }
+
+enum E5 implements B {
+  element;
+
+  String toString() => "E5";
+}
+
+enum E6 with A { element }
+
+enum E7 with A {
+  element;
+
+  String toString() => "E7";
+}
+
+main() {}
+mixin M {
+  String toString() => "M";
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.expect
new file mode 100644
index 0000000..e3996a0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    return "M";
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "A";
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "B";
+}
+abstract class _E1&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 element = #C3;
+  const constructor •(core::int #index, core::String #name) → self::E1
+    : super self::_E1&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = #C6;
+  static const field self::E2 element = #C5;
+  const constructor •(core::int #index, core::String #name) → self::E2
+    : super self::_E2&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E2";
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = #C8;
+  static const field self::E3 element = #C7;
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = #C10;
+  static const field self::E4 element = #C9;
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = #C12;
+  static const field self::E5 element = #C11;
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5";
+}
+abstract class _E6&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = #C14;
+  static const field self::E6 element = #C13;
+  const constructor •(core::int #index, core::String #name) → self::E6
+    : super self::_E6&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = #C16;
+  static const field self::E7 element = #C15;
+  const constructor •(core::int #index, core::String #name) → self::E7
+    : super self::_E7&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E7";
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::checkEqual("${#C3}", "M");
+  self::checkEqual("${#C5}", "E2");
+  self::checkEqual("${#C7}", "E3");
+  self::checkEqual("${#C9}", "E4.element");
+  self::checkEqual("${#C11}", "E5");
+  self::checkEqual("${#C13}", "A");
+  self::checkEqual("${#C15}", "E7");
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2 {index:#C1, _name:#C2}
+  #C6 = <self::E2*>[#C5]
+  #C7 = self::E3 {index:#C1, _name:#C2}
+  #C8 = <self::E3*>[#C7]
+  #C9 = self::E4 {index:#C1, _name:#C2}
+  #C10 = <self::E4*>[#C9]
+  #C11 = self::E5 {index:#C1, _name:#C2}
+  #C12 = <self::E5*>[#C11]
+  #C13 = self::E6 {index:#C1, _name:#C2}
+  #C14 = <self::E6*>[#C13]
+  #C15 = self::E7 {index:#C1, _name:#C2}
+  #C16 = <self::E7*>[#C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49236.dart:
+- E1. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _E1&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- _E2&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- E3. (from org-dartlang-testcase:///issue49236.dart:27:6)
+- E4. (from org-dartlang-testcase:///issue49236.dart:33:6)
+- E5. (from org-dartlang-testcase:///issue49236.dart:37:6)
+- E6. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- _E6&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- E7. (from org-dartlang-testcase:///issue49236.dart:47:6)
+- _E7&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:47:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.modular.expect
new file mode 100644
index 0000000..e3996a0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.modular.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    return "M";
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "A";
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "B";
+}
+abstract class _E1&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 element = #C3;
+  const constructor •(core::int #index, core::String #name) → self::E1
+    : super self::_E1&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = #C6;
+  static const field self::E2 element = #C5;
+  const constructor •(core::int #index, core::String #name) → self::E2
+    : super self::_E2&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E2";
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = #C8;
+  static const field self::E3 element = #C7;
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = #C10;
+  static const field self::E4 element = #C9;
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = #C12;
+  static const field self::E5 element = #C11;
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5";
+}
+abstract class _E6&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = #C14;
+  static const field self::E6 element = #C13;
+  const constructor •(core::int #index, core::String #name) → self::E6
+    : super self::_E6&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = #C16;
+  static const field self::E7 element = #C15;
+  const constructor •(core::int #index, core::String #name) → self::E7
+    : super self::_E7&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E7";
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::checkEqual("${#C3}", "M");
+  self::checkEqual("${#C5}", "E2");
+  self::checkEqual("${#C7}", "E3");
+  self::checkEqual("${#C9}", "E4.element");
+  self::checkEqual("${#C11}", "E5");
+  self::checkEqual("${#C13}", "A");
+  self::checkEqual("${#C15}", "E7");
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2 {index:#C1, _name:#C2}
+  #C6 = <self::E2*>[#C5]
+  #C7 = self::E3 {index:#C1, _name:#C2}
+  #C8 = <self::E3*>[#C7]
+  #C9 = self::E4 {index:#C1, _name:#C2}
+  #C10 = <self::E4*>[#C9]
+  #C11 = self::E5 {index:#C1, _name:#C2}
+  #C12 = <self::E5*>[#C11]
+  #C13 = self::E6 {index:#C1, _name:#C2}
+  #C14 = <self::E6*>[#C13]
+  #C15 = self::E7 {index:#C1, _name:#C2}
+  #C16 = <self::E7*>[#C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49236.dart:
+- E1. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _E1&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- _E2&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- E3. (from org-dartlang-testcase:///issue49236.dart:27:6)
+- E4. (from org-dartlang-testcase:///issue49236.dart:33:6)
+- E5. (from org-dartlang-testcase:///issue49236.dart:37:6)
+- E6. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- _E6&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- E7. (from org-dartlang-testcase:///issue49236.dart:47:6)
+- _E7&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:47:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.outline.expect
new file mode 100644
index 0000000..6e652e5
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.outline.expect
@@ -0,0 +1,129 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    ;
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E1&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::element];
+  static const field self::E1 element = const self::E1::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E1
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::M::toString}();
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = const <self::E2>[self::E2::element];
+  static const field self::E2 element = const self::E2::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E2
+    ;
+  method toString() → core::String
+    return super.{self::_E2&_Enum&M::toString}();
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = const <self::E3>[self::E3::element];
+  static const field self::E3 element = const self::E3::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = const <self::E4>[self::E4::element];
+  static const field self::E4 element = const self::E4::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = const <self::E5>[self::E5::element];
+  static const field self::E5 element = const self::E5::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5.${this.{core::_Enum::_name}{core::String}}";
+}
+abstract class _E6&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = const <self::E6>[self::E6::element];
+  static const field self::E6 element = const self::E6::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E6
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub method toString() → core::String
+    return super.{self::A::toString}();
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = const <self::E7>[self::E7::element];
+  static const field self::E7 element = const self::E7::•(0, "element");
+  const constructor •(core::int #index, core::String #name) → self::E7
+    ;
+  method toString() → core::String
+    return super.{self::_E7&_Enum&A::toString}();
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:17:6 -> ListConstant(const <E1*>[const E1{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:18:3 -> InstanceConstant(const E1{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:21:6 -> ListConstant(const <E2*>[const E2{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:22:3 -> InstanceConstant(const E2{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:27:6 -> ListConstant(const <E3*>[const E3{_Enum.index: 0, _Enum._name: "element"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:28:3 -> InstanceConstant(const E3{_Enum.index: 0, _Enum._name: "element"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:33:6 -> ListConstant(const <E4*>[const E4{_Enum.index: 0, _Enum._name: "element"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:34:3 -> InstanceConstant(const E4{_Enum.index: 0, _Enum._name: "element"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:37:6 -> ListConstant(const <E5*>[const E5{_Enum.index: 0, _Enum._name: "element"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:38:3 -> InstanceConstant(const E5{_Enum.index: 0, _Enum._name: "element"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:43:6 -> ListConstant(const <E6*>[const E6{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:44:3 -> InstanceConstant(const E6{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49236.dart:47:6 -> ListConstant(const <E7*>[const E7{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49236.dart:48:3 -> InstanceConstant(const E7{})
+Extra constant evaluation: evaluated: 45, effectively constant: 14
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.transformed.expect
new file mode 100644
index 0000000..c6df72d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49236.dart.weak.transformed.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  method toString() → core::String
+    return "M";
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "A";
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method toString() → core::String
+    return "B";
+}
+abstract class _E1&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "M";
+}
+class E1 extends self::_E1&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 element = #C3;
+  const constructor •(core::int #index, core::String #name) → self::E1
+    : super self::_E1&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E1&_Enum&M::toString}();
+}
+abstract class _E2&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "M";
+}
+class E2 extends self::_E2&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E2> values = #C6;
+  static const field self::E2 element = #C5;
+  const constructor •(core::int #index, core::String #name) → self::E2
+    : super self::_E2&_Enum&M::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E2";
+}
+class E3 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3> values = #C8;
+  static const field self::E3 element = #C7;
+  const constructor •(core::int #index, core::String #name) → self::E3
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E3";
+}
+class E4 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E4> values = #C10;
+  static const field self::E4 element = #C9;
+  const constructor •(core::int #index, core::String #name) → self::E4
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+}
+class E5 extends core::_Enum implements self::B /*isEnum*/  {
+  static const field core::List<self::E5> values = #C12;
+  static const field self::E5 element = #C11;
+  const constructor •(core::int #index, core::String #name) → self::E5
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E5";
+}
+abstract class _E6&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E6&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "A";
+}
+class E6 extends self::_E6&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E6> values = #C14;
+  static const field self::E6 element = #C13;
+  const constructor •(core::int #index, core::String #name) → self::E6
+    : super self::_E6&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return super.{self::_E6&_Enum&A::toString}();
+}
+abstract class _E7&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E7&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  method toString() → core::String
+    return "A";
+}
+class E7 extends self::_E7&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E7> values = #C16;
+  static const field self::E7 element = #C15;
+  const constructor •(core::int #index, core::String #name) → self::E7
+    : super self::_E7&_Enum&A::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E7";
+}
+static method checkEqual(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::checkEqual("${#C3}", "M");
+  self::checkEqual("${#C5}", "E2");
+  self::checkEqual("${#C7}", "E3");
+  self::checkEqual("${#C9}", "E4.element");
+  self::checkEqual("${#C11}", "E5");
+  self::checkEqual("${#C13}", "A");
+  self::checkEqual("${#C15}", "E7");
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2 {index:#C1, _name:#C2}
+  #C6 = <self::E2*>[#C5]
+  #C7 = self::E3 {index:#C1, _name:#C2}
+  #C8 = <self::E3*>[#C7]
+  #C9 = self::E4 {index:#C1, _name:#C2}
+  #C10 = <self::E4*>[#C9]
+  #C11 = self::E5 {index:#C1, _name:#C2}
+  #C12 = <self::E5*>[#C11]
+  #C13 = self::E6 {index:#C1, _name:#C2}
+  #C14 = <self::E6*>[#C13]
+  #C15 = self::E7 {index:#C1, _name:#C2}
+  #C16 = <self::E7*>[#C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49236.dart:
+- E1. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _E1&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:17:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- _E2&_Enum&M. (from org-dartlang-testcase:///issue49236.dart:21:6)
+- E3. (from org-dartlang-testcase:///issue49236.dart:27:6)
+- E4. (from org-dartlang-testcase:///issue49236.dart:33:6)
+- E5. (from org-dartlang-testcase:///issue49236.dart:37:6)
+- E6. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- _E6&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:43:6)
+- E7. (from org-dartlang-testcase:///issue49236.dart:47:6)
+- _E7&_Enum&A. (from org-dartlang-testcase:///issue49236.dart:47:6)
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 8015039..a3f6508 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -93,7 +93,8 @@
   ..addOption('depfile',
       help: 'Path to output Ninja depfile. Only used in batch mode.')
   ..addOption('packages',
-      help: '.packages file to use for compilation', defaultsTo: null)
+      help: '.dart_tool/package_config.json file to use for compilation',
+      defaultsTo: null)
   ..addMultiOption('source',
       help: 'List additional source files to include into compilation.',
       defaultsTo: const <String>[])
@@ -670,7 +671,8 @@
   Future<void> writeJavascriptBundle(KernelCompilationResults results,
       String filename, String fileSystemScheme, String moduleFormat) async {
     var packageConfig = await loadPackageConfigUri(
-        _compilerOptions.packagesFileUri ?? File('.packages').absolute.uri);
+        _compilerOptions.packagesFileUri ??
+            File('.dart_tool/package_config.json').absolute.uri);
     var soundNullSafety = _compilerOptions.nnbdMode == NnbdMode.Strong;
     final Component component = results.component;
     // Compute strongly connected components.
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 12004ad..d9d8b6f 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -486,7 +486,8 @@
     Directory tempDir;
     setUp(() {
       var systemTempDir = Directory.systemTemp;
-      tempDir = systemTempDir.createTempSync('foo bar');
+      tempDir = systemTempDir.createTempSync('frontendServerTest');
+      new Directory('${tempDir.path}/.dart_tool').createSync();
     });
 
     tearDown(() {
@@ -1349,9 +1350,21 @@
     ]
   }
 ''');
-      file = File('${tempDir.path}/app/.packages')..createSync(recursive: true);
-      file.writeAsStringSync("pkgA:../pkgA\n"
-          "pkgB:../pkgB");
+      file = File('${tempDir.path}/app/.dart_tool/package_config.json')
+        ..createSync(recursive: true);
+      file.writeAsStringSync(jsonEncode({
+        "configVersion": 2,
+        "packages": [
+          {
+            "name": "pkgA",
+            "rootUri": "../../pkgA",
+          },
+          {
+            "name": "pkgB",
+            "rootUri": "../../pkgB",
+          },
+        ],
+      }));
 
       // Entry point A uses both package A and B.
       file = File('${tempDir.path}/app/a.dart')..createSync(recursive: true);
@@ -1441,9 +1454,17 @@
     test('incremental-serialization with reject', () async {
       // Basically a reproduction of
       // https://github.com/flutter/flutter/issues/44384.
-      var file = File('${tempDir.path}/pkgA/.packages')
+      var file = File('${tempDir.path}/pkgA/.dart_tool/package_config.json')
         ..createSync(recursive: true);
-      file.writeAsStringSync("pkgA:.");
+      file.writeAsStringSync(jsonEncode({
+        "configVersion": 2,
+        "packages": [
+          {
+            "name": "pkgA",
+            "rootUri": "..",
+          },
+        ],
+      }));
       file = File('${tempDir.path}/pkgA/a.dart')..createSync(recursive: true);
       file.writeAsStringSync("pkgA() {}");
 
@@ -1629,9 +1650,9 @@
     test('compile and recompile with MultiRootFileSystem', () async {
       var file = File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("main() {}\n");
-      File('${tempDir.path}/.packages')
+      File('${tempDir.path}/.dart_tool/package_config.json')
         ..createSync()
-        ..writeAsStringSync("\n");
+        ..writeAsStringSync('{"configVersion": 2, "packages": []}');
       var dillFile = File('${tempDir.path}/app.dill');
       expect(dillFile.existsSync(), equals(false));
       final List<String> args = <String>[
@@ -1639,7 +1660,7 @@
         '--incremental',
         '--platform=${platformKernel.path}',
         '--output-dill=${dillFile.path}',
-        '--packages=test-scheme:///.packages',
+        '--packages=test-scheme:///.dart_tool/package_config.json',
         '--filesystem-root=${tempDir.path}',
         '--filesystem-scheme=test-scheme',
         'test-scheme:///foo.dart'
@@ -1657,9 +1678,10 @@
       final src3 = File('${tempDir.path}/src3.dart')
         ..createSync()
         ..writeAsStringSync("entryPoint3() {}\n");
-      final packagesFile = File('${tempDir.path}/.packages')
-        ..createSync()
-        ..writeAsStringSync("\n");
+      final packagesFile =
+          File('${tempDir.path}/.dart_tool/package_config.json')
+            ..createSync()
+            ..writeAsStringSync('{"configVersion": 2, "packages": []}');
       final dillFile = File('${tempDir.path}/app.dill');
       expect(dillFile.existsSync(), equals(false));
       final List<String> args = <String>[
@@ -1766,7 +1788,7 @@
           '--platform=${platformKernel.path}',
           '--output-dill=${dillFile.path}',
           '--enable-http-uris',
-          '--packages=http://$host:$port/.packages',
+          '--packages=http://$host:$port/.dart_tool/package_config.json',
           'http://$host:$port/foo.dart',
         ];
         expect(await starter(args), 0);
@@ -1781,7 +1803,7 @@
           '--platform=${platformKernel.path}',
           '--output-dill=${dillFile.path}',
           '--enable-http-uris',
-          '--packages=test-app:///.packages',
+          '--packages=test-app:///.dart_tool/package_config.json',
           '--filesystem-root=http://$host:$port/',
           '--filesystem-scheme=test-app',
           'test-app:///foo.dart',
@@ -2037,9 +2059,17 @@
     test('compile to JavaScript with package scheme', () async {
       var file = File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("main() {\n}\n");
-      var packages = File('${tempDir.path}/.packages')
+      var packages = File('${tempDir.path}/.dart_tool/package_config.json')
         ..createSync()
-        ..writeAsStringSync("hello:${tempDir.uri}\n");
+        ..writeAsStringSync(jsonEncode({
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "hello",
+              "rootUri": "${tempDir.uri}",
+            },
+          ],
+        }));
       var dillFile = File('${tempDir.path}/app.dill');
 
       expect(dillFile.existsSync(), false);
@@ -2060,9 +2090,17 @@
     test('compile to JavaScript weak null safety', () async {
       var file = File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("// @dart = 2.9\nmain() {\n}\n");
-      var packages = File('${tempDir.path}/.packages')
+      var packages = File('${tempDir.path}/.dart_tool/package_config.json')
         ..createSync()
-        ..writeAsStringSync("hello:${tempDir.uri}\n");
+        ..writeAsStringSync(jsonEncode({
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "hello",
+              "rootUri": "${tempDir.uri}",
+            },
+          ],
+        }));
       var dillFile = File('${tempDir.path}/app.dill');
 
       expect(dillFile.existsSync(), false);
@@ -2084,9 +2122,17 @@
         () async {
       var file = File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("// @dart = 2.9\nmain() {\n}\n");
-      var packages = File('${tempDir.path}/.packages')
+      var packages = File('${tempDir.path}/.dart_tool/package_config.json')
         ..createSync()
-        ..writeAsStringSync("hello:${tempDir.uri}\n");
+        ..writeAsStringSync(jsonEncode({
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "hello",
+              "rootUri": "${tempDir.uri}",
+            },
+          ],
+        }));
       var dillFile = File('${tempDir.path}/app.dill');
 
       expect(dillFile.existsSync(), false);
@@ -2844,9 +2890,17 @@
       File('${lib.path}/foo.dart')
         ..createSync()
         ..writeAsStringSync("main() {}\n");
-      File packages = File('${tempDir.path}/.packages')
+      File packages = File('${tempDir.path}/.dart_tool/package_config.json')
         ..createSync()
-        ..writeAsStringSync('test:lib/\n');
+        ..writeAsStringSync(jsonEncode({
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "test",
+              "rootUri": "../lib",
+            },
+          ],
+        }));
       var dillFile = File('${tempDir.path}/app.dill');
       expect(dillFile.existsSync(), equals(false));
       var depFile = File('${tempDir.path}/the depfile');
diff --git a/pkg/js_shared/analysis_options.yaml b/pkg/js_shared/analysis_options.yaml
new file mode 100644
index 0000000..c36c2c5
--- /dev/null
+++ b/pkg/js_shared/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/core.yaml
diff --git a/pkg/js_shared/lib/synced/recipe_syntax.dart b/pkg/js_shared/lib/synced/recipe_syntax.dart
index b24e7c2..51b8358 100644
--- a/pkg/js_shared/lib/synced/recipe_syntax.dart
+++ b/pkg/js_shared/lib/synced/recipe_syntax.dart
@@ -131,7 +131,9 @@
   static const int _at = 0x40;
   static const String _atString = '@';
 
+  // ignore: unused_field
   static const int _uppercaseA = 0x41;
+  // ignore: unused_field
   static const int _uppercaseZ = 0x5A;
 
   static const int _leftBracket = 0x5B;
@@ -148,6 +150,7 @@
   static const String _backtickString = '`';
 
   static const int _lowercaseA = 0x61;
+  // ignore: unused_field
   static const int _lowercaseZ = 0x7A;
 
   static const int _leftBrace = 0x7B;
diff --git a/pkg/js_shared/pubspec.yaml b/pkg/js_shared/pubspec.yaml
index 3503f25..f2cad2e 100644
--- a/pkg/js_shared/pubspec.yaml
+++ b/pkg/js_shared/pubspec.yaml
@@ -9,3 +9,4 @@
 dev_dependencies:
   _fe_analyzer_shared: any
   expect: any
+  lints: any
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 0bc4b59..ed2255b 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -49,7 +49,7 @@
 final bool verbose = new bool.fromEnvironment('DFE_VERBOSE');
 final bool dumpKernel = new bool.fromEnvironment('DFE_DUMP_KERNEL');
 const String platformKernelFile = 'virtual_platform_kernel.dill';
-const String dotPackagesFile = '.packages';
+const String packageConfigFile = '.dart_tool/package_config.json';
 
 // NOTE: Any changes to these tags need to be reflected in kernel_isolate.cc
 // Tags used to indicate different requests to the dart frontend.
@@ -599,7 +599,7 @@
       }
 
       FileSystem fileSystem =
-          _buildFileSystem([dotPackagesFile, <int>[]], null, null, null);
+          _buildFileSystem([packageConfigFile, <int>[]], null, null, null);
 
       // TODO(aam): IncrementalCompilerWrapper instance created below have to be
       // destroyed when corresponding isolate is shut down. To achieve that
@@ -610,7 +610,7 @@
             component, isolateGroupId, fileSystem, null,
             enableAsserts: enableAsserts,
             experimentalFlags: experimentalFlags,
-            packageConfig: dotPackagesFile,
+            packageConfig: packageConfigFile,
             enableMirrors: enableMirrors);
         isolateCompilers[isolateGroupId] = compiler;
         await compiler.compile(
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 03ffe27..8a380dc 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -69,7 +69,8 @@
 void declareCompilerOptions(ArgParser args) {
   args.addOption('platform',
       help: 'Path to vm_platform_strong.dill file', defaultsTo: null);
-  args.addOption('packages', help: 'Path to .packages file', defaultsTo: null);
+  args.addOption('packages',
+      help: 'Path to .dart_tool/package_config.json file', defaultsTo: null);
   args.addOption('output',
       abbr: 'o', help: 'Path to resulting dill file', defaultsTo: null);
   args.addFlag('aot',
@@ -95,7 +96,7 @@
       defaultsTo: true);
   args.addMultiOption('filesystem-root',
       help: 'A base path for the multi-root virtual file system.'
-          ' If multi-root file system is used, the input script and .packages file should be specified using URI.');
+          ' If multi-root file system is used, the input script and .dart_tool/package_config.json file should be specified using URI.');
   args.addOption('filesystem-scheme',
       help: 'The URI scheme for the multi-root virtual filesystem.');
   args.addMultiOption('source',
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index aaf4463..8bfa4e40 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -1029,8 +1029,20 @@
     });
 
     test('compile, reject, compile again', () async {
-      var packageUri = Uri.file('${mytest.path}/.packages');
-      new File(packageUri.toFilePath()).writeAsStringSync('foo:lib/\n');
+      new Directory(mytest.path + "/.dart_tool").createSync();
+      var packageUri =
+          Uri.file('${mytest.path}/.dart_tool/package_config.json');
+      new File(packageUri.toFilePath()).writeAsStringSync(jsonEncode({
+        "configVersion": 2,
+        "packages": [
+          {
+            "name": "foo",
+            "rootUri": "..",
+            "packageUri": "lib",
+            "languageVersion": "2.7",
+          },
+        ],
+      }));
       new Directory(mytest.path + "/lib").createSync();
       var fooUri = Uri.file('${mytest.path}/lib/foo.dart');
       new File(fooUri.toFilePath())
@@ -1581,7 +1593,7 @@
     });
 
     test('from dill with package uri', () async {
-      // 2 iterations: One where the .packages file is deleted, and one where
+      // 2 iterations: One where the package_config.json file is deleted, and one where
       // it is not.
       for (int i = 0; i < 2; i++) {
         Directory dir = mytest.createTempSync();
@@ -1595,8 +1607,18 @@
           int extra() { return 22; }
         """);
 
-        File packagesFile = new File.fromUri(dir.uri.resolve(".packages"));
-        packagesFile.writeAsStringSync("foo:.");
+        File packagesFile =
+            new File.fromUri(dir.uri.resolve("package_config.json"));
+        packagesFile.writeAsStringSync(jsonEncode({
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "foo",
+              "rootUri": ".",
+              "languageVersion": "2.7",
+            },
+          ],
+        }));
 
         Uri mainUri = Uri.parse("package:foo/main.dart");
 
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index 037a610c..9151eea 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -19,7 +19,6 @@
 
 const String mainScript = 'pkg/vm/bin/gen_kernel.dart';
 const String mainScriptPackageUri = 'package:vm/kernel_front_end.dart';
-const String packagesFile = '.packages';
 const String packageConfigFile = '.dart_tool/package_config.json';
 
 Future<void> testCompile(List<String> args) async {
@@ -56,7 +55,7 @@
       '--platform',
       platformPath(),
       '--packages',
-      '$sdkDir/$packagesFile',
+      '$sdkDir/$packageConfigFile',
       '--output',
       outputDill(),
       '$sdkDir/$mainScript',
@@ -72,7 +71,7 @@
       '--filesystem-root',
       sdkDir,
       '--packages',
-      'test-filesystem-scheme:///$packagesFile',
+      'test-filesystem-scheme:///$packageConfigFile',
       '--output',
       outputDill(),
       'test-filesystem-scheme:///$mainScript',
@@ -88,7 +87,7 @@
       '--filesystem-root',
       sdkDir,
       '--packages',
-      'test-filesystem-scheme:///$packagesFile',
+      'test-filesystem-scheme:///$packageConfigFile',
       '--output',
       outputDill(),
       '$mainScriptPackageUri',
@@ -100,7 +99,7 @@
       '--platform',
       platformPath(),
       '--packages',
-      '$sdkDir/$packagesFile',
+      '$sdkDir/$packageConfigFile',
       '--output',
       outputDill(),
       '--split-output-by-packages',
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 8e05c6c..0b08a37 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -25,7 +25,7 @@
   }
 
   // Tests are run in the root directory of the sdk checkout.
-  final Uri packagesFile = sdkRootFile('.packages');
+  final Uri packagesFile = sdkRootFile('.dart_tool/package_config.json');
   final Uri librariesFile = sdkRootFile('sdk/lib/libraries.json');
 
   final vmTarget = VmTarget(TargetFlags(supportMirrors: false));
diff --git a/pkg/vm_snapshot_analysis/test/utils.dart b/pkg/vm_snapshot_analysis/test/utils.dart
index cea4a7f..ea0216f 100644
--- a/pkg/vm_snapshot_analysis/test/utils.dart
+++ b/pkg/vm_snapshot_analysis/test/utils.dart
@@ -46,7 +46,15 @@
       await File(path.join(dir, file.key)).writeAsString(file.value);
     }
     await File(packages).writeAsString('''
-input:./
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "input",
+      "rootUri": "./"
+    }
+  ]
+}
 ''');
     await File(mainDart).writeAsString('''
 import 'package:input/input.dart' as input;
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 2196982..2d8b531 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1378,6 +1378,12 @@
     if (should_run_user_program) {
       try_load_snapshots_lambda();
     }
+  } else if (script_name == nullptr &&
+             Options::gen_snapshot_kind() != SnapshotKind::kNone) {
+    Syslog::PrintErr(
+        "Snapshot generation should be done using the 'dart compile' "
+        "command.\n");
+    Platform::Exit(kErrorExitCode);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json
index 486220a..c40bb0d 100644
--- a/runtime/tests/concurrency/stress_test_list.json
+++ b/runtime/tests/concurrency/stress_test_list.json
@@ -6705,7 +6705,7 @@
     "../../../tests/standalone_2/no_support_service_test.dart",
     "../../../tests/standalone_2/no_support_timeline_test.dart",
     "../../../tests/standalone_2/number_identity_test.dart",
-    "../../../tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart",
+    "../../../tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/both_dir_dot_packages_and_package_config_noimports_test.dart",
     "../../../tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart",
     "../../../tests/standalone_2/package/scenarios/invalid/invalid_utf8_test.dart",
     "../../../tests/standalone_2/package/scenarios/invalid/non_existent_packages_file_test.dart",
diff --git a/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart
index 9b6d74d..d9072ee 100644
--- a/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart
+++ b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart
@@ -42,7 +42,7 @@
     // Compile script to Kernel IR.
     await run('pkg/vm/tool/gen_kernel', <String>[
       '--aot',
-      '--packages=$sdkDir/.packages',
+      '--packages=$sdkDir/.dart_tool/package_config.json',
       '--platform=$platformDill',
       '-o',
       scriptDill,
diff --git a/runtime/tests/vm/dart/issue32950_test.dart b/runtime/tests/vm/dart/issue32950_test.dart
index 7e14a7f..7e24a33 100644
--- a/runtime/tests/vm/dart/issue32950_test.dart
+++ b/runtime/tests/vm/dart/issue32950_test.dart
@@ -15,7 +15,7 @@
 
   var exitPort = new ReceivePort();
   await Isolate.spawnUri(p.toUri(p.absolute(path)), [], null,
-      packageConfig: p.toUri(p.absolute(".packages")),
+      packageConfig: p.toUri(p.absolute(".dart_tool/package_config.json")),
       onExit: exitPort.sendPort);
   await exitPort.first;
   await sourceFile.delete();
diff --git a/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart
index 5310fcd..3221cb5 100644
--- a/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart
+++ b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart
@@ -44,7 +44,7 @@
     // Compile script to Kernel IR.
     await run('pkg/vm/tool/gen_kernel', <String>[
       '--aot',
-      '--packages=$sdkDir/.packages',
+      '--packages=$sdkDir/.dart_tool/package_config.json',
       '--platform=$platformDill',
       '-o',
       scriptDill,
diff --git a/runtime/tests/vm/dart_2/isolates/reload_utils.dart b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
index f41c52f..c721d01 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_utils.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
@@ -97,7 +97,7 @@
 Future compile(String from, String to) async {
   final executable = Platform.executable;
   final command = [
-    '--packages=.packages',
+    '--packages=.dart_tool/package_config.json',
     '--snapshot-kind=kernel',
     '--snapshot=$to',
     from,
diff --git a/runtime/tests/vm/dart_2/issue32950_test.dart b/runtime/tests/vm/dart_2/issue32950_test.dart
index b3f38fc..1f3ec6e 100644
--- a/runtime/tests/vm/dart_2/issue32950_test.dart
+++ b/runtime/tests/vm/dart_2/issue32950_test.dart
@@ -17,7 +17,7 @@
 
   var exitPort = new ReceivePort();
   await Isolate.spawnUri(p.toUri(p.absolute(path)), [], null,
-      packageConfig: p.toUri(p.absolute(".packages")),
+      packageConfig: p.toUri(p.absolute(".dart_tool/package_config.json")),
       onExit: exitPort.sendPort);
   await exitPort.first;
   await sourceFile.delete();
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index a13f06a7..ea47f52 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -2144,7 +2144,7 @@
   void RestoreCodePointer();
 
   // Restores the values of the registers that are blocked to cache some values
-  // e.g. BARRIER_MASK and NULL_REG.
+  // e.g. HEAP_BITS and NULL_REG.
   void RestorePinnedRegisters();
 
   void SetupGlobalPoolAndDispatchTable();
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index cdfa87a..862bf92 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -3019,6 +3019,7 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
+  // See RestorePinnedRegisters for why this can be `ble`.
   // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_value_be_smi == kValueCanBeSmi) {
@@ -3028,8 +3029,7 @@
   lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
   srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
   and_(TMP, TMP, TMP2);
-  and_(TMP, TMP, WRITE_BARRIER_MASK);
-  beqz(TMP, &done, kNearJump);
+  ble(TMP, WRITE_BARRIER_STATE, &done, kNearJump);
 
   Register objectForCall = object;
   if (value != kWriteBarrierValueReg) {
@@ -3091,6 +3091,7 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
+  // See RestorePinnedRegisters for why this can be `ble`.
   // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_value_be_smi == kValueCanBeSmi) {
@@ -3100,8 +3101,7 @@
   lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
   srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
   and_(TMP, TMP, TMP2);
-  and_(TMP, TMP, WRITE_BARRIER_MASK);
-  beqz(TMP, &done, kNearJump);
+  ble(TMP, WRITE_BARRIER_STATE, &done, kNearJump);
   if (spill_lr) {
     PushRegister(RA);
   }
@@ -3672,12 +3672,46 @@
   subi(PP, PP, kHeapObjectTag);  // Pool in PP is untagged!
 }
 
-// Restores the values of the registers that are blocked to cache some values
-// e.g. BARRIER_MASK and NULL_REG.
 void Assembler::RestorePinnedRegisters() {
-  lx(WRITE_BARRIER_MASK,
+  lx(WRITE_BARRIER_STATE,
      Address(THR, target::Thread::write_barrier_mask_offset()));
   lx(NULL_REG, Address(THR, target::Thread::object_null_offset()));
+
+  // Our write barrier usually uses mask-and-test,
+  //   01b6f6b3  and tmp, tmp, mask
+  //       c689  beqz tmp, +10
+  // but on RISC-V compare-and-branch is shorter,
+  //   00ddd663  ble tmp, wbs, +12
+  //
+  // TMP bit 4+ = 0
+  // TMP bit 3  = object is old-and-not-remembered AND value is new (genr bit)
+  // TMP bit 2  = object is old AND value is old-and-not-marked     (incr bit)
+  // TMP bit 1  = garbage
+  // TMP bit 0  = garbage
+  //
+  // Thread::wbm | WRITE_BARRIER_STATE | TMP/combined headers | result
+  // generational only
+  // 0b1000        0b0111                0b11xx                 impossible
+  //                                     0b10xx                 call stub
+  //                                     0b01xx                 skip
+  //                                     0b00xx                 skip
+  // generational and incremental
+  // 0b1100        0b0011                0b11xx                 impossible
+  //                                     0b10xx                 call stub
+  //                                     0b01xx                 call stub
+  //                                     0b00xx                 skip
+  xori(WRITE_BARRIER_STATE, WRITE_BARRIER_STATE,
+       (target::UntaggedObject::kGenerationalBarrierMask << 1) - 1);
+
+  // Generational bit must be higher than incremental bit, with no other bits
+  // between.
+  ASSERT(target::UntaggedObject::kGenerationalBarrierMask ==
+         (target::UntaggedObject::kIncrementalBarrierMask << 1));
+  // Other header bits must be lower.
+  ASSERT(target::UntaggedObject::kIncrementalBarrierMask >
+         target::UntaggedObject::kCanonicalBit);
+  ASSERT(target::UntaggedObject::kIncrementalBarrierMask >
+         target::UntaggedObject::kCardRememberedBit);
 }
 
 void Assembler::SetupGlobalPoolAndDispatchTable() {
@@ -3816,7 +3850,7 @@
     // Or would need to save above.
     COMPILE_ASSERT(IsCalleeSavedRegister(THR));
     COMPILE_ASSERT(IsCalleeSavedRegister(NULL_REG));
-    COMPILE_ASSERT(IsCalleeSavedRegister(WRITE_BARRIER_MASK));
+    COMPILE_ASSERT(IsCalleeSavedRegister(WRITE_BARRIER_STATE));
     COMPILE_ASSERT(IsCalleeSavedRegister(DISPATCH_TABLE_REG));
   }
 
@@ -3859,7 +3893,7 @@
   // Already saved.
   COMPILE_ASSERT(IsCalleeSavedRegister(THR));
   COMPILE_ASSERT(IsCalleeSavedRegister(NULL_REG));
-  COMPILE_ASSERT(IsCalleeSavedRegister(WRITE_BARRIER_MASK));
+  COMPILE_ASSERT(IsCalleeSavedRegister(WRITE_BARRIER_STATE));
   COMPILE_ASSERT(IsCalleeSavedRegister(DISPATCH_TABLE_REG));
   // Need to save.
   COMPILE_ASSERT(!IsCalleeSavedRegister(PP));
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index f62f545..cefa220 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -1257,7 +1257,7 @@
   void RestorePoolPointer();
 
   // Restores the values of the registers that are blocked to cache some values
-  // e.g. BARRIER_MASK and NULL_REG.
+  // e.g. WRITE_BARRIER_STATE and NULL_REG.
   void RestorePinnedRegisters();
 
   void SetupGlobalPoolAndDispatchTable();
diff --git a/runtime/vm/compiler/assembler/assembler_riscv_test.cc b/runtime/vm/compiler/assembler/assembler_riscv_test.cc
index ff2bfb3..8616410 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv_test.cc
@@ -32,7 +32,7 @@
   __ PushNativeCalleeSavedRegisters();
 
   __ mv(THR, A2);
-  __ lx(WRITE_BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ RestorePinnedRegisters();  // Setup WRITE_BARRIER_STATE.
 
   __ StoreIntoObject(A1, FieldAddress(A1, GrowableObjectArray::data_offset()),
                      A0);
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index abf5464..2490c68 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -355,6 +355,8 @@
 const word UntaggedObject::kCardRememberedBit =
     dart::UntaggedObject::kCardRememberedBit;
 
+const word UntaggedObject::kCanonicalBit = dart::UntaggedObject::kCanonicalBit;
+
 const word UntaggedObject::kOldAndNotRememberedBit =
     dart::UntaggedObject::kOldAndNotRememberedBit;
 
@@ -397,6 +399,9 @@
 const word UntaggedObject::kGenerationalBarrierMask =
     dart::UntaggedObject::kGenerationalBarrierMask;
 
+const word UntaggedObject::kIncrementalBarrierMask =
+    dart::UntaggedObject::kIncrementalBarrierMask;
+
 bool IsTypedDataClassId(intptr_t cid) {
   return dart::IsTypedDataClassId(cid);
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 723e277..5f8ec14 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -410,6 +410,7 @@
 class UntaggedObject : public AllStatic {
  public:
   static const word kCardRememberedBit;
+  static const word kCanonicalBit;
   static const word kOldAndNotRememberedBit;
   static const word kOldAndNotMarkedBit;
   static const word kSizeTagPos;
@@ -422,6 +423,7 @@
   static const word kTagBitsSizeTagPos;
   static const word kBarrierOverlapShift;
   static const word kGenerationalBarrierMask;
+  static const word kIncrementalBarrierMask;
 
   static bool IsTypedDataClassId(intptr_t cid);
 };
diff --git a/runtime/vm/constants_riscv.cc b/runtime/vm/constants_riscv.cc
index 7c9b6ed..481d83f 100644
--- a/runtime/vm/constants_riscv.cc
+++ b/runtime/vm/constants_riscv.cc
@@ -18,9 +18,9 @@
 #endif
 
 const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
-    "zero", "ra", "sp",  "gp",   "tp",   "t0",   "t1", "t2", "fp", "thr", "a0",
-    "a1",   "a2", "tmp", "tmp2", "pp",   "a6",   "a7", "s2", "s3", "s4",  "s5",
-    "s6",   "s7", "s8",  "s9",   "null", "mask", "t3", "t4", "t5", "t6",
+    "zero", "ra", "sp",  "gp",   "tp",   "t0",  "t1", "t2", "fp", "thr", "a0",
+    "a1",   "a2", "tmp", "tmp2", "pp",   "a6",  "a7", "s2", "s3", "s4",  "s5",
+    "s6",   "s7", "s8",  "s9",   "null", "wbs", "t3", "t4", "t5", "t6",
 };
 
 const char* const cpu_reg_abi_names[kNumberOfCpuRegisters] = {
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
index 7c2a2b9..e073037 100644
--- a/runtime/vm/constants_riscv.h
+++ b/runtime/vm/constants_riscv.h
@@ -70,7 +70,7 @@
   S8 = 24,   // CALLEE_SAVED_TEMP / FAR_TMP
   S9 = 25,   // DISPATCH_TABLE_REG
   S10 = 26,  // NULL
-  S11 = 27,  // WRITE_BARRIER_MASK
+  S11 = 27,  // WRITE_BARRIER_STATE
   T3 = 28,
   T4 = 29,
   T5 = 30,
@@ -162,7 +162,7 @@
 constexpr Register THR = S1;  // Caches current thread in generated code.
 constexpr Register CALLEE_SAVED_TEMP = S8;
 constexpr Register CALLEE_SAVED_TEMP2 = S7;
-constexpr Register WRITE_BARRIER_MASK = S11;
+constexpr Register WRITE_BARRIER_STATE = S11;
 constexpr Register NULL_REG = S10;  // Caches NullObject() value.
 
 // ABI for catch-clause entry point.
@@ -450,13 +450,13 @@
 // We rely on that any calls into C++ also preserve X18.
 constexpr intptr_t kReservedCpuRegisters =
     R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
-    R(RA) | R(WRITE_BARRIER_MASK) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
+    R(RA) | R(WRITE_BARRIER_STATE) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
     R(FAR_TMP) | R(18);
 constexpr intptr_t kNumberOfReservedCpuRegisters = 15;
 #else
 constexpr intptr_t kReservedCpuRegisters =
     R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
-    R(RA) | R(WRITE_BARRIER_MASK) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
+    R(RA) | R(WRITE_BARRIER_STATE) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
     R(FAR_TMP);
 constexpr intptr_t kNumberOfReservedCpuRegisters = 14;
 #endif
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index abc979e..2e4ad32 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -158,11 +158,11 @@
   // bit fields for storing tags.
   enum TagBits {
     kCardRememberedBit = 0,
-    kOldAndNotMarkedBit = 1,      // Incremental barrier target.
-    kNewBit = 2,                  // Generational barrier target.
-    kOldBit = 3,                  // Incremental barrier source.
-    kOldAndNotRememberedBit = 4,  // Generational barrier source.
-    kCanonicalBit = 5,
+    kCanonicalBit = 1,
+    kOldAndNotMarkedBit = 2,      // Incremental barrier target.
+    kNewBit = 3,                  // Generational barrier target.
+    kOldBit = 4,                  // Incremental barrier source.
+    kOldAndNotRememberedBit = 5,  // Generational barrier source.
     kReservedTagPos = 6,
     kReservedTagSize = 2,
 
diff --git a/runtime/vm/simulator_riscv.cc b/runtime/vm/simulator_riscv.cc
index 3b2034f..937c314 100644
--- a/runtime/vm/simulator_riscv.cc
+++ b/runtime/vm/simulator_riscv.cc
@@ -463,7 +463,9 @@
   pp -= kHeapObjectTag;  // In the PP register, the pool pointer is untagged.
   set_xreg(CODE_REG, code);
   set_xreg(PP, pp);
-  set_xreg(WRITE_BARRIER_MASK, thread->write_barrier_mask());
+  set_xreg(WRITE_BARRIER_STATE,
+           thread->write_barrier_mask() ^
+               ((UntaggedObject::kGenerationalBarrierMask << 1) - 1));
   set_xreg(NULL_REG, static_cast<uintx_t>(Object::null()));
   if (FLAG_precompiled_mode) {
     set_xreg(DISPATCH_TABLE_REG,
diff --git a/sdk/lib/_internal/js_shared/lib/synced/recipe_syntax.dart b/sdk/lib/_internal/js_shared/lib/synced/recipe_syntax.dart
index b24e7c2..51b8358 100644
--- a/sdk/lib/_internal/js_shared/lib/synced/recipe_syntax.dart
+++ b/sdk/lib/_internal/js_shared/lib/synced/recipe_syntax.dart
@@ -131,7 +131,9 @@
   static const int _at = 0x40;
   static const String _atString = '@';
 
+  // ignore: unused_field
   static const int _uppercaseA = 0x41;
+  // ignore: unused_field
   static const int _uppercaseZ = 0x5A;
 
   static const int _leftBracket = 0x5B;
@@ -148,6 +150,7 @@
   static const String _backtickString = '`';
 
   static const int _lowercaseA = 0x61;
+  // ignore: unused_field
   static const int _lowercaseZ = 0x7A;
 
   static const int _leftBrace = 0x7B;
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index bd41381..f4da9ca 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -109,7 +109,9 @@
         CastStreamTransformer,
         checkNotNullable,
         EmptyIterator,
+        isNullFuture,
         IterableElementError,
+        nullFuture,
         printToZone,
         printToConsole,
         Since,
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 117465c..bb942d9 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -515,7 +515,7 @@
       controller
         ..onCancel = () {
           timer.cancel();
-          return Zone._current._nullFuture;
+          return nullFuture;
         }
         ..onPause = () {
           watch.stop();
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 1f34d76..2d381c5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -590,7 +590,7 @@
   Future<void> _ensureDoneFuture() =>
       _doneFuture ??
       (_isCanceled
-          ? Zone._current._nullFuture as Future<void>
+          ? nullFuture as Future<void>
           : _doneFuture = _Future<void>());
 
   /// Send or enqueue a data event.
@@ -922,7 +922,7 @@
     var cancel = addSubscription.cancel();
     if (cancel == null) {
       addStreamFuture._asyncComplete(null);
-      return Zone._current._nullFuture;
+      return nullFuture;
     }
     return cancel.whenComplete(() {
       addStreamFuture._asyncComplete(null);
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index b5a40cb..9065c46 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -197,7 +197,7 @@
     if (!_isCanceled) {
       _cancel();
     }
-    return _cancelFuture ?? Zone._current._nullFuture;
+    return _cancelFuture ?? nullFuture;
   }
 
   Future<E> asFuture<E>([E? futureValue]) {
@@ -217,7 +217,7 @@
     };
     _onError = (Object error, StackTrace stackTrace) {
       Future cancelFuture = cancel();
-      if (!identical(Zone._current._nullFuture, cancelFuture)) {
+      if (!isNullFuture(Zone._current, cancelFuture)) {
         cancelFuture.whenComplete(() {
           result._completeError(error, stackTrace);
         });
@@ -365,8 +365,7 @@
       _state |= _STATE_WAIT_FOR_CANCEL;
       _cancel();
       var cancelFuture = _cancelFuture;
-      if (cancelFuture != null &&
-          !identical(Zone._current._nullFuture, cancelFuture)) {
+      if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
         cancelFuture.whenComplete(sendError);
       } else {
         sendError();
@@ -395,8 +394,7 @@
     _cancel();
     _state |= _STATE_WAIT_FOR_CANCEL;
     var cancelFuture = _cancelFuture;
-    if (cancelFuture != null &&
-        !identical(Zone._current._nullFuture, cancelFuture)) {
+    if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
       cancelFuture.whenComplete(sendDone);
     } else {
       sendDone();
@@ -672,7 +670,7 @@
     }
   }
 
-  Future cancel() => Zone._current._nullFuture;
+  Future cancel() => nullFuture;
 
   Future<E> asFuture<E>([E? futureValue]) {
     E resultValue;
@@ -819,7 +817,7 @@
 
   Future cancel() {
     _stream._cancelSubscription();
-    return Zone._current._nullFuture;
+    return nullFuture;
   }
 
   bool get isPaused {
@@ -963,7 +961,7 @@
       }
       return subscription.cancel();
     }
-    return Zone._current._nullFuture;
+    return nullFuture;
   }
 
   void _onData(T data) {
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 2caa84b..78ad675 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -26,8 +26,7 @@
 void _cancelAndError(StreamSubscription subscription, _Future future,
     Object error, StackTrace stackTrace) {
   var cancelFuture = subscription.cancel();
-  if (cancelFuture != null &&
-      !identical(Zone._current._nullFuture, cancelFuture)) {
+  if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
     cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
   } else {
     future._completeError(error, stackTrace);
@@ -56,8 +55,7 @@
   before completing with a value. */
 void _cancelAndValue(StreamSubscription subscription, _Future future, value) {
   var cancelFuture = subscription.cancel();
-  if (cancelFuture != null &&
-      !identical(Zone._current._nullFuture, cancelFuture)) {
+  if (cancelFuture != null && !isNullFuture(Zone._current, cancelFuture)) {
     cancelFuture.whenComplete(() => future._complete(value));
   } else {
     future._complete(value);
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 42e0c76..b9bcd19 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -1078,28 +1078,6 @@
           implZone, e, identical(error, e) ? stackTrace : s);
     }
   }
-
-  /// A reusable `null`-valued future per zone used by `dart:async`.
-  ///
-  /// **DO NOT USE.**
-  ///
-  /// This future is used in situations where a future is expected,
-  /// but no asynchronous computation actually happens,
-  /// like cancelling a stream from a controller with no `onCancel` callback.
-  /// *Some code depends on recognizing this future in order to react
-  /// synchronously.*
-  /// It does so to avoid changing event interleaving during the null safety
-  /// migration where, for example, the [StreamSubscription.cancel] method
-  /// stopped being able to return `null`.
-  /// The code that would be broken by such a timing change is fragile,
-  /// but we are not able to simply change it.
-  /// For better or worse, code depends on the precise timing
-  /// that our libraries have so far exhibited.
-  ///
-  /// This future will be removed again if we can ever do so.
-  /// Do not use it for anything other than preserving timing
-  /// during the null safety migration.
-  _Future<Null> get _nullFuture;
 }
 
 class _CustomZone extends _Zone {
@@ -1127,9 +1105,6 @@
   /// The parent zone.
   final _Zone parent;
 
-  /// Cached value for [_nullFuture];
-  _Future<Null>? _nullFutureCache;
-
   /// The zone's scoped value declaration map.
   ///
   /// This is always a [HashMap].
@@ -1221,18 +1196,6 @@
   /// parent's error-zone.
   Zone get errorZone => _handleUncaughtError.zone;
 
-  _Future<Null> get _nullFuture {
-    _Future<Null>? result = _nullFutureCache;
-    if (result != null) return result;
-    // We only care about the zone of the null future
-    // because of the zone it schedules microtasks in.
-    var microtaskZone = _scheduleMicrotask.zone;
-    if (!identical(microtaskZone, this)) {
-      return _nullFutureCache = microtaskZone._nullFuture;
-    }
-    return _nullFutureCache = _Future<Null>.value(null);
-  }
-
   void runGuarded(void f()) {
     try {
       run(f);
@@ -1546,8 +1509,6 @@
 }
 
 class _RootZone extends _Zone {
-  static final _nullFutureCache = _Future<Null>.zoneValue(null, _rootZone);
-
   const _RootZone();
 
   _ZoneFunction<RunHandler> get _run =>
@@ -1586,8 +1547,6 @@
   // The parent zone.
   _Zone? get parent => null;
 
-  _Future<Null> get _nullFuture => _nullFutureCache;
-
   /// The zone's scoped value declaration map.
   ///
   /// This is always a [HashMap].
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 91224f6..671f68a 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -37302,13 +37302,13 @@
   }
 
   Future cancel() {
-    if (!_canceled) {
-      _unlisten();
-      // Clear out the target to indicate this is complete.
-      _target = null;
-      _onData = null;
-    }
-    return Future<void>.value(null);
+    if (_canceled) return nullFuture;
+
+    _unlisten();
+    // Clear out the target to indicate this is complete.
+    _target = null;
+    _onData = null;
+    return nullFuture;
   }
 
   bool get _canceled => _target == null;
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 0353c71..92f7a34 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -136,6 +136,33 @@
   return digit1 * 16 + digit2 - (digit2 & 256);
 }
 
+/// A reusable `null`-valued future per zone used by `dart:async`.
+///
+/// **DO NOT USE.**
+///
+/// This future is used in situations where a future is expected,
+/// but no asynchronous computation actually happens,
+/// like cancelling a stream from a controller with no `onCancel` callback.
+/// *Some code depends on recognizing this future in order to react
+/// synchronously.*
+/// It does so to avoid changing event interleaving during the null safety
+/// migration where, for example, the [StreamSubscription.cancel] method
+/// stopped being able to return `null`.
+/// The code that would be broken by such a timing change is fragile,
+/// but we are not able to simply change it.
+/// For better or worse, code depends on the precise timing that our libraries
+/// have so far exhibited.
+///
+/// This future will be removed again if we can ever do so.
+/// Do not use it for anything other than preserving timing
+/// during the null safety migration.
+Future<Null> get nullFuture =>
+    _nullFutures[Zone.current] ??= Future<Null>.value(null);
+
+/// Whether [future] is the null future of the current zone.
+bool isNullFuture(Zone zone, Future future) =>
+    identical(_nullFutures[zone], future);
+
 final Expando<Future<Null>> _nullFutures = Expando<Future<Null>>();
 
 /// A default hash function used by the platform in various places.
diff --git a/tests/lib/async/null_future_zone_test.dart b/tests/lib/async/null_future_zone_test.dart
index 34201e7..c74554b 100644
--- a/tests/lib/async/null_future_zone_test.dart
+++ b/tests/lib/async/null_future_zone_test.dart
@@ -16,6 +16,7 @@
 
     bool nullFutureZoneUsed = false;
     runZoned(() {
+      // Known code that exposes the special "nullFuture".
       nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
     }, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
         (Zone self, ZoneDelegate parent, Zone zone, void f()) {
diff --git a/tests/lib/isolate/package_resolve_test.dart b/tests/lib/isolate/package_resolve_test.dart
index 3199de7..22740d9 100644
--- a/tests/lib/isolate/package_resolve_test.dart
+++ b/tests/lib/isolate/package_resolve_test.dart
@@ -8,11 +8,6 @@
 final packageUriToResolve = "package:foo/bar.dart";
 final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
 
-final dotPackages = """
-# This is the content of a .packages file.
-foo:file:///no/such/directory/lib/
-""";
-
 final packageConfigJson = """
 {
   "configVersion": 2,
@@ -32,7 +27,6 @@
     testPackageResolution(port);
     return;
   }
-  await runTest(dotPackages);
   await runTest(packageConfigJson);
 }
 
diff --git a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index 3199de7..22740d9 100644
--- a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -8,11 +8,6 @@
 final packageUriToResolve = "package:foo/bar.dart";
 final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
 
-final dotPackages = """
-# This is the content of a .packages file.
-foo:file:///no/such/directory/lib/
-""";
-
 final packageConfigJson = """
 {
   "configVersion": 2,
@@ -32,7 +27,6 @@
     testPackageResolution(port);
     return;
   }
-  await runTest(dotPackages);
   await runTest(packageConfigJson);
 }
 
diff --git a/tests/lib/isolate/spawn_uri__package_uri__test.dart b/tests/lib/isolate/spawn_uri__package_uri__test.dart
index b212874..b502a5f 100644
--- a/tests/lib/isolate/spawn_uri__package_uri__test.dart
+++ b/tests/lib/isolate/spawn_uri__package_uri__test.dart
@@ -21,8 +21,6 @@
       print('TEST spawnWithPackageConfig = $spawnWithPackageConfig ');
       final bool checkForResolveUri =
           runWithPackagesArg || !spawnWithPackageConfig;
-      futures.add(runDotPackagesTest(
-          runWithPackagesArg, spawnWithPackageConfig, checkForResolveUri));
       for (final optionalPackageUri in const [true, false]) {
         print('TEST optionalPackageUri = $optionalPackageUri');
         futures.add(runPackageConfigTest(runWithPackagesArg,
@@ -42,41 +40,6 @@
   }, spawnWithArg, optionalPackageUri, checkForResolveUri);
 }
 
-Future runDotPackagesTest(
-    bool withPackagesArg, bool spawnWithArg, bool checkForResolveUri) async {
-  await withApplicationDirAndDotPackages(
-      (String tempDir, String dotPackagesFile, String mainFile) async {
-    final args = [
-      if (withPackagesArg) '--packages=$dotPackagesFile',
-      mainFile,
-    ];
-    await run(executable, args);
-  }, spawnWithArg, checkForResolveUri);
-}
-
-Future withApplicationDirAndDotPackages(
-    Future fn(String tempDir, String packagesDir, String mainFile),
-    bool spawnWithArg,
-    bool checkForResolveUri) async {
-  await withTempDir((String tempDir) async {
-    // Setup ".packages"
-    final dotPackagesFile =
-        path.join(tempDir, spawnWithArg ? 'baz.packages' : '.packages');
-    await File(dotPackagesFile).writeAsString(buildDotPackages('foo'));
-
-    final mainFile = path.join(tempDir, 'main.dart');
-    final childIsolateFile = path.join(tempDir, 'child_isolate.dart');
-    final importUri = 'package:foo/child_isolate.dart';
-    await File(childIsolateFile).writeAsString(buildChildIsolate());
-    await File(mainFile).writeAsString(buildMainIsolate(
-        importUri,
-        spawnWithArg ? dotPackagesFile : null,
-        checkForResolveUri ? childIsolateFile : null));
-
-    await fn(tempDir, dotPackagesFile, mainFile);
-  });
-}
-
 Future withApplicationDirAndDotDartToolPackageConfig(
     Future fn(String tempDir, String packageJson, String mainFile),
     bool spawnWithArg,
diff --git a/tests/lib_2/isolate/package_resolve_test.dart b/tests/lib_2/isolate/package_resolve_test.dart
index 057c5df..b315b40 100644
--- a/tests/lib_2/isolate/package_resolve_test.dart
+++ b/tests/lib_2/isolate/package_resolve_test.dart
@@ -10,11 +10,6 @@
 final packageUriToResolve = "package:foo/bar.dart";
 final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
 
-final dotPackages = """
-# This is the content of a .packages file.
-foo:file:///no/such/directory/lib/
-""";
-
 final packageConfigJson = """
 {
   "configVersion": 2,
@@ -34,7 +29,6 @@
     testPackageResolution(port);
     return;
   }
-  await runTest(dotPackages);
   await runTest(packageConfigJson);
 }
 
diff --git a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index 057c5df..b315b40 100644
--- a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -10,11 +10,6 @@
 final packageUriToResolve = "package:foo/bar.dart";
 final packageResolvedUri = "file:///no/such/directory/lib/bar.dart";
 
-final dotPackages = """
-# This is the content of a .packages file.
-foo:file:///no/such/directory/lib/
-""";
-
 final packageConfigJson = """
 {
   "configVersion": 2,
@@ -34,7 +29,6 @@
     testPackageResolution(port);
     return;
   }
-  await runTest(dotPackages);
   await runTest(packageConfigJson);
 }
 
diff --git a/tests/lib_2/isolate/scenarios/package_relative_root/.dart_tool/package_config.json b/tests/lib_2/isolate/scenarios/package_relative_root/.dart_tool/package_config.json
new file mode 100644
index 0000000..899389f
--- /dev/null
+++ b/tests/lib_2/isolate/scenarios/package_relative_root/.dart_tool/package_config.json
@@ -0,0 +1,13 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../packages/foo"
+    },
+    {
+      "name": "bar",
+      "rootUri": "../packages/bar"
+    }
+  ]
+}
diff --git a/tests/lib_2/isolate/scenarios/package_relative_root/.packages b/tests/lib_2/isolate/scenarios/package_relative_root/.packages
deleted file mode 100644
index 32bc5eee..0000000
--- a/tests/lib_2/isolate/scenarios/package_relative_root/.packages
+++ /dev/null
@@ -1,2 +0,0 @@
-foo:packages/foo
-bar:packages/bar
diff --git a/tests/lib_2/isolate/scenarios/package_relative_spec/.dart_tool/package_config.json b/tests/lib_2/isolate/scenarios/package_relative_spec/.dart_tool/package_config.json
new file mode 100644
index 0000000..96d8ed7
--- /dev/null
+++ b/tests/lib_2/isolate/scenarios/package_relative_spec/.dart_tool/package_config.json
@@ -0,0 +1,13 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../foo_package"
+    },
+    {
+      "name": "bar",
+      "rootUri": "../bar1_package"
+    }
+  ]
+}
diff --git a/tests/lib_2/isolate/scenarios/package_relative_spec/.packages b/tests/lib_2/isolate/scenarios/package_relative_spec/.packages
deleted file mode 100644
index d7a0d92..0000000
--- a/tests/lib_2/isolate/scenarios/package_relative_spec/.packages
+++ /dev/null
@@ -1,4 +0,0 @@
-# This is the package spec for the spawning isolate.
-
-foo:foo_package/
-bar:bar1_package/
diff --git a/tests/lib_2/isolate/scenarios/package_relative_spec/bar1_package/package.config b/tests/lib_2/isolate/scenarios/package_relative_spec/bar1_package/package.config
index b580fe3..b72b9b3 100644
--- a/tests/lib_2/isolate/scenarios/package_relative_spec/bar1_package/package.config
+++ b/tests/lib_2/isolate/scenarios/package_relative_spec/bar1_package/package.config
@@ -1,4 +1,13 @@
-# This is the package spec for the spawned isolate.
-
-foo:../foo_package/
-bar:../bar2_package/
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../foo_package"
+    },
+    {
+      "name": "bar",
+      "rootUri": "../bar2_package"
+    }
+  ]
+}
diff --git a/tests/lib_2/isolate/scenarios/short_package/.dart_tool/package_config.json b/tests/lib_2/isolate/scenarios/short_package/.dart_tool/package_config.json
new file mode 100644
index 0000000..a806459
--- /dev/null
+++ b/tests/lib_2/isolate/scenarios/short_package/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "flu",
+      "rootUri": "../flu_package"
+    }
+  ]
+}
diff --git a/tests/lib_2/isolate/scenarios/short_package/.packages b/tests/lib_2/isolate/scenarios/short_package/.packages
deleted file mode 100644
index 324934c..0000000
--- a/tests/lib_2/isolate/scenarios/short_package/.packages
+++ /dev/null
@@ -1 +0,0 @@
-flu:flu_package/
diff --git a/tests/lib_2/isolate/spawn_uri__package_uri__test.dart b/tests/lib_2/isolate/spawn_uri__package_uri__test.dart
index 23d4707..c06ea40 100644
--- a/tests/lib_2/isolate/spawn_uri__package_uri__test.dart
+++ b/tests/lib_2/isolate/spawn_uri__package_uri__test.dart
@@ -23,8 +23,6 @@
       print('TEST spawnWithPackageConfig = $spawnWithPackageConfig ');
       final bool checkForResolveUri =
           runWithPackagesArg || !spawnWithPackageConfig;
-      futures.add(runDotPackagesTest(
-          runWithPackagesArg, spawnWithPackageConfig, checkForResolveUri));
       for (final optionalPackageUri in const [true, false]) {
         print('TEST optionalPackageUri = $optionalPackageUri');
         futures.add(runPackageConfigTest(runWithPackagesArg,
@@ -44,41 +42,6 @@
   }, spawnWithArg, optionalPackageUri, checkForResolveUri);
 }
 
-Future runDotPackagesTest(
-    bool withPackagesArg, bool spawnWithArg, bool checkForResolveUri) async {
-  await withApplicationDirAndDotPackages(
-      (String tempDir, String dotPackagesFile, String mainFile) async {
-    final args = [
-      if (withPackagesArg) '--packages=$dotPackagesFile',
-      mainFile,
-    ];
-    await run(executable, args);
-  }, spawnWithArg, checkForResolveUri);
-}
-
-Future withApplicationDirAndDotPackages(
-    Future fn(String tempDir, String packagesDir, String mainFile),
-    bool spawnWithArg,
-    bool checkForResolveUri) async {
-  await withTempDir((String tempDir) async {
-    // Setup ".packages"
-    final dotPackagesFile =
-        path.join(tempDir, spawnWithArg ? 'baz.packages' : '.packages');
-    await File(dotPackagesFile).writeAsString(buildDotPackages('foo'));
-
-    final mainFile = path.join(tempDir, 'main.dart');
-    final childIsolateFile = path.join(tempDir, 'child_isolate.dart');
-    final importUri = 'package:foo/child_isolate.dart';
-    await File(childIsolateFile).writeAsString(buildChildIsolate());
-    await File(mainFile).writeAsString(buildMainIsolate(
-        importUri,
-        spawnWithArg ? dotPackagesFile : null,
-        checkForResolveUri ? childIsolateFile : null));
-
-    await fn(tempDir, dotPackagesFile, mainFile);
-  });
-}
-
 Future withApplicationDirAndDotDartToolPackageConfig(
     Future fn(String tempDir, String packageJson, String mainFile),
     bool spawnWithArg,
diff --git a/tests/standalone/package/scenarios/empty_packages_file/.dart_tool/package_config.json b/tests/standalone/package/scenarios/empty_packages_file/.dart_tool/package_config.json
new file mode 100644
index 0000000..a774220
--- /dev/null
+++ b/tests/standalone/package/scenarios/empty_packages_file/.dart_tool/package_config.json
@@ -0,0 +1,4 @@
+{
+  "configVersion": 2,
+  "packages": []
+}
diff --git a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
index af76de8..ee85f40 100644
--- a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
+++ b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Packages=.packages
+// Packages=.dart_tool/package_config.json
 
 // We expect this to not cause any errors. An empty packages file is valid,
 // you should only run into problems if you try to resolve a package import.
diff --git a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
index fbde79f..93a1612 100644
--- a/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
+++ b/tests/standalone/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Packages=.packages
+// Packages=.dart_tool/package_config.json
 
 library empty_packages_file_option_test;
 
diff --git a/tests/standalone/package/scenarios/invalid/invalid_package_name.packages b/tests/standalone/package/scenarios/invalid/invalid_package_name.packages
index d74d280..664189c 100644
--- a/tests/standalone/package/scenarios/invalid/invalid_package_name.packages
+++ b/tests/standalone/package/scenarios/invalid/invalid_package_name.packages
@@ -1,2 +1,13 @@
-..:nonexistent/
-foo:foo/
\ No newline at end of file
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "..",
+      "rootUri": "nonexistent"
+    },
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    }
+  ]
+}
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines.packages b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines.packages
index e81099e..a8d6618 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines.packages
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_lines.packages
@@ -1,11 +1,18 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
 
 
+"name": "foo",
 
 
-foo:foo/
+"rootUri":"foo"},{"name":
 
 
-bar:bar/
+"bar"
+
+, "rootUri":"bar"},
 
 
 
@@ -13,8 +20,4 @@
 
 
 
-
-baz:baz/
-
-
-
+{"name": "baz", "rootUri": "baz"}]}
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
index 0152a79..57c7d4e 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
@@ -1 +1,9 @@
-foo:
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": ""
+    }
+  ]
+}
diff --git a/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages b/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
index c3d3e75..e5e63a7 100644
--- a/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
+++ b/tests/standalone/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
@@ -1,3 +1,17 @@
-foo:foo/
-bar:bar/

-baz:baz/
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    },
+    {
+      "name": "bar",
+      "rootUri": "bar"

+    },
+    {
+      "name": "baz",
+      "rootUri": "baz"
+    }
+  ]
+}
diff --git a/tests/standalone/package/scenarios/packages_option_only/sub/.packages b/tests/standalone/package/scenarios/packages_option_only/sub/.packages
index 17ae735..46389c5 100644
--- a/tests/standalone/package/scenarios/packages_option_only/sub/.packages
+++ b/tests/standalone/package/scenarios/packages_option_only/sub/.packages
@@ -1 +1,9 @@
-foo:foo/
\ No newline at end of file
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    }
+  ]
+}
diff --git a/tests/standalone_2/http_launch_data/.dart_tool/package_config.json b/tests/standalone_2/http_launch_data/.dart_tool/package_config.json
new file mode 100644
index 0000000..6ff2893
--- /dev/null
+++ b/tests/standalone_2/http_launch_data/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "simple",
+      "rootUri": "../the_packages/simple"
+    }
+  ]
+}
diff --git a/tests/standalone_2/http_launch_data/.packages b/tests/standalone_2/http_launch_data/.packages
deleted file mode 100644
index 4d7ff27..0000000
--- a/tests/standalone_2/http_launch_data/.packages
+++ /dev/null
@@ -1 +0,0 @@
-simple:the_packages/simple
diff --git a/tests/standalone_2/http_launch_test.dart b/tests/standalone_2/http_launch_test.dart
index 8a6d37be..15b7eda 100644
--- a/tests/standalone_2/http_launch_test.dart
+++ b/tests/standalone_2/http_launch_test.dart
@@ -9,7 +9,7 @@
 // OtherResources=http_launch_data/http_launch_main.dart
 // OtherResources=http_launch_data/http_spawn_main.dart
 // OtherResources=http_launch_data/the_packages/simple/simple.dart
-// OtherResources=http_launch_data/.packages
+// OtherResources=http_launch_data/.dart_tool/package_config.json
 //
 // Test:
 //   *) Launching a script fetched over HTTP.
diff --git a/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/.dart_tool/package_config.json b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/.dart_tool/package_config.json
new file mode 100644
index 0000000..fe79168
--- /dev/null
+++ b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/.dart_tool/package_config.json
@@ -0,0 +1,10 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../foo2"
+    }
+  ]
+}
+
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/.packages b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/.packages
similarity index 100%
rename from tests/standalone_2/package/scenarios/both_dir_and_file/.packages
rename to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/.packages
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/both_dir_dot_packages_and_package_config_noimports_test.dart
similarity index 79%
rename from tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart
rename to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/both_dir_dot_packages_and_package_config_noimports_test.dart
index 03fa700..6732641 100644
--- a/tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart
+++ b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/both_dir_dot_packages_and_package_config_noimports_test.dart
@@ -6,6 +6,6 @@
 
 // Packages=none
 
-library both_dir_and_file_noimports_test;
+library both_dir_dot_packages_and_package_config_noimports_test;
 
 main() {}
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/foo/foo.dart
similarity index 76%
copy from tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart
copy to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/foo/foo.dart
index 03fa700..7b46a78 100644
--- a/tests/standalone_2/package/scenarios/both_dir_and_file/both_dir_and_file_noimports_test.dart
+++ b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/foo/foo.dart
@@ -4,8 +4,6 @@
 
 // @dart = 2.9
 
-// Packages=none
+library foo;
 
-library both_dir_and_file_noimports_test;
-
-main() {}
+String bar = 'dot packages';
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/foo/foo.dart b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/foo2/foo.dart
similarity index 100%
rename from tests/standalone_2/package/scenarios/both_dir_and_file/foo/foo.dart
rename to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/foo2/foo.dart
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/packages/foo/foo.dart b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/packages/foo/foo.dart
similarity index 100%
rename from tests/standalone_2/package/scenarios/both_dir_and_file/packages/foo/foo.dart
rename to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/packages/foo/foo.dart
diff --git a/tests/standalone_2/package/scenarios/both_dir_and_file/prefers_packages_file_test.dart b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/prefers_package_config_file_test.dart
similarity index 89%
rename from tests/standalone_2/package/scenarios/both_dir_and_file/prefers_packages_file_test.dart
rename to tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/prefers_package_config_file_test.dart
index fb5d6db..2dac68a 100644
--- a/tests/standalone_2/package/scenarios/both_dir_and_file/prefers_packages_file_test.dart
+++ b/tests/standalone_2/package/scenarios/both_dir_dot_packages_and_package_config/prefers_package_config_file_test.dart
@@ -6,7 +6,7 @@
 
 // Packages=none
 
-library prefers_packages_file_test;
+library prefers_package_config_file_test;
 
 import 'package:foo/foo.dart' as foo;
 
diff --git a/tests/standalone_2/package/scenarios/empty_packages_file/.dart_tool/package_config.json b/tests/standalone_2/package/scenarios/empty_packages_file/.dart_tool/package_config.json
new file mode 100644
index 0000000..a774220
--- /dev/null
+++ b/tests/standalone_2/package/scenarios/empty_packages_file/.dart_tool/package_config.json
@@ -0,0 +1,4 @@
+{
+  "configVersion": 2,
+  "packages": []
+}
diff --git a/tests/standalone_2/package/scenarios/empty_packages_file/.packages b/tests/standalone_2/package/scenarios/empty_packages_file/.packages
deleted file mode 100644
index e69de29..0000000
--- a/tests/standalone_2/package/scenarios/empty_packages_file/.packages
+++ /dev/null
diff --git a/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart b/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
index d539707..ffbc43a 100644
--- a/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
+++ b/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_noimports_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// Packages=.packages
+// Packages=.dart_tool/package_config.json
 
 // We expect this to not cause any errors. An empty packages file is valid,
 // you should only run into problems if you try to resolve a package import.
diff --git a/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart b/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
index 708d8bb..9fd360b 100644
--- a/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
+++ b/tests/standalone_2/package/scenarios/empty_packages_file/empty_packages_file_option_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// Packages=.packages
+// Packages=.dart_tool/package_config.json
 
 library empty_packages_file_option_test;
 
diff --git a/tests/standalone_2/package/scenarios/invalid/invalid_package_name.packages b/tests/standalone_2/package/scenarios/invalid/invalid_package_name.packages
index d74d280..664189c 100644
--- a/tests/standalone_2/package/scenarios/invalid/invalid_package_name.packages
+++ b/tests/standalone_2/package/scenarios/invalid/invalid_package_name.packages
@@ -1,2 +1,13 @@
-..:nonexistent/
-foo:foo/
\ No newline at end of file
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "..",
+      "rootUri": "nonexistent"
+    },
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    }
+  ]
+}
diff --git a/tests/standalone_2/package/scenarios/packages_file_in_parent/.dart_tool/package_config.json b/tests/standalone_2/package/scenarios/packages_file_in_parent/.dart_tool/package_config.json
new file mode 100644
index 0000000..5eeda62
--- /dev/null
+++ b/tests/standalone_2/package/scenarios/packages_file_in_parent/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../foo"
+    }
+  ]
+}
diff --git a/tests/standalone_2/package/scenarios/packages_file_in_parent/.packages b/tests/standalone_2/package/scenarios/packages_file_in_parent/.packages
deleted file mode 100644
index 17ae735..0000000
--- a/tests/standalone_2/package/scenarios/packages_file_in_parent/.packages
+++ /dev/null
@@ -1 +0,0 @@
-foo:foo/
\ No newline at end of file
diff --git a/tests/standalone_2/package/scenarios/packages_file_only/.dart_tool/package_config.json b/tests/standalone_2/package/scenarios/packages_file_only/.dart_tool/package_config.json
new file mode 100644
index 0000000..5eeda62
--- /dev/null
+++ b/tests/standalone_2/package/scenarios/packages_file_only/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "../foo"
+    }
+  ]
+}
diff --git a/tests/standalone_2/package/scenarios/packages_file_only/.packages b/tests/standalone_2/package/scenarios/packages_file_only/.packages
deleted file mode 100644
index 17ae735..0000000
--- a/tests/standalone_2/package/scenarios/packages_file_only/.packages
+++ /dev/null
@@ -1 +0,0 @@
-foo:foo/
\ No newline at end of file
diff --git a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_lines.packages b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_lines.packages
index e81099e..a8d6618 100644
--- a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_lines.packages
+++ b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_lines.packages
@@ -1,11 +1,18 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
 
 
+"name": "foo",
 
 
-foo:foo/
+"rootUri":"foo"},{"name":
 
 
-bar:bar/
+"bar"
+
+, "rootUri":"bar"},
 
 
 
@@ -13,8 +20,4 @@
 
 
 
-
-baz:baz/
-
-
-
+{"name": "baz", "rootUri": "baz"}]}
diff --git a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
index 0152a79..57c7d4e 100644
--- a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
+++ b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/empty_package_dir.packages
@@ -1 +1,9 @@
-foo:
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": ""
+    }
+  ]
+}
diff --git a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
index c3d3e75..e5e63a7 100644
--- a/tests/standalone_2/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
+++ b/tests/standalone_2/package/scenarios/packages_file_strange_formatting/mixed_line_ends.packages
@@ -1,3 +1,17 @@
-foo:foo/
-bar:bar/

-baz:baz/
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    },
+    {
+      "name": "bar",
+      "rootUri": "bar"

+    },
+    {
+      "name": "baz",
+      "rootUri": "baz"
+    }
+  ]
+}
diff --git a/tests/standalone_2/package/scenarios/packages_option_only/sub/.packages b/tests/standalone_2/package/scenarios/packages_option_only/sub/.packages
index 17ae735..46389c5 100644
--- a/tests/standalone_2/package/scenarios/packages_option_only/sub/.packages
+++ b/tests/standalone_2/package/scenarios/packages_option_only/sub/.packages
@@ -1 +1,9 @@
-foo:foo/
\ No newline at end of file
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "foo",
+      "rootUri": "foo"
+    }
+  ]
+}
diff --git a/tools/VERSION b/tools/VERSION
index cc2dd56..5671960 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 224
+PRERELEASE 225
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 1ae6268..90b19aa 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -248,13 +248,13 @@
   }
 
   Future cancel() {
-    if (!_canceled) {
-      _unlisten();
-      // Clear out the target to indicate this is complete.
-      _target = null;
-      _onData = null;
-    }
-    return Future<void>.value(null);
+    if (_canceled) return nullFuture;
+
+    _unlisten();
+    // Clear out the target to indicate this is complete.
+    _target = null;
+    _onData = null;
+    return nullFuture;
   }
 
   bool get _canceled => _target == null;