[dart2js] Steps to prepare js_model/env.dart for migration

env.dart and closure.dart have a circular dependency that is a bit
hard to break, but this is a step towards starting migrating them.
It may be worth migrating the cycle of env and closure together
in one go.

That said, the definitions moved from closure.dart to
element_map_migrated.dart (e.g. ClassDefinition) seem to match
other definitions already in the latter file
(e.g. MemberDefinition)

Change-Id: Ifa8114b992e75ec6662db702fa1dd51b31112276
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/252964
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 5cd2856..4a05706 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -987,42 +987,6 @@
   }
 }
 
-class ClosureClassDefinition implements ClassDefinition {
-  /// Tag used for identifying serialized [ClosureClassDefinition] objects in a
-  /// debugging data stream.
-  static const String tag = 'closure-class-definition';
-
-  @override
-  final SourceSpan location;
-
-  ClosureClassDefinition(this.location);
-
-  factory ClosureClassDefinition.readFromDataSource(DataSourceReader source) {
-    source.begin(tag);
-    SourceSpan location = source.readSourceSpan();
-    source.end(tag);
-    return ClosureClassDefinition(location);
-  }
-
-  @override
-  void writeToDataSink(DataSinkWriter sink) {
-    sink.writeEnum(ClassKind.closure);
-    sink.begin(tag);
-    sink.writeSourceSpan(location);
-    sink.end(tag);
-  }
-
-  @override
-  ClassKind get kind => ClassKind.closure;
-
-  @override
-  ir.Node get node =>
-      throw UnsupportedError('ClosureClassDefinition.node for $location');
-
-  @override
-  String toString() => 'ClosureClassDefinition(kind:$kind,location:$location)';
-}
-
 abstract class ClosureMemberData implements JMemberData {
   @override
   final MemberDefinition definition;
@@ -1037,7 +1001,7 @@
   }
 
   @override
-  InterfaceType getMemberThisType(JsToElementMap elementMap) {
+  InterfaceType getMemberThisType(covariant JsToElementMap elementMap) {
     return memberThisType;
   }
 }
@@ -1181,44 +1145,6 @@
       ClassTypeVariableAccess.none;
 }
 
-class RecordContainerDefinition implements ClassDefinition {
-  /// Tag used for identifying serialized [RecordContainerDefinition] objects in
-  /// a debugging data stream.
-  static const String tag = 'record-definition';
-
-  @override
-  final SourceSpan location;
-
-  RecordContainerDefinition(this.location);
-
-  factory RecordContainerDefinition.readFromDataSource(
-      DataSourceReader source) {
-    source.begin(tag);
-    SourceSpan location = source.readSourceSpan();
-    source.end(tag);
-    return RecordContainerDefinition(location);
-  }
-
-  @override
-  void writeToDataSink(DataSinkWriter sink) {
-    sink.writeEnum(ClassKind.record);
-    sink.begin(tag);
-    sink.writeSourceSpan(location);
-    sink.end(tag);
-  }
-
-  @override
-  ClassKind get kind => ClassKind.record;
-
-  @override
-  ir.Node get node =>
-      throw UnsupportedError('RecordContainerDefinition.node for $location');
-
-  @override
-  String toString() =>
-      'RecordContainerDefinition(kind:$kind,location:$location)';
-}
-
 abstract class ClosureRtiNeed {
   bool classNeedsTypeArguments(ClassEntity cls);
 
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 7350f29..75b6a58 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -19,7 +19,6 @@
 import '../js_model/class_type_variable_access.dart';
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../native/behavior.dart';
-import '../serialization/serialization.dart';
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 import '../world.dart';
@@ -36,6 +35,7 @@
   JCommonElements get commonElements;
 
   /// Access to the [DartTypes] object.
+  @override
   DartTypes get types;
 
   /// Returns the [DartType] corresponding to [type].
@@ -64,6 +64,7 @@
   Selector getSelector(ir.Expression node);
 
   /// Returns the [MemberEntity] corresponding to the member [node].
+  @override
   MemberEntity getMember(ir.Member node);
 
   /// Returns the [FunctionEntity] corresponding to the procedure [node].
@@ -102,6 +103,7 @@
   // TODO(johnniwinther,sigmund): Remove the need for [memberContext]. This is
   //  only needed because effectively constant expressions are not replaced by
   //  constant expressions during resolution.
+  @override
   ConstantValue getConstantValue(
       ir.Member memberContext, ir.Expression expression,
       {bool requireConstant = true, bool implicitNull = false});
@@ -111,6 +113,7 @@
   ///
   /// These should only appear within the defaultValues object attached to
   /// closures and tearoffs when emitting Function.apply.
+  @override
   ConstantValue getRequiredSentinelConstantValue();
 
   /// Return the [ImportEntity] corresponding to [node].
@@ -120,6 +123,7 @@
   ClassDefinition getClassDefinition(covariant ClassEntity cls);
 
   /// [ElementEnvironment] for library, class and member lookup.
+  @override
   JElementEnvironment get elementEnvironment;
 
   /// Returns the list of [DartType]s corresponding to [types].
@@ -242,81 +246,6 @@
   return null;
 }
 
