[dart2js] Migrate js_emitter/metadata_collector.dart

Change-Id: I5494de7b1475bed8a3a5f9fcd9154d7d457803c1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251181
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
index a0f4161..31de9ed 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -20,6 +20,7 @@
 import 'namer.dart';
 import 'native_data.dart';
 import 'runtime_types_codegen.dart' show RuntimeTypesSubstitutions;
+import 'runtime_types_new_interfaces.dart' as interfaces;
 
 class RecipeEncoding {
   final jsAst.Literal recipe;
@@ -28,13 +29,16 @@
   const RecipeEncoding(this.recipe, this.typeVariables);
 }
 
-abstract class RecipeEncoder {
+abstract class RecipeEncoder implements interfaces.RecipeEncoder {
   /// Returns a [RecipeEncoding] representing the given [recipe] to be
   /// evaluated against a type environment with shape [structure].
   RecipeEncoding encodeRecipe(ModularEmitter emitter,
       TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);
 
-  jsAst.Literal encodeGroundRecipe(ModularEmitter emitter, TypeRecipe recipe);
+  @override
+  // TODO(48820): Remove covariant when ModularEmitter is migrated.
+  jsAst.Literal encodeGroundRecipe(
+      covariant ModularEmitter emitter, TypeRecipe recipe);
 
   /// Returns a [jsAst.Literal] representing [supertypeArgument] to be evaluated
   /// against a [FullTypeEnvironmentStructure] representing [declaringType]. Any
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart
new file mode 100644
index 0000000..2b65d05
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart
@@ -0,0 +1,7 @@
+import '../js_emitter/code_emitter_task_interfaces.dart';
+import '../js_model/type_recipe.dart';
+import '../js/js.dart' as jsAst;
+
+abstract class RecipeEncoder {
+  jsAst.Literal encodeGroundRecipe(ModularEmitter emitter, TypeRecipe recipe);
+}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 5932c85..790e988 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -26,6 +26,7 @@
 import 'startup_emitter/emitter.dart' as startup_js_emitter;
 import 'startup_emitter/fragment_merger.dart';
 
+import 'code_emitter_task_interfaces.dart' as interfaces;
 import 'metadata_collector.dart' show MetadataCollector;
 import 'model.dart';
 import 'native_emitter.dart' show NativeEmitter;
@@ -155,7 +156,7 @@
 ///
 /// Note that the emission phase is not itself modular but performed on
 /// the closed world computed by the codegen enqueuer.
-abstract class ModularEmitter {
+abstract class ModularEmitter implements interfaces.ModularEmitter {
   /// Returns the JS prototype of the given class [e].
   jsAst.Expression prototypeAccess(ClassEntity e);
 
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart
new file mode 100644
index 0000000..3071fdf
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart
@@ -0,0 +1,5 @@
+// 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.
+
+abstract class ModularEmitter {}
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index ae10aaa..76c71d4 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.10
-
 library dart2js.js_emitter.metadata_collector;
 
 import 'package:js_ast/src/precedence.dart' as js_precedence;
@@ -13,10 +11,10 @@
 
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
-import '../js_backend/runtime_types_new.dart' show RecipeEncoder;
+import '../js_backend/runtime_types_new_interfaces.dart' show RecipeEncoder;
 import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 
-import 'code_emitter_task.dart' show Emitter;
+import 'code_emitter_task_interfaces.dart' show ModularEmitter;
 
 /// Represents an entry's position in one of the global metadata arrays.
 ///
@@ -76,17 +74,15 @@
 }
 
 class _MetadataList extends jsAst.DeferredExpression {
-  jsAst.Expression _value;
+  late final jsAst.Expression _value;
 
   void setExpression(jsAst.Expression value) {
-    assert(_value == null);
     assert(value.precedenceLevel == this.precedenceLevel);
     _value = value;
   }
 
   @override
   jsAst.Expression get value {
-    assert(_value != null);
     return _value;
   }
 
@@ -96,7 +92,7 @@
 
 class MetadataCollector implements jsAst.TokenFinalizer {
   final DiagnosticReporter reporter;
-  final Emitter _emitter;
+  final ModularEmitter _emitter;
   final RecipeEncoder _rtiRecipeEncoder;
 
   /// A map used to canonicalize the entries of metadata.
@@ -143,7 +139,7 @@
     }
   }
 
-  jsAst.Expression reifyType(DartType type, OutputUnit outputUnit) {
+  jsAst.Expression? reifyType(DartType type, OutputUnit outputUnit) {
     return _addTypeInOutputUnit(type, outputUnit);
   }
 
@@ -153,19 +149,11 @@
   }
 
   jsAst.Expression _addTypeInOutputUnit(DartType type, OutputUnit outputUnit) {
-    _typesMap[outputUnit] ??= {};
-    BoundMetadataEntry metadataEntry;
-
-    if (_typesMap[outputUnit].containsKey(type)) {
-      metadataEntry = _typesMap[outputUnit][type].single;
-    } else {
-      _typesMap[outputUnit].putIfAbsent(type, () {
-        metadataEntry =
-            BoundMetadataEntry(_computeTypeRepresentationNewRti(type));
-        return [metadataEntry];
-      });
-    }
-    return metadataEntry;
+    final typeMap = _typesMap[outputUnit] ??= {};
+    final metadataEntryList = (typeMap[type] ??= [
+      BoundMetadataEntry(_computeTypeRepresentationNewRti(type))
+    ]);
+    return metadataEntryList.single;
   }
 
   @override
@@ -194,14 +182,13 @@
         entry.finalize(count++);
       }
 
-      List<jsAst.Node> values =
-          entries.map((BoundMetadataEntry e) => e.entry).toList();
+      final values = entries.map((BoundMetadataEntry e) => e.entry).toList();
 
       return jsAst.ArrayInitializer(values);
     }
 
     _typesTokens.forEach((OutputUnit outputUnit, _MetadataList token) {
-      Map<DartType, List<BoundMetadataEntry>> typesMap = _typesMap[outputUnit];
+      final typesMap = _typesMap[outputUnit];
       if (typesMap != null) {
         typesMap.values.forEach(countTokensInTypes);
         token.setExpression(finalizeMap(typesMap));