[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 {