-enum ClassKind {
-  regular,
-  closure,
-  // TODO(efortuna, johnniwinther): Record is not a class, but is
-  // masquerading as one currently for consistency with the old element model.
-  record,
-}
-
-/// Definition information for a [ClassEntity].
-abstract class ClassDefinition {
-  /// The kind of the defined class. This determines the semantics of [node].
-  ClassKind get kind;
-
-  /// The defining [ir.Node] for this class, if supported by its [kind].
-  ir.Node get node;
-
-  /// The canonical location of [cls]. This is used for sorting the classes
-  /// in the emitted code.
-  SourceSpan get location;
-
-  /// Deserializes a [ClassDefinition] object from [source].
-  factory ClassDefinition.readFromDataSource(DataSourceReader source) {
-    ClassKind kind = source.readEnum(ClassKind.values);
-    switch (kind) {
-      case ClassKind.regular:
-        return RegularClassDefinition.readFromDataSource(source);
-      case ClassKind.closure:
-        return ClosureClassDefinition.readFromDataSource(source);
-      case ClassKind.record:
-        return RecordContainerDefinition.readFromDataSource(source);
-    }
-    throw UnsupportedError("Unexpected ClassKind $kind");
-  }
-
-  /// Serializes this [ClassDefinition] to [sink].
-  void writeToDataSink(DataSinkWriter sink);
-}
-
-/// A class directly defined by its [ir.Class] node.
-class RegularClassDefinition implements ClassDefinition {
-  /// Tag used for identifying serialized [RegularClassDefinition] objects in a
-  /// debugging data stream.
-  static const String tag = 'regular-class-definition';
-
-  @override
-  final ir.Class node;
-
-  RegularClassDefinition(this.node);
-
-  factory RegularClassDefinition.readFromDataSource(DataSourceReader source) {
-    source.begin(tag);
-    ir.Class node = source.readClassNode();
-    source.end(tag);
-    return RegularClassDefinition(node);
-  }
-
-  @override
-  void writeToDataSink(DataSinkWriter sink) {
-    sink.writeEnum(kind);
-    sink.begin(tag);
-    sink.writeClassNode(node);
-    sink.end(tag);
-  }
-
-  @override
-  SourceSpan get location => computeSourceSpanFromTreeNode(node);
-
-  @override
-  ClassKind get kind => ClassKind.regular;
-
-  @override
-  String toString() => 'RegularClassDefinition(kind:$kind,'
-      'node:$node,location:$location)';
-}
-
 /// Returns the initializer for [field].
 ///
 /// If [field] is an instance field with a null literal initializer `null` is
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 7836deb..f005c4d 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -55,10 +55,12 @@
 import 'closure_migrated.dart' as closureMigrated;
 import 'elements.dart';
 import 'element_map.dart';
+import 'element_map_interfaces.dart' as interfaces show JsKernelToElementMap;
 import 'env.dart';
 import 'locals.dart';
 
-class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
+class JsKernelToElementMap
+    implements interfaces.JsKernelToElementMap, JsToElementMap, IrToElementMap {
   /// Tag used for identifying serialized [JsKernelToElementMap] objects in a
   /// debugging data stream.
   static const String tag = 'js-kernel-to-element-map';
diff --git a/pkg/compiler/lib/src/js_model/element_map_interfaces.dart b/pkg/compiler/lib/src/js_model/element_map_interfaces.dart
index 8016e27..7b548e09 100644
--- a/pkg/compiler/lib/src/js_model/element_map_interfaces.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_interfaces.dart
@@ -5,12 +5,24 @@
 import 'package:compiler/src/js_model/element_map_migrated.dart';
 import 'package:kernel/ast.dart' as ir;
 
+import '../common/elements.dart';
+import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/element_map.dart';
 
 // TODO(48820): Remove this interface when nnbd migration is done.
 abstract class JsToElementMap {
+  JElementEnvironment get elementEnvironment;
+  DartTypes get types;
+  ConstantValue getConstantValue(
+      ir.Member memberContext, ir.Expression expression,
+      {bool requireConstant = true, bool implicitNull = false});
   DartType getDartType(ir.DartType type);
 
+  MemberEntity getMember(ir.Member node);
   MemberDefinition getMemberDefinition(MemberEntity member);
+  ConstantValue getRequiredSentinelConstantValue();
 }
+
+abstract class JsKernelToElementMap implements JsToElementMap, IrToElementMap {}
diff --git a/pkg/compiler/lib/src/js_model/element_map_migrated.dart b/pkg/compiler/lib/src/js_model/element_map_migrated.dart
index fb5417f..1794774 100644
--- a/pkg/compiler/lib/src/js_model/element_map_migrated.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_migrated.dart
@@ -340,3 +340,151 @@
   }
   failedAt(function, "Unexpected function definition $definition.");
 }
