[dart2js] Migrate native_data.dart

Change-Id: I63a0243c75f0d358e495fd0a753cb2447b75acac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/249961
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index f6f4c84..1e228c8 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -8,7 +8,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../inferrer/abstract_value_domain.dart';
-import '../js_backend/native_data_interfaces.dart' show NativeBasicData;
+import '../js_backend/native_data.dart' show NativeBasicData;
 import '../js_model/locals.dart';
 import '../universe/selector.dart' show Selector;
 
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index 7147656..11c80ec 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -68,7 +68,7 @@
   }
 
   void forEachJsInteropClass(
-      void Function(ir.Class, String, {bool isAnonymous}) f) {
+      void Function(ir.Class, String, {required bool isAnonymous}) f) {
     _jsInteropClassNames.forEach((ir.Class node, String name) {
       f(node, name, isAnonymous: isAnonymousJsInteropClass(node));
     });
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 20ae34a..7cb6871 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.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 js_backend.native_data;
 
 import 'package:kernel/ast.dart' as ir;
@@ -18,8 +16,6 @@
 import '../serialization/serialization.dart';
 import '../util/util.dart';
 
-import 'native_data_interfaces.dart' as interfaces;
-
 class NativeBasicDataBuilder {
   bool _closed = false;
 
@@ -58,7 +54,7 @@
     // method.
     assert(
         _nativeClassTagInfo[cls] == null ||
-            _nativeClassTagInfo[cls].text == tagText,
+            _nativeClassTagInfo[cls]!.text == tagText,
         failedAt(
             cls,
             "Native tag info set inconsistently on $cls: "
@@ -72,7 +68,7 @@
   /// If [name] is provided, it sets the explicit js interop name for the
   /// library [element], other the js interop name is expected to be computed
   /// later.
-  void markAsJsInteropLibrary(LibraryEntity element, {String name}) {
+  void markAsJsInteropLibrary(LibraryEntity element, {required String name}) {
     assert(
         !_closed,
         failedAt(
@@ -88,7 +84,7 @@
   /// class [element], other the js interop name is expected to be computed
   /// later.
   void markAsJsInteropClass(ClassEntity element,
-      {String name, bool isAnonymous = false}) {
+      {required String name, required bool isAnonymous}) {
     assert(
         !_closed,
         failedAt(
@@ -135,7 +131,7 @@
 /// Basic information for native classes and js-interop libraries and classes.
 ///
 /// This information is computed during loading using [NativeBasicDataBuilder].
-class NativeBasicData implements interfaces.NativeBasicData {
+class NativeBasicData {
   /// Tag used for identifying serialized [NativeBasicData] objects in a
   /// debugging data stream.
   static const String tag = 'native-basic-data';
@@ -158,7 +154,7 @@
   final Set<ClassEntity> _anonymousJsInteropClasses;
 
   /// The JavaScript members implemented via typed JavaScript interop.
-  final Map<MemberEntity, String> _jsInteropMembers;
+  final Map<MemberEntity, String?> _jsInteropMembers;
 
   NativeBasicData(
       this._env,
@@ -176,24 +172,28 @@
     Map<LibraryEntity, String> jsInteropLibraries = {};
     Map<ClassEntity, String> jsInteropClasses = {};
     Set<ClassEntity> anonymousJsInteropClasses = {};
-    Map<MemberEntity, String> jsInteropMembers = {};
+    Map<MemberEntity, String?> jsInteropMembers = {};
 
     data.forEachNativeClass((ir.Class node, String text) {
       nativeClassTagInfo[map.getClass(node)] = NativeClassTag(text);
     });
     data.forEachJsInteropLibrary((ir.Library node, String name) {
-      jsInteropLibraries[env.lookupLibrary(node.importUri, required: true)] =
+      jsInteropLibraries[env.lookupLibrary(node.importUri, required: true)!] =
           name;
     });
     data.forEachJsInteropClass((ir.Class node, String name,
-        {bool isAnonymous}) {
+        {required bool isAnonymous}) {
       ClassEntity cls = map.getClass(node);
       jsInteropClasses[cls] = name;
       if (isAnonymous) {
         anonymousJsInteropClasses.add(cls);
       }
     });
-    data.forEachJsInteropMember((ir.Member node, String name) {
+    data.forEachJsInteropMember((ir.Member node, String? name) {
+      // TODO(49428): Are there other members that we should ignore here?
+      //  There are non-external and unannotated members because the source code
+      //  doesn't contain them. (e.g. default constructor) Does it make sense to
+      //  consider these valid JS members?
       if (memberIsIgnorable(node)) return;
       jsInteropMembers[map.getMember(node)] = name;
     });
@@ -209,7 +209,7 @@
     bool isAllowInteropUsed = source.readBool();
     Map<ClassEntity, NativeClassTag> nativeClassTagInfo =
         source.readClassMap(() {
-      List<String> names = source.readStrings() /*!*/;
+      final names = source.readStrings()!;
       bool isNonLeaf = source.readBool();
       return NativeClassTag.internal(names, isNonLeaf);
     });
@@ -218,8 +218,8 @@
     Map<ClassEntity, String> jsInteropClasses =
         source.readClassMap(source.readString);
     Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
-    Map<MemberEntity, String> jsInteropMembers =
-        source.readMemberMap((MemberEntity member) => source.readString());
+    Map<MemberEntity, String?> jsInteropMembers = source
+        .readMemberMap((MemberEntity member) => source.readStringOrNull());
     source.end(tag);
     return NativeBasicData(
         elementEnvironment,
@@ -243,7 +243,7 @@
     sink.writeClassMap(_jsInteropClasses, sink.writeString);
     sink.writeClasses(_anonymousJsInteropClasses);
     sink.writeMemberMap(_jsInteropMembers,
-        (MemberEntity member, String name) => sink.writeString(name));
+        (MemberEntity member, String? name) => sink.writeStringOrNull(name));
     sink.end(tag);
   }
 
@@ -263,21 +263,19 @@
   /// A class is marked as native either through the `@Native(...)` annotation
   /// allowed for internal libraries or via the typed JavaScriptInterop
   /// mechanism allowed for user libraries.
-  @override
   bool isNativeClass(ClassEntity element) {
     if (isJsInteropClass(element)) return true;
     return _nativeClassTagInfo.containsKey(element);
   }
 
   /// Returns the list of non-directive native tag words for [cls].
-  @override
   List<String> getNativeTagsOfClass(ClassEntity cls) {
-    return _nativeClassTagInfo[cls].names;
+    return _nativeClassTagInfo[cls]!.names;
   }
 
   /// Returns `true` if [cls] has a `!nonleaf` tag word.
   bool hasNativeTagsForcedNonLeaf(ClassEntity cls) {
-    return _nativeClassTagInfo[cls].isNonLeaf;
+    return _nativeClassTagInfo[cls]!.isNonLeaf;
   }
 
   /// Returns `true` if js interop features are used.
@@ -290,7 +288,6 @@
   }
 
   /// Returns `true` if [element] is a JsInterop class.
-  @override
   bool isJsInteropClass(ClassEntity element) {
     return _jsInteropClasses.containsKey(element);
   }
@@ -307,12 +304,12 @@
         element.isConstructor ||
         element.isGetter ||
         element.isSetter) {
-      FunctionEntity function = element;
+      final function = element as FunctionEntity;
       if (!function.isExternal) return false;
 
       if (_isJsInteropMember(function)) return true;
       if (function.enclosingClass != null) {
-        return isJsInteropClass(function.enclosingClass);
+        return isJsInteropClass(function.enclosingClass!);
       }
       if (function.isTopLevel) {
         return isJsInteropLibrary(function.library);
@@ -323,8 +320,10 @@
     }
   }
 
-  /// Returns `true` if [element] or any of its superclasses is native.
-  bool isNativeOrExtendsNative(ClassEntity element) {
+  /// Returns `true` if [element] or any of its superclasses is native. Supports
+  /// nullable element for checks on non-existent enclosing class of top-level
+  /// functions.
+  bool isNativeOrExtendsNative(ClassEntity? element) {
     if (element == null) return false;
     if (isNativeClass(element) || isJsInteropClass(element)) {
       return true;
@@ -344,7 +343,7 @@
         map.toBackendClassMap(_jsInteropClasses, identity);
     Set<ClassEntity> anonymousJsInteropClasses =
         map.toBackendClassSet(_anonymousJsInteropClasses);
-    Map<MemberEntity, String> jsInteropMembers =
+    Map<MemberEntity, String?> jsInteropMembers =
         map.toBackendMemberMap(_jsInteropMembers, identity);
     return NativeBasicData(
         environment,
@@ -464,7 +463,7 @@
         String name,
         Iterable<String> createsAnnotations,
         Iterable<String> returnsAnnotations) {
-      MemberEntity member = map.getMember(node);
+      final member = map.getMember(node) as FunctionEntity;
       nativeMemberName[member] = name;
       bool isJsInterop = nativeBasicData.isJsInteropMember(member);
       nativeMethodBehavior[member] = map.getNativeBehaviorForMethod(
@@ -476,9 +475,10 @@
         String name,
         Iterable<String> createsAnnotations,
         Iterable<String> returnsAnnotations) {
-      FieldEntity field = map.getMember(node);
+      final field = map.getMember(node) as FieldEntity;
       nativeMemberName[field] = name;
       bool isJsInterop = nativeBasicData.isJsInteropMember(field);
+      node as ir.Field;
       nativeFieldLoadBehavior[field] = map.getNativeBehaviorForFieldLoad(
           node, createsAnnotations, returnsAnnotations,
           isJsInterop: isJsInterop);
@@ -564,7 +564,7 @@
       _nativeBasicData._jsInteropClasses;
 
   @override
-  Map<MemberEntity, String> get _jsInteropMembers =>
+  Map<MemberEntity, String?> get _jsInteropMembers =>
       _nativeBasicData._jsInteropMembers;
 
   /// Returns `true` if [element] has an `@Anonymous` annotation.
@@ -596,21 +596,21 @@
       _nativeBasicData.isJsInteropClass(element);
 
   @override
-  bool isNativeOrExtendsNative(ClassEntity element) =>
+  bool isNativeOrExtendsNative(ClassEntity? element) =>
       _nativeBasicData.isNativeOrExtendsNative(element);
 
   /// Returns the explicit js interop name for library [element].
-  String getJsInteropLibraryName(LibraryEntity element) {
+  String? getJsInteropLibraryName(LibraryEntity element) {
     return _jsInteropLibraries[element];
   }
 
   /// Returns the explicit js interop name for class [element].
-  String getJsInteropClassName(ClassEntity element) {
+  String? getJsInteropClassName(ClassEntity element) {
     return _jsInteropClasses[element];
   }
 
   /// Returns the explicit js interop name for member [element].
-  String getJsInteropMemberName(MemberEntity element) {
+  String? getJsInteropMemberName(MemberEntity element) {
     return _jsInteropMembers[element];
   }
 
@@ -625,12 +625,12 @@
         element.isConstructor ||
         element.isGetter ||
         element.isSetter) {
-      FunctionEntity function = element;
+      final function = element as FunctionEntity;
       if (!function.isExternal) return false;
 
       if (_isJsInteropMember(function)) return true;
       if (function.enclosingClass != null) {
-        return isJsInteropClass(function.enclosingClass);
+        return isJsInteropClass(function.enclosingClass!);
       }
       if (function.isTopLevel) {
         return isJsInteropLibrary(function.library);
@@ -649,11 +649,11 @@
 
   /// Computes the name for [element] to use in the generated JavaScript. This
   /// is either given through a native annotation or a js interop annotation.
-  String getFixedBackendName(MemberEntity element) {
-    String name = _nativeMemberName[element];
+  String? getFixedBackendName(MemberEntity element) {
+    String? name = _nativeMemberName[element];
     if (name == null && isJsInteropMember(element)) {
       if (element.isConstructor) {
-        name = _jsClassNameHelper(element.enclosingClass);
+        name = _jsClassNameHelper(element.enclosingClass!);
       } else {
         name = _jsMemberNameHelper(element);
         // Top-level static JS interop members can be associated with a dotted
@@ -668,19 +668,19 @@
   }
 
   String _jsLibraryNameHelper(LibraryEntity element) {
-    String jsInteropName = getJsInteropLibraryName(element);
+    String? jsInteropName = getJsInteropLibraryName(element);
     if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
     return 'self';
   }
 
   String _jsClassNameHelper(ClassEntity element) {
-    String jsInteropName = getJsInteropClassName(element);
+    String? jsInteropName = getJsInteropClassName(element);
     if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
     return computeUnescapedJSInteropName(element.name);
   }
 
   String _jsMemberNameHelper(MemberEntity element) {
-    String jsInteropName = _jsInteropMembers[element];
+    String? jsInteropName = _jsInteropMembers[element];
     assert(
         !(_jsInteropMembers.containsKey(element) && jsInteropName == null),
         failedAt(
@@ -690,7 +690,7 @@
     if (jsInteropName != null && jsInteropName.isNotEmpty) {
       return jsInteropName;
     }
-    return computeUnescapedJSInteropName(element.name);
+    return computeUnescapedJSInteropName(element.name!);
   }
 
   /// Returns a JavaScript path specifying the context in which
@@ -699,18 +699,18 @@
   /// For example: fixedBackendPath for the static method createMap in the
   /// Map class of the goog.map JavaScript library would have path
   /// "goog.maps.Map".
-  String getFixedBackendMethodPath(FunctionEntity element) {
+  String? getFixedBackendMethodPath(FunctionEntity element) {
     if (!isJsInteropMember(element)) return null;
     if (element.isInstanceMember) return 'this';
     if (element.isConstructor) {
-      return _fixedBackendClassPath(element.enclosingClass);
+      return _fixedBackendClassPath(element.enclosingClass!);
     }
     StringBuffer sb = StringBuffer();
     sb.write(_jsLibraryNameHelper(element.library));
     if (element.enclosingClass != null) {
       sb
         ..write('.')
-        ..write(_jsClassNameHelper(element.enclosingClass));
+        ..write(_jsClassNameHelper(element.enclosingClass!));
     }
 
     // Top-level static JS interop members can be associated with a dotted
@@ -724,7 +724,7 @@
     return sb.toString();
   }
 
-  String _fixedBackendClassPath(ClassEntity element) {
+  String? _fixedBackendClassPath(ClassEntity element) {
     if (!isJsInteropClass(element)) return null;
     return _jsLibraryNameHelper(element.library);
   }
@@ -746,7 +746,7 @@
         _nativeMethodBehavior.containsKey(method),
         failedAt(method,
             "No native method behavior has been computed for $method."));
-    return _nativeMethodBehavior[method];
+    return _nativeMethodBehavior[method]!;
   }
 
   /// Returns the [NativeBehavior] for reading from the native [field].
@@ -757,7 +757,7 @@
             field,
             "No native field load behavior has been "
             "computed for $field."));
-    return _nativeFieldLoadBehavior[field];
+    return _nativeFieldLoadBehavior[field]!;
   }
 
   /// Returns the [NativeBehavior] for writing to the native [field].
@@ -766,7 +766,7 @@
         _nativeFieldStoreBehavior.containsKey(field),
         failedAt(field,
             "No native field store behavior has been computed for $field."));
-    return _nativeFieldStoreBehavior[field];
+    return _nativeFieldStoreBehavior[field]!;
   }
 
   /// Apply JS$ escaping scheme to convert possible escaped Dart names into
@@ -793,7 +793,7 @@
     final nativeMethodBehavior = <FunctionEntity, NativeBehavior>{};
     _nativeMethodBehavior
         .forEach((FunctionEntity method, NativeBehavior behavior) {
-      FunctionEntity backendMethod = map.toBackendMember(method);
+      final backendMethod = map.toBackendMember(method) as FunctionEntity?;
       if (backendMethod != null) {
         // If [method] isn't used it doesn't have a corresponding backend
         // method.
diff --git a/pkg/compiler/lib/src/js_backend/native_data_interfaces.dart b/pkg/compiler/lib/src/js_backend/native_data_interfaces.dart
deleted file mode 100644
index f2e7f67..0000000
--- a/pkg/compiler/lib/src/js_backend/native_data_interfaces.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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:compiler/src/elements/entities.dart';
-
-/// This is a facade interface for the members of NativeBasicData that are
-/// required by other migrated classes.
-// TODO(48820): When NativeBasicData is migrated, remove this facade.
-abstract class NativeBasicData {
-  bool isJsInteropClass(ClassEntity element);
-
-  bool isNativeClass(ClassEntity element);
-
-  List<String> getNativeTagsOfClass(ClassEntity cls);
-}
diff --git a/pkg/compiler/lib/src/kernel/native_basic_data.dart b/pkg/compiler/lib/src/kernel/native_basic_data.dart
index b80a7c7..2ea23da 100644
--- a/pkg/compiler/lib/src/kernel/native_basic_data.dart
+++ b/pkg/compiler/lib/src/kernel/native_basic_data.dart
@@ -119,7 +119,10 @@
           } else {
             FunctionEntity function = member;
             ir.Member memberNode = elementMap.getMemberNode(member);
-            String memberName =
+            // Members that are not annotated and not external will result in
+            // null here. For example, the default constructor which is not
+            // user-specified.
+            String /*?*/ memberName =
                 annotationData.getJsInteropMemberName(memberNode);
             if (function.isExternal) {
               memberName ??= function.name;
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 4832afb..19aac54 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -8,7 +8,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as js;
-import '../js_backend/native_data_interfaces.dart' show NativeBasicData;
+import '../js_backend/native_data.dart' show NativeBasicData;
 import '../js_model/js_to_frontend_map.dart' show JsToFrontendMap;
 import '../options.dart';
 import '../serialization/serialization.dart';
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index bf52762..68b63ba 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -7,7 +7,7 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../js_backend/native_data_interfaces.dart';
+import '../js_backend/native_data.dart';
 
 /// Determines all native classes in a set of libraries.
 class NativeClassFinder {