+
+enum ClassKind {
+  regular,
+  closure,
+  // TODO(efortuna, johnniwinther): Record is not a class, but is
+  // masquerading as one currently for consistency with the old element model.
+  record,
+}
+
+/// Definition information for a [ClassEntity].
+abstract class ClassDefinition {
+  /// The kind of the defined class. This determines the semantics of [node].
+  ClassKind get kind;
+
+  /// The defining [ir.Node] for this class, if supported by its [kind].
+  ir.Node get node;
+
+  /// The canonical location of [cls]. This is used for sorting the classes
+  /// in the emitted code.
+  SourceSpan get location;
+
+  /// Deserializes a [ClassDefinition] object from [source].
+  factory ClassDefinition.readFromDataSource(DataSourceReader source) {
+    ClassKind kind = source.readEnum(ClassKind.values);
+    switch (kind) {
+      case ClassKind.regular:
+        return RegularClassDefinition.readFromDataSource(source);
+      case ClassKind.closure:
+        return ClosureClassDefinition.readFromDataSource(source);
+      case ClassKind.record:
+        return RecordContainerDefinition.readFromDataSource(source);
+    }
+  }
+
+  /// Serializes this [ClassDefinition] to [sink].
+  void writeToDataSink(DataSinkWriter sink);
+}
+
+/// A class directly defined by its [ir.Class] node.
+class RegularClassDefinition implements ClassDefinition {
+  /// Tag used for identifying serialized [RegularClassDefinition] objects in a
+  /// debugging data stream.
+  static const String tag = 'regular-class-definition';
+
+  @override
+  final ir.Class node;
+
+  RegularClassDefinition(this.node);
+
+  factory RegularClassDefinition.readFromDataSource(DataSourceReader source) {
+    source.begin(tag);
+    ir.Class node = source.readClassNode();
+    source.end(tag);
+    return RegularClassDefinition(node);
+  }
+
+  @override
+  void writeToDataSink(DataSinkWriter sink) {
+    sink.writeEnum(kind);
+    sink.begin(tag);
+    sink.writeClassNode(node);
+    sink.end(tag);
+  }
+
+  @override
+  SourceSpan get location => computeSourceSpanFromTreeNode(node);
+
+  @override
+  ClassKind get kind => ClassKind.regular;
+
+  @override
+  String toString() => 'RegularClassDefinition(kind:$kind,'
+      'node:$node,location:$location)';
+}
+
+class ClosureClassDefinition implements ClassDefinition {
+  /// Tag used for identifying serialized [ClosureClassDefinition] objects in a
+  /// debugging data stream.
+  static const String tag = 'closure-class-definition';
+
+  @override
+  final SourceSpan location;
+
+  ClosureClassDefinition(this.location);
+
+  factory ClosureClassDefinition.readFromDataSource(DataSourceReader source) {
+    source.begin(tag);
+    SourceSpan location = source.readSourceSpan();
+    source.end(tag);
+    return ClosureClassDefinition(location);
+  }
+
+  @override
+  void writeToDataSink(DataSinkWriter sink) {
+    sink.writeEnum(ClassKind.closure);
+    sink.begin(tag);
+    sink.writeSourceSpan(location);
+    sink.end(tag);
+  }
+
+  @override
+  ClassKind get kind => ClassKind.closure;
+
+  @override
+  ir.Node get node =>
+      throw UnsupportedError('ClosureClassDefinition.node for $location');
+
+  @override
+  String toString() => 'ClosureClassDefinition(kind:$kind,location:$location)';
+}
+
+class RecordContainerDefinition implements ClassDefinition {
+  /// Tag used for identifying serialized [RecordContainerDefinition] objects in
+  /// a debugging data stream.
+  static const String tag = 'record-definition';
+
+  @override
+  final SourceSpan location;
+
+  RecordContainerDefinition(this.location);
+
+  factory RecordContainerDefinition.readFromDataSource(
+      DataSourceReader source) {
+    source.begin(tag);
+    SourceSpan location = source.readSourceSpan();
+    source.end(tag);
+    return RecordContainerDefinition(location);
+  }
+
+  @override
+  void writeToDataSink(DataSinkWriter sink) {
+    sink.writeEnum(ClassKind.record);
+    sink.begin(tag);
+    sink.writeSourceSpan(location);
+    sink.end(tag);
+  }
+
+  @override
+  ClassKind get kind => ClassKind.record;
+
+  @override
+  ir.Node get node =>
+      throw UnsupportedError('RecordContainerDefinition.node for $location');
+
+  @override
+  String toString() =>
+      'RecordContainerDefinition(kind:$kind,location:$location)';
+}
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 0bf7e80..f597c52 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -19,9 +19,18 @@
 import '../ordered_typeset.dart';
 import '../serialization/deferrable.dart';
 import '../serialization/serialization.dart';
-import 'closure.dart';
-import 'element_map.dart';
-import 'element_map_impl.dart';
+import 'closure.dart'
+    show
+        ClosureClassData,
+        RecordClassData,
+        ClosureFunctionData,
+        ClosureFieldData;
+import 'element_map_interfaces.dart' show JsToElementMap, JsKernelToElementMap;
+import 'element_map_migrated.dart'
+    show
+        ClassDefinition,
+        MemberDefinition,
+        forEachOrderedParameterByFunctionNode;
 import 'elements.dart';
 
 /// Environment for fast lookup of component libraries.