2bb32ec55a
Change-Id: Ib1afd38a7d3694c2e5ed591132f41b147f76d75a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427560 Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
1786 lines
57 KiB
Dart
1786 lines
57 KiB
Dart
// 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:js_shared/variance.dart';
|
|
|
|
import '../common.dart';
|
|
import '../constants/constant_system.dart' as constant_system;
|
|
import '../constants/values.dart';
|
|
import '../elements/entities.dart';
|
|
import '../elements/names.dart';
|
|
import '../elements/types.dart';
|
|
import '../inferrer/abstract_value_domain.dart';
|
|
import '../ir/element_map.dart';
|
|
import '../js_backend/native_data.dart' show NativeBasicData;
|
|
import '../js_model/locals.dart';
|
|
import '../universe/selector.dart' show Selector;
|
|
import '../universe/world_builder.dart';
|
|
|
|
import 'names.dart' show Identifiers, Uris;
|
|
|
|
/// The common elements and types in Dart.
|
|
abstract class CommonElements {
|
|
final DartTypes dartTypes;
|
|
final ElementEnvironment _env;
|
|
ClassEntity? _symbolClass;
|
|
ConstructorEntity? _symbolConstructorTarget;
|
|
bool _computedSymbolConstructorDependencies = false;
|
|
ConstructorEntity? _symbolConstructorImplementationTarget;
|
|
ClassEntity? _mapLiteralClass;
|
|
ClassEntity? _symbolImplementationClass;
|
|
FieldEntity? _symbolImplementationField;
|
|
|
|
CommonElements(this.dartTypes, this._env);
|
|
|
|
/// The `Object` class defined in 'dart:core'.
|
|
late final ClassEntity objectClass = _findClass(coreLibrary, 'Object');
|
|
|
|
/// The `bool` class defined in 'dart:core'.
|
|
late final ClassEntity boolClass = _findClass(coreLibrary, 'bool');
|
|
|
|
/// The `num` class defined in 'dart:core'.
|
|
late final ClassEntity numClass = _findClass(coreLibrary, 'num');
|
|
|
|
/// The `int` class defined in 'dart:core'.
|
|
late final ClassEntity intClass = _findClass(coreLibrary, 'int');
|
|
|
|
/// The `double` class defined in 'dart:core'.
|
|
late final ClassEntity doubleClass = _findClass(coreLibrary, 'double');
|
|
|
|
/// The `String` class defined in 'dart:core'.
|
|
late final ClassEntity stringClass = _findClass(coreLibrary, 'String');
|
|
|
|
/// The `Function` class defined in 'dart:core'.
|
|
late final ClassEntity functionClass = _findClass(coreLibrary, 'Function');
|
|
|
|
/// The `Record` class defined in 'dart:core'.
|
|
late final ClassEntity recordClass = _findClass(coreLibrary, 'Record');
|
|
|
|
/// The `Resource` class defined in 'dart:core'.
|
|
late final ClassEntity resourceClass = _findClass(coreLibrary, 'Resource');
|
|
|
|
/// The `Symbol` class defined in 'dart:core'.
|
|
late final ClassEntity symbolClass = _findClass(coreLibrary, 'Symbol');
|
|
|
|
/// The `Null` class defined in 'dart:core'.
|
|
late final ClassEntity nullClass = _findClass(coreLibrary, 'Null');
|
|
|
|
/// The `Type` class defined in 'dart:core'.
|
|
late final ClassEntity typeClass = _findClass(coreLibrary, 'Type');
|
|
|
|
/// The `StackTrace` class defined in 'dart:core';
|
|
late final ClassEntity stackTraceClass = _findClass(
|
|
coreLibrary,
|
|
'StackTrace',
|
|
);
|
|
|
|
/// The `List` class defined in 'dart:core';
|
|
late final ClassEntity listClass = _findClass(coreLibrary, 'List');
|
|
|
|
/// The `Set` class defined in 'dart:core';
|
|
late final ClassEntity setClass = _findClass(coreLibrary, 'Set');
|
|
|
|
/// The `Map` class defined in 'dart:core';
|
|
late final ClassEntity mapClass = _findClass(coreLibrary, 'Map');
|
|
|
|
/// The `Set` class defined in 'dart:core';
|
|
late final ClassEntity unmodifiableSetClass = _findClass(
|
|
collectionLibrary,
|
|
'_UnmodifiableSet',
|
|
);
|
|
|
|
/// The `Iterable` class defined in 'dart:core';
|
|
late final ClassEntity iterableClass = _findClass(coreLibrary, 'Iterable');
|
|
|
|
/// The `Future` class defined in 'async';.
|
|
late final ClassEntity futureClass = _findClass(asyncLibrary, 'Future');
|
|
|
|
/// The `Stream` class defined in 'async';
|
|
late final ClassEntity streamClass = _findClass(asyncLibrary, 'Stream');
|
|
|
|
/// The dart:core library.
|
|
late final LibraryEntity coreLibrary = _env.lookupLibrary(
|
|
Uris.dartCore,
|
|
required: true,
|
|
)!;
|
|
|
|
/// The dart:async library.
|
|
late final LibraryEntity? asyncLibrary = _env.lookupLibrary(Uris.dartAsync);
|
|
|
|
/// The dart:collection library.
|
|
late final LibraryEntity? collectionLibrary = _env.lookupLibrary(
|
|
Uris.dartCollection,
|
|
);
|
|
|
|
/// The dart:mirrors library.
|
|
/// Null if the program doesn't access dart:mirrors.
|
|
late final LibraryEntity? mirrorsLibrary = _env.lookupLibrary(
|
|
Uris.dartMirrors,
|
|
);
|
|
|
|
/// The dart:typed_data library.
|
|
late final LibraryEntity typedDataLibrary = _env.lookupLibrary(
|
|
Uris.dartNativeTypedData,
|
|
required: true,
|
|
)!;
|
|
|
|
/// The dart:_js_shared_embedded_names library.
|
|
late final LibraryEntity sharedEmbeddedNamesLibrary = _env.lookupLibrary(
|
|
Uris.dartJSSharedEmbeddedNames,
|
|
required: true,
|
|
)!;
|
|
|
|
/// The dart:_js_helper library.
|
|
late final LibraryEntity? jsHelperLibrary = _env.lookupLibrary(
|
|
Uris.dartJSHelper,
|
|
);
|
|
|
|
/// The dart:_late_helper library
|
|
late final LibraryEntity? lateHelperLibrary = _env.lookupLibrary(
|
|
Uris.dartLateHelper,
|
|
);
|
|
|
|
/// The dart:_interceptors library.
|
|
late final LibraryEntity? interceptorsLibrary = _env.lookupLibrary(
|
|
Uris.dartInterceptors,
|
|
);
|
|
|
|
/// The dart:_foreign_helper library.
|
|
late final LibraryEntity? foreignLibrary = _env.lookupLibrary(
|
|
Uris.dartForeignHelper,
|
|
);
|
|
|
|
/// The dart:_rti library.
|
|
late final LibraryEntity rtiLibrary = _env.lookupLibrary(
|
|
Uris.dartRti,
|
|
required: true,
|
|
)!;
|
|
|
|
/// The dart:_internal library.
|
|
late final LibraryEntity internalLibrary = _env.lookupLibrary(
|
|
Uris.dartInternal,
|
|
required: true,
|
|
)!;
|
|
|
|
/// The dart:js_util library.
|
|
late final LibraryEntity? dartJsUtilLibrary = _env.lookupLibrary(
|
|
Uris.dartJSUtil,
|
|
);
|
|
|
|
/// The package:js library.
|
|
late final LibraryEntity? packageJsLibrary = _env.lookupLibrary(
|
|
Uris.packageJS,
|
|
);
|
|
|
|
/// The dart:_js_annotations library.
|
|
late final LibraryEntity? dartJsAnnotationsLibrary = _env.lookupLibrary(
|
|
Uris.dartJSAnnotations,
|
|
);
|
|
|
|
/// The dart:js_interop library.
|
|
late final LibraryEntity? dartJsInteropLibrary = _env.lookupLibrary(
|
|
Uris.dartJSInterop,
|
|
);
|
|
|
|
/// The `NativeTypedData` class from dart:typed_data.
|
|
ClassEntity get typedDataClass =>
|
|
_findClass(typedDataLibrary, 'NativeTypedData');
|
|
|
|
/// Constructor of the `Symbol` class in dart:internal.
|
|
///
|
|
/// This getter will ensure that `Symbol` is resolved and lookup the
|
|
/// constructor on demand.
|
|
ConstructorEntity get symbolConstructorTarget {
|
|
// TODO(johnniwinther): Kernel does not include redirecting factories
|
|
// so this cannot be found in kernel. Find a consistent way to handle
|
|
// this and similar cases.
|
|
return _symbolConstructorTarget ??= _env.lookupConstructor(
|
|
symbolImplementationClass,
|
|
'',
|
|
)!;
|
|
}
|
|
|
|
void _ensureSymbolConstructorDependencies() {
|
|
if (_computedSymbolConstructorDependencies) return;
|
|
_computedSymbolConstructorDependencies = true;
|
|
if (_symbolConstructorTarget == null) {
|
|
_symbolImplementationClass ??= _findClassOrNull(
|
|
internalLibrary,
|
|
'Symbol',
|
|
);
|
|
if (_symbolImplementationClass != null) {
|
|
_symbolConstructorTarget = _env.lookupConstructor(
|
|
_symbolImplementationClass!,
|
|
'',
|
|
required: false,
|
|
);
|
|
}
|
|
}
|
|
_symbolClass ??= _findClassOrNull(coreLibrary, 'Symbol');
|
|
if (_symbolClass == null) {
|
|
return;
|
|
}
|
|
_symbolConstructorImplementationTarget = _env.lookupConstructor(
|
|
symbolClass,
|
|
'',
|
|
required: false,
|
|
);
|
|
}
|
|
|
|
/// Whether [element] is the same as [symbolConstructor].
|
|
///
|
|
/// Used to check for the constructor without computing it until it is likely
|
|
/// to be seen.
|
|
bool isSymbolConstructor(ConstructorEntity element) {
|
|
_ensureSymbolConstructorDependencies();
|
|
return element == _symbolConstructorImplementationTarget ||
|
|
element == _symbolConstructorTarget;
|
|
}
|
|
|
|
/// The function `identical` in dart:core.
|
|
late final FunctionEntity identicalFunction = _findLibraryMember(
|
|
coreLibrary,
|
|
'identical',
|
|
)!;
|
|
|
|
/// Whether [element] is the `Function.apply` method.
|
|
///
|
|
/// This will not resolve the apply method if it hasn't been seen yet during
|
|
/// compilation.
|
|
bool isFunctionApplyMethod(MemberEntity element) =>
|
|
element.name == 'apply' && element.enclosingClass == functionClass;
|
|
|
|
/// The `dynamic` type.
|
|
DynamicType get dynamicType => _env.dynamicType as DynamicType;
|
|
|
|
/// The `Object` type defined in 'dart:core'.
|
|
InterfaceType get objectType => _getRawType(objectClass);
|
|
|
|
/// The `bool` type defined in 'dart:core'.
|
|
InterfaceType get boolType => _getRawType(boolClass);
|
|
|
|
/// The `num` type defined in 'dart:core'.
|
|
InterfaceType get numType => _getRawType(numClass);
|
|
|
|
/// The `int` type defined in 'dart:core'.
|
|
InterfaceType get intType => _getRawType(intClass);
|
|
|
|
/// The `double` type defined in 'dart:core'.
|
|
InterfaceType get doubleType => _getRawType(doubleClass);
|
|
|
|
/// The `String` type defined in 'dart:core'.
|
|
InterfaceType get stringType => _getRawType(stringClass);
|
|
|
|
/// The `Symbol` type defined in 'dart:core'.
|
|
InterfaceType get symbolType => _getRawType(symbolClass);
|
|
|
|
/// The `Function` type defined in 'dart:core'.
|
|
InterfaceType get functionType => _getRawType(functionClass);
|
|
|
|
/// The `Null` type defined in 'dart:core'.
|
|
InterfaceType get nullType => _getRawType(nullClass);
|
|
|
|
/// The `Record` type defined in 'dart:core'.
|
|
InterfaceType get recordType => _getRawType(recordClass);
|
|
|
|
/// The `Type` type defined in 'dart:core'.
|
|
InterfaceType get typeType => _getRawType(typeClass);
|
|
|
|
InterfaceType get typeLiteralType => _getRawType(typeLiteralClass);
|
|
|
|
/// The `StackTrace` type defined in 'dart:core';
|
|
InterfaceType get stackTraceType => _getRawType(stackTraceClass);
|
|
|
|
/// Returns an instance of the `List` type defined in 'dart:core' with
|
|
/// [elementType] as its type argument.
|
|
///
|
|
/// If no type argument is provided, the canonical raw type is returned.
|
|
InterfaceType listType([DartType? elementType]) {
|
|
if (elementType == null) {
|
|
return _getRawType(listClass);
|
|
}
|
|
return _createInterfaceType(listClass, [elementType]);
|
|
}
|
|
|
|
/// Returns an instance of the `Set` type defined in 'dart:core' with
|
|
/// [elementType] as its type argument.
|
|
///
|
|
/// If no type argument is provided, the canonical raw type is returned.
|
|
InterfaceType setType([DartType? elementType]) {
|
|
if (elementType == null) {
|
|
return _getRawType(setClass);
|
|
}
|
|
return _createInterfaceType(setClass, [elementType]);
|
|
}
|
|
|
|
/// Returns an instance of the `Map` type defined in 'dart:core' with
|
|
/// [keyType] and [valueType] as its type arguments.
|
|
///
|
|
/// If no type arguments are provided, the canonical raw type is returned.
|
|
|
|
InterfaceType mapType([DartType? keyType, DartType? valueType]) {
|
|
if (keyType == null && valueType == null) {
|
|
return _getRawType(mapClass);
|
|
} else if (keyType == null) {
|
|
keyType = dynamicType;
|
|
} else {
|
|
valueType ??= dynamicType;
|
|
}
|
|
return _createInterfaceType(mapClass, [keyType, valueType!]);
|
|
}
|
|
|
|
/// Returns an instance of the `Iterable` type defined in 'dart:core' with
|
|
/// [elementType] as its type argument.
|
|
///
|
|
/// If no type argument is provided, the canonical raw type is returned.
|
|
InterfaceType iterableType([DartType? elementType]) {
|
|
if (elementType == null) {
|
|
return _getRawType(iterableClass);
|
|
}
|
|
return _createInterfaceType(iterableClass, [elementType]);
|
|
}
|
|
|
|
/// Returns an instance of the `Future` type defined in 'dart:async' with
|
|
/// [elementType] as its type argument.
|
|
///
|
|
/// If no type argument is provided, the canonical raw type is returned.
|
|
// CommonElementsForDartTypes
|
|
InterfaceType futureType([DartType? elementType]) {
|
|
if (elementType == null) {
|
|
return _getRawType(futureClass);
|
|
}
|
|
return _createInterfaceType(futureClass, [elementType]);
|
|
}
|
|
|
|
/// Returns an instance of the `Stream` type defined in 'dart:async' with
|
|
/// [elementType] as its type argument.
|
|
///
|
|
/// If no type argument is provided, the canonical raw type is returned.
|
|
InterfaceType streamType([DartType? elementType]) {
|
|
if (elementType == null) {
|
|
return _getRawType(streamClass);
|
|
}
|
|
return _createInterfaceType(streamClass, [elementType]);
|
|
}
|
|
|
|
ClassEntity _findClass(LibraryEntity? library, String name) {
|
|
return _env.lookupClass(library!, name, required: true)!;
|
|
}
|
|
|
|
ClassEntity? _findClassOrNull(LibraryEntity? library, String name) {
|
|
if (library == null) return null;
|
|
return _env.lookupClass(library, name, required: false);
|
|
}
|
|
|
|
T? _findLibraryMember<T extends MemberEntity>(
|
|
LibraryEntity? library,
|
|
String name, {
|
|
bool setter = false,
|
|
bool required = true,
|
|
}) {
|
|
if (library == null) return null;
|
|
return _env.lookupLibraryMember(
|
|
library,
|
|
name,
|
|
setter: setter,
|
|
required: required,
|
|
)
|
|
as T?;
|
|
}
|
|
|
|
T? _findClassMemberOrNull<T extends MemberEntity>(
|
|
ClassEntity cls,
|
|
String name,
|
|
) {
|
|
return _env.lookupLocalClassMember(
|
|
cls,
|
|
Name(name, cls.library.canonicalUri, isSetter: false),
|
|
required: false,
|
|
)
|
|
as T?;
|
|
}
|
|
|
|
T _findClassMember<T extends MemberEntity>(ClassEntity cls, String name) {
|
|
return _env.lookupLocalClassMember(
|
|
cls,
|
|
Name(name, cls.library.canonicalUri, isSetter: false),
|
|
required: true,
|
|
)
|
|
as T;
|
|
}
|
|
|
|
/// Return the raw type of [cls].
|
|
InterfaceType _getRawType(ClassEntity cls) {
|
|
return _env.getRawType(cls);
|
|
}
|
|
|
|
/// Create the instantiation of [cls] with the given [typeArguments] and
|
|
/// [nullability].
|
|
InterfaceType _createInterfaceType(
|
|
ClassEntity cls,
|
|
List<DartType> typeArguments,
|
|
) {
|
|
return _env.createInterfaceType(cls, typeArguments);
|
|
}
|
|
|
|
InterfaceType getConstantListTypeFor(InterfaceType sourceType) {
|
|
// TODO(51534): Use CONST_CANONICAL_TYPE(T_i) for arguments.
|
|
return _env.createInterfaceType(jsArrayClass, sourceType.typeArguments);
|
|
}
|
|
|
|
InterfaceType getConstantMapTypeFor(
|
|
InterfaceType sourceType, {
|
|
bool onlyStringKeys = false,
|
|
}) {
|
|
// TODO(51534): Use CONST_CANONICAL_TYPE(T_i) for arguments.
|
|
ClassEntity classElement = onlyStringKeys
|
|
? constantStringMapClass
|
|
: generalConstantMapClass;
|
|
return _env.createInterfaceType(classElement, sourceType.typeArguments);
|
|
}
|
|
|
|
InterfaceType getConstantSetTypeFor(
|
|
InterfaceType sourceType, {
|
|
bool onlyStringKeys = false,
|
|
}) {
|
|
// TODO(51534): Use CONST_CANONICAL_TYPE(T_i) for arguments.
|
|
ClassEntity classElement = onlyStringKeys
|
|
? constantStringSetClass
|
|
: generalConstantSetClass;
|
|
return _env.createInterfaceType(classElement, sourceType.typeArguments);
|
|
}
|
|
|
|
/// Returns the field that holds the internal name in the implementation class
|
|
/// for `Symbol`.
|
|
|
|
FieldEntity get symbolField => _symbolImplementationField ??=
|
|
_env.lookupLocalClassMember(
|
|
symbolImplementationClass,
|
|
PrivateName(
|
|
'_name',
|
|
symbolImplementationClass.library.canonicalUri,
|
|
),
|
|
required: true,
|
|
)
|
|
as FieldEntity;
|
|
|
|
InterfaceType get symbolImplementationType =>
|
|
_env.getRawType(symbolImplementationClass);
|
|
|
|
// From dart:core
|
|
ClassEntity get mapLiteralClass {
|
|
if (_mapLiteralClass == null) {
|
|
_mapLiteralClass = _env.lookupClass(coreLibrary, 'LinkedHashMap');
|
|
_mapLiteralClass ??= _findClass(collectionLibrary, 'LinkedHashMap');
|
|
}
|
|
return _mapLiteralClass!;
|
|
}
|
|
|
|
late final ConstructorEntity mapLiteralConstructor = _env.lookupConstructor(
|
|
mapLiteralClass,
|
|
'_literal',
|
|
)!;
|
|
late final ConstructorEntity mapLiteralConstructorEmpty = _env
|
|
.lookupConstructor(mapLiteralClass, '_empty')!;
|
|
late final FunctionEntity mapLiteralUntypedMaker =
|
|
_env.lookupLocalClassMember(
|
|
mapLiteralClass,
|
|
PrivateName('_makeLiteral', mapLiteralClass.library.canonicalUri),
|
|
)
|
|
as FunctionEntity;
|
|
late final FunctionEntity mapLiteralUntypedEmptyMaker =
|
|
_env.lookupLocalClassMember(
|
|
mapLiteralClass,
|
|
PrivateName('_makeEmpty', mapLiteralClass.library.canonicalUri),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
late final ClassEntity setLiteralClass = _findClass(
|
|
collectionLibrary,
|
|
'LinkedHashSet',
|
|
);
|
|
|
|
late final ConstructorEntity setLiteralConstructor = _env.lookupConstructor(
|
|
setLiteralClass,
|
|
'_literal',
|
|
)!;
|
|
late final ConstructorEntity setLiteralConstructorEmpty = _env
|
|
.lookupConstructor(setLiteralClass, '_empty')!;
|
|
late final FunctionEntity setLiteralUntypedMaker =
|
|
_env.lookupLocalClassMember(
|
|
setLiteralClass,
|
|
PrivateName('_makeLiteral', setLiteralClass.library.canonicalUri),
|
|
)
|
|
as FunctionEntity;
|
|
late final FunctionEntity setLiteralUntypedEmptyMaker =
|
|
_env.lookupLocalClassMember(
|
|
setLiteralClass,
|
|
PrivateName('_makeEmpty', setLiteralClass.library.canonicalUri),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
late final FunctionEntity? objectNoSuchMethod =
|
|
_env.lookupLocalClassMember(
|
|
objectClass,
|
|
const PublicName(Identifiers.noSuchMethod_),
|
|
)
|
|
as FunctionEntity?;
|
|
|
|
bool isDefaultNoSuchMethodImplementation(FunctionEntity element) {
|
|
ClassEntity? classElement = element.enclosingClass;
|
|
return classElement == objectClass ||
|
|
classElement == jsInterceptorClass ||
|
|
classElement == jsNullClass;
|
|
}
|
|
|
|
// From dart:async
|
|
ClassEntity _findAsyncHelperClass(String name) =>
|
|
_findClass(asyncLibrary, name);
|
|
|
|
FunctionEntity _findAsyncHelperFunction(String name) =>
|
|
_findLibraryMember(asyncLibrary, name)!;
|
|
|
|
FunctionEntity get asyncHelperStartSync =>
|
|
_findAsyncHelperFunction("_asyncStartSync");
|
|
|
|
FunctionEntity get asyncHelperAwait =>
|
|
_findAsyncHelperFunction("_asyncAwait");
|
|
|
|
FunctionEntity get asyncHelperReturn =>
|
|
_findAsyncHelperFunction("_asyncReturn");
|
|
|
|
FunctionEntity get asyncHelperRethrow =>
|
|
_findAsyncHelperFunction("_asyncRethrow");
|
|
|
|
FunctionEntity get wrapBody =>
|
|
_findAsyncHelperFunction("_wrapJsFunctionForAsync");
|
|
|
|
FunctionEntity get yieldStar =>
|
|
_env.lookupLocalClassMember(
|
|
_findAsyncHelperClass("_IterationMarker"),
|
|
const PublicName("yieldStar"),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
FunctionEntity get yieldSingle =>
|
|
_env.lookupLocalClassMember(
|
|
_findAsyncHelperClass("_IterationMarker"),
|
|
const PublicName("yieldSingle"),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
FunctionEntity get syncStarUncaughtError =>
|
|
_env.lookupLocalClassMember(
|
|
_findAsyncHelperClass("_IterationMarker"),
|
|
const PublicName("uncaughtError"),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
FunctionEntity get asyncStarHelper =>
|
|
_findAsyncHelperFunction("_asyncStarHelper");
|
|
|
|
FunctionEntity get streamOfController =>
|
|
_findAsyncHelperFunction("_streamOfController");
|
|
|
|
FunctionEntity get endOfIteration =>
|
|
_env.lookupLocalClassMember(
|
|
_findAsyncHelperClass("_IterationMarker"),
|
|
const PublicName("endOfIteration"),
|
|
)
|
|
as FunctionEntity;
|
|
|
|
ClassEntity get syncStarIterable =>
|
|
_findAsyncHelperClass("_SyncStarIterable");
|
|
|
|
late final ClassEntity _syncStarIteratorClass = _findAsyncHelperClass(
|
|
'_SyncStarIterator',
|
|
);
|
|
|
|
late final FieldEntity syncStarIteratorCurrentField = _findClassMember(
|
|
_syncStarIteratorClass,
|
|
'_current',
|
|
);
|
|
|
|
late final FieldEntity syncStarIteratorDatumField = _findClassMember(
|
|
_syncStarIteratorClass,
|
|
'_datum',
|
|
);
|
|
|
|
late final FunctionEntity syncStarIteratorYieldStarMethod = _findClassMember(
|
|
_syncStarIteratorClass,
|
|
'_yieldStar',
|
|
);
|
|
|
|
ClassEntity get futureImplementation => _findAsyncHelperClass('_Future');
|
|
|
|
ClassEntity get controllerStream =>
|
|
_findAsyncHelperClass("_ControllerStream");
|
|
|
|
ClassEntity get streamIterator => _findAsyncHelperClass("StreamIterator");
|
|
|
|
ConstructorEntity get streamIteratorConstructor =>
|
|
_env.lookupConstructor(streamIterator, "")!;
|
|
|
|
late final FunctionEntity syncStarIterableFactory = _findAsyncHelperFunction(
|
|
'_makeSyncStarIterable',
|
|
);
|
|
|
|
late final FunctionEntity asyncAwaitCompleterFactory =
|
|
_findAsyncHelperFunction('_makeAsyncAwaitCompleter');
|
|
|
|
late final FunctionEntity asyncStarStreamControllerFactory =
|
|
_findAsyncHelperFunction('_makeAsyncStarStreamController');
|
|
|
|
// From dart:_interceptors
|
|
ClassEntity _findInterceptorsClass(String name) =>
|
|
_findClass(interceptorsLibrary, name);
|
|
|
|
FunctionEntity _findInterceptorsFunction(String name) =>
|
|
_findLibraryMember(interceptorsLibrary, name)!;
|
|
|
|
late final ClassEntity jsInterceptorClass = _findInterceptorsClass(
|
|
'Interceptor',
|
|
);
|
|
|
|
late final ClassEntity jsStringClass = _findInterceptorsClass('JSString');
|
|
|
|
late final ClassEntity jsArrayClass = _findInterceptorsClass('JSArray');
|
|
|
|
late final ClassEntity jsNumberClass = _findInterceptorsClass('JSNumber');
|
|
|
|
late final ClassEntity jsIntClass = _findInterceptorsClass('JSInt');
|
|
|
|
late final ClassEntity jsNumNotIntClass = _findInterceptorsClass(
|
|
'JSNumNotInt',
|
|
);
|
|
|
|
late final ClassEntity jsNullClass = _findInterceptorsClass('JSNull');
|
|
|
|
late final ClassEntity jsBoolClass = _findInterceptorsClass('JSBool');
|
|
|
|
late final ClassEntity jsPlainJavaScriptObjectClass = _findInterceptorsClass(
|
|
'PlainJavaScriptObject',
|
|
);
|
|
|
|
late final ClassEntity jsUnknownJavaScriptObjectClass =
|
|
_findInterceptorsClass('UnknownJavaScriptObject');
|
|
|
|
late final ClassEntity jsJavaScriptBigIntClass = _findInterceptorsClass(
|
|
'JavaScriptBigInt',
|
|
);
|
|
|
|
late final ClassEntity jsJavaScriptFunctionClass = _findInterceptorsClass(
|
|
'JavaScriptFunction',
|
|
);
|
|
|
|
late final ClassEntity jsJavaScriptSymbolClass = _findInterceptorsClass(
|
|
'JavaScriptSymbol',
|
|
);
|
|
|
|
InterfaceType get jsJavaScriptFunctionType =>
|
|
_getRawType(jsJavaScriptFunctionClass);
|
|
|
|
late final ClassEntity jsLegacyJavaScriptObjectClass = _findInterceptorsClass(
|
|
'LegacyJavaScriptObject',
|
|
);
|
|
|
|
late final ClassEntity jsJavaScriptObjectClass = _findInterceptorsClass(
|
|
'JavaScriptObject',
|
|
);
|
|
|
|
InterfaceType get jsJavaScriptObjectType =>
|
|
_getRawType(jsJavaScriptObjectClass);
|
|
|
|
late final ClassEntity jsIndexableClass = _findInterceptorsClass(
|
|
'JSIndexable',
|
|
);
|
|
|
|
late final ClassEntity jsMutableIndexableClass = _findInterceptorsClass(
|
|
'JSMutableIndexable',
|
|
);
|
|
|
|
late final ClassEntity jsMutableArrayClass = _findInterceptorsClass(
|
|
'JSMutableArray',
|
|
);
|
|
|
|
late final ClassEntity jsFixedArrayClass = _findInterceptorsClass(
|
|
'JSFixedArray',
|
|
);
|
|
|
|
late final ClassEntity jsExtendableArrayClass = _findInterceptorsClass(
|
|
'JSExtendableArray',
|
|
);
|
|
|
|
late final ClassEntity jsUnmodifiableArrayClass = _findInterceptorsClass(
|
|
'JSUnmodifiableArray',
|
|
);
|
|
|
|
late final ClassEntity jsPositiveIntClass = _findInterceptorsClass(
|
|
'JSPositiveInt',
|
|
);
|
|
|
|
late final ClassEntity jsUInt32Class = _findInterceptorsClass('JSUInt32');
|
|
|
|
late final ClassEntity jsUInt31Class = _findInterceptorsClass('JSUInt31');
|
|
|
|
/// Returns `true` member is the 'findIndexForNativeSubclassType' method
|
|
/// declared in `dart:_interceptors`.
|
|
bool isFindIndexForNativeSubclassType(MemberEntity member) {
|
|
return member.name == 'findIndexForNativeSubclassType' &&
|
|
member.isTopLevel &&
|
|
member.library == interceptorsLibrary;
|
|
}
|
|
|
|
late final FunctionEntity getNativeInterceptorMethod =
|
|
_findInterceptorsFunction('getNativeInterceptor');
|
|
|
|
late final ConstructorEntity jsArrayTypedConstructor = _env.lookupConstructor(
|
|
jsArrayClass,
|
|
'typed',
|
|
)!;
|
|
|
|
// From dart:_js_helper
|
|
// TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
|
|
FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
|
|
|
|
FunctionEntity _findHelperFunction(String name) =>
|
|
_findLibraryMember(jsHelperLibrary, name)!;
|
|
|
|
ClassEntity _findHelperClass(String name) =>
|
|
_findClass(jsHelperLibrary, name);
|
|
|
|
FunctionEntity _findLateHelperFunction(String name) =>
|
|
_findLibraryMember(lateHelperLibrary, name)!;
|
|
|
|
late final ClassEntity closureClass = _findHelperClass('Closure');
|
|
|
|
late final ClassEntity closureClass0Args = _findHelperClass('Closure0Args');
|
|
|
|
late final ClassEntity closureClass2Args = _findHelperClass('Closure2Args');
|
|
|
|
late final ClassEntity boundClosureClass = _findHelperClass('BoundClosure');
|
|
|
|
late final ClassEntity typeLiteralClass = _findRtiClass('_Type');
|
|
|
|
late final ClassEntity constMapLiteralClass = _findHelperClass('ConstantMap');
|
|
|
|
late final ClassEntity constSetLiteralClass = _findHelperClass('ConstantSet');
|
|
|
|
/// Base class for all records.
|
|
late final ClassEntity recordBaseClass = _findHelperClass('_Record');
|
|
|
|
/// A function that is used to model the back-end impacts of record lowering
|
|
/// in the front-end.
|
|
late final FunctionEntity recordImpactModel = _findHelperFunction(
|
|
'_recordImpactModel',
|
|
);
|
|
|
|
/// Base class for records with N fields. Can be a fixed-arity class or a
|
|
/// general class that works for any arity.
|
|
ClassEntity recordArityClass(int n) {
|
|
return _findClassOrNull(jsHelperLibrary, '_Record$n') ??
|
|
(n == 0 ? emptyRecordClass : recordGeneralBaseClass);
|
|
}
|
|
|
|
late final ClassEntity recordGeneralBaseClass = _findHelperClass('_RecordN');
|
|
|
|
late final ClassEntity emptyRecordClass = _findHelperClass('_EmptyRecord');
|
|
|
|
late final FunctionEntity recordTestByListHelper = _findHelperFunction(
|
|
'_testRecordValues',
|
|
);
|
|
|
|
late final ClassEntity jsInvocationMirrorClass = _findHelperClass(
|
|
'JSInvocationMirror',
|
|
);
|
|
|
|
late final ClassEntity requiredSentinelClass = _findHelperClass('_Required');
|
|
|
|
InterfaceType get requiredSentinelType => _getRawType(requiredSentinelClass);
|
|
|
|
late final MemberEntity invocationTypeArgumentGetter = _findClassMember(
|
|
jsInvocationMirrorClass,
|
|
'typeArguments',
|
|
);
|
|
|
|
/// Interface used to determine if an object has the JavaScript
|
|
/// indexing behavior. The interface is only visible to specific libraries.
|
|
late final ClassEntity jsIndexingBehaviorInterface = _findHelperClass(
|
|
'JavaScriptIndexingBehavior',
|
|
);
|
|
|
|
late final ClassEntity stackTraceHelperClass = _findHelperClass(
|
|
'_StackTrace',
|
|
);
|
|
|
|
late final ClassEntity constantMapClass = _findHelperClass(
|
|
constant_system.JavaScriptMapConstant.dartClass,
|
|
);
|
|
|
|
late final ClassEntity constantStringMapClass = _findHelperClass(
|
|
constant_system.JavaScriptMapConstant.dartStringClass,
|
|
);
|
|
|
|
late final ClassEntity generalConstantMapClass = _findHelperClass(
|
|
constant_system.JavaScriptMapConstant.dartGeneralClass,
|
|
);
|
|
|
|
late final ClassEntity constantStringSetClass = _findHelperClass(
|
|
constant_system.JavaScriptSetConstant.dartStringClass,
|
|
);
|
|
|
|
late final ClassEntity generalConstantSetClass = _findHelperClass(
|
|
constant_system.JavaScriptSetConstant.dartGeneralClass,
|
|
);
|
|
|
|
late final ClassEntity annotationCreatesClass = _findHelperClass('Creates');
|
|
|
|
late final ClassEntity annotationReturnsClass = _findHelperClass('Returns');
|
|
|
|
late final ClassEntity annotationJSNameClass = _findHelperClass('JSName');
|
|
|
|
/// The class for native annotations defined in dart:_js_helper.
|
|
late final ClassEntity nativeAnnotationClass = _findHelperClass('Native');
|
|
|
|
bool isAssertTest(MemberEntity member) =>
|
|
member.name == 'assertTest' &&
|
|
member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary;
|
|
|
|
late final assertTest = _findHelperFunction('assertTest');
|
|
|
|
late final assertThrow = _findHelperFunction('assertThrow');
|
|
|
|
bool isAssertHelper(MemberEntity member) =>
|
|
member.name == 'assertHelper' &&
|
|
member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary;
|
|
|
|
late final assertHelper = _findHelperFunction('assertHelper');
|
|
|
|
late final assertUnreachableMethod = _findHelperFunction('assertUnreachable');
|
|
|
|
/// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
|
|
/// loaded.
|
|
late final getIsolateAffinityTagMarker = _findHelperFunction(
|
|
'getIsolateAffinityTag',
|
|
);
|
|
|
|
/// Holds the method "requiresPreamble" in _js_helper.
|
|
late final requiresPreambleMarker = _findHelperFunction('requiresPreamble');
|
|
|
|
/// Holds the method "_rawStartupMetrics" in _js_helper.
|
|
late final rawStartupMetrics = _findHelperFunction('rawStartupMetrics');
|
|
|
|
FunctionEntity get loadDeferredLibrary =>
|
|
_findHelperFunction("loadDeferredLibrary");
|
|
|
|
FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
|
|
|
|
FunctionEntity get closureFromTearOff =>
|
|
_findHelperFunction('closureFromTearOff');
|
|
|
|
FunctionEntity get isJsIndexable => _findHelperFunction('isJsIndexable');
|
|
|
|
FunctionEntity get throwIllegalArgumentException =>
|
|
_findHelperFunction('iae');
|
|
|
|
FunctionEntity get throwIndexOutOfRangeException =>
|
|
_findHelperFunction('ioore');
|
|
|
|
FunctionEntity get exceptionUnwrapper =>
|
|
_findHelperFunction('unwrapException');
|
|
|
|
FunctionEntity get throwUnsupportedError =>
|
|
_findHelperFunction('throwUnsupportedError');
|
|
|
|
FunctionEntity get throwTypeError => _findRtiFunction('throwTypeError');
|
|
|
|
/// Recognizes the `checkConcurrentModificationError` helper without needing
|
|
/// it to be resolved.
|
|
bool isCheckConcurrentModificationError(MemberEntity member) {
|
|
return member.name == 'checkConcurrentModificationError' &&
|
|
member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary;
|
|
}
|
|
|
|
late final FunctionEntity checkConcurrentModificationError =
|
|
_findHelperFunction('checkConcurrentModificationError');
|
|
|
|
FunctionEntity get throwConcurrentModificationError =>
|
|
_findHelperFunction('throwConcurrentModificationError');
|
|
|
|
FunctionEntity get stringInterpolationHelper => _findHelperFunction('S');
|
|
|
|
FunctionEntity get initializeExceptionWrapper =>
|
|
_findHelperFunction('initializeExceptionWrapper');
|
|
|
|
FunctionEntity get wrapExceptionHelper =>
|
|
_findHelperFunction('wrapException');
|
|
|
|
FunctionEntity get throwExpressionHelper =>
|
|
_findHelperFunction('throwExpression');
|
|
|
|
FunctionEntity get closureConverter =>
|
|
_findHelperFunction('convertDartClosureToJS');
|
|
|
|
FunctionEntity get traceFromException =>
|
|
_findHelperFunction('getTraceFromException');
|
|
|
|
FunctionEntity get checkDeferredIsLoaded =>
|
|
_findHelperFunction('checkDeferredIsLoaded');
|
|
|
|
FunctionEntity get createRuntimeType => _findRtiFunction('createRuntimeType');
|
|
|
|
FunctionEntity get createInvocationMirror =>
|
|
_findHelperFunction('createInvocationMirror');
|
|
|
|
FunctionEntity get createUnmangledInvocationMirror =>
|
|
_findHelperFunction('createUnmangledInvocationMirror');
|
|
|
|
FunctionEntity get throwUnsupportedOperation =>
|
|
_findHelperFunction('throwUnsupportedOperation');
|
|
|
|
FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
|
|
|
|
FunctionEntity get throwLateFieldNI =>
|
|
_findLateHelperFunction('throwLateFieldNI');
|
|
|
|
FunctionEntity get throwLateFieldAI =>
|
|
_findLateHelperFunction('throwLateFieldAI');
|
|
|
|
FunctionEntity get throwLateFieldADI =>
|
|
_findLateHelperFunction('throwLateFieldADI');
|
|
|
|
FunctionEntity get throwUnnamedLateFieldNI =>
|
|
_findLateHelperFunction('throwUnnamedLateFieldNI');
|
|
|
|
FunctionEntity get throwUnnamedLateFieldAI =>
|
|
_findLateHelperFunction('throwUnnamedLateFieldAI');
|
|
|
|
FunctionEntity get throwUnnamedLateFieldADI =>
|
|
_findLateHelperFunction('throwUnnamedLateFieldADI');
|
|
|
|
bool isExtractTypeArguments(FunctionEntity member) {
|
|
return member.name == 'extractTypeArguments' &&
|
|
member.library == internalLibrary;
|
|
}
|
|
|
|
// TODO(johnniwinther,sra): Support arbitrary type argument count.
|
|
void _checkTypeArgumentCount(int typeArgumentCount) {
|
|
assert(typeArgumentCount > 0);
|
|
if (typeArgumentCount > 20) {
|
|
failedAt(
|
|
noLocationSpannable,
|
|
"Unsupported instantiation argument count: "
|
|
"$typeArgumentCount",
|
|
);
|
|
}
|
|
}
|
|
|
|
ClassEntity getInstantiationClass(int typeArgumentCount) {
|
|
_checkTypeArgumentCount(typeArgumentCount);
|
|
return _findHelperClass('Instantiation$typeArgumentCount');
|
|
}
|
|
|
|
FunctionEntity getInstantiateFunction(int typeArgumentCount) {
|
|
_checkTypeArgumentCount(typeArgumentCount);
|
|
return _findHelperFunction('instantiate$typeArgumentCount');
|
|
}
|
|
|
|
FunctionEntity get convertMainArgumentList =>
|
|
_findHelperFunction('convertMainArgumentList');
|
|
|
|
// From dart:_rti
|
|
|
|
ClassEntity _findRtiClass(String name) => _findClass(rtiLibrary, name);
|
|
|
|
FunctionEntity _findRtiFunction(String name) =>
|
|
_findLibraryMember(rtiLibrary, name)!;
|
|
|
|
late final FunctionEntity interopNullAssertion = _findRtiFunction(
|
|
'_interopNullAssertion',
|
|
);
|
|
|
|
late final FunctionEntity setArrayType = _findRtiFunction('_setArrayType');
|
|
|
|
late final FunctionEntity findType = _findRtiFunction('findType');
|
|
|
|
late final FunctionEntity instanceType = _findRtiFunction('instanceType');
|
|
|
|
late final FunctionEntity arrayInstanceType = _findRtiFunction(
|
|
'_arrayInstanceType',
|
|
);
|
|
|
|
late final FunctionEntity simpleInstanceType = _findRtiFunction(
|
|
'_instanceType',
|
|
);
|
|
|
|
late final FunctionEntity typeLiteralMaker = _findRtiFunction('typeLiteral');
|
|
|
|
late final FunctionEntity checkTypeBound = _findRtiFunction('checkTypeBound');
|
|
|
|
late final FunctionEntity pairwiseIsTest = _findRtiFunction('pairwiseIsTest');
|
|
|
|
ClassEntity get _rtiImplClass => _findRtiClass('Rti');
|
|
|
|
ClassEntity get _rtiUniverseClass => _findRtiClass('_Universe');
|
|
|
|
FieldEntity _findRtiClassField(String name) =>
|
|
_findClassMember(_rtiImplClass, name);
|
|
|
|
late final FieldEntity rtiAsField = _findRtiClassField('_as');
|
|
|
|
late final FieldEntity rtiIsField = _findRtiClassField('_is');
|
|
|
|
late final FieldEntity rtiRestField = _findRtiClassField('_rest');
|
|
|
|
late final FieldEntity rtiPrecomputed1Field = _findRtiClassField(
|
|
'_precomputed1',
|
|
);
|
|
|
|
late final FunctionEntity rtiEvalMethod = _findClassMember(
|
|
_rtiImplClass,
|
|
'_eval',
|
|
);
|
|
|
|
late final FunctionEntity rtiBindMethod = _findClassMember(
|
|
_rtiImplClass,
|
|
'_bind',
|
|
);
|
|
|
|
late final FunctionEntity rtiAddRulesMethod = _findClassMember(
|
|
_rtiUniverseClass,
|
|
'addRules',
|
|
);
|
|
|
|
late final FunctionEntity rtiAddErasedTypesMethod = _findClassMember(
|
|
_rtiUniverseClass,
|
|
'addErasedTypes',
|
|
);
|
|
|
|
late final FunctionEntity rtiAddTypeParameterVariancesMethod =
|
|
_findClassMember(_rtiUniverseClass, 'addTypeParameterVariances');
|
|
|
|
FunctionEntity get installSpecializedIsTest =>
|
|
_findRtiFunction('_installSpecializedIsTest');
|
|
|
|
FunctionEntity get installSpecializedAsCheck =>
|
|
_findRtiFunction('_installSpecializedAsCheck');
|
|
|
|
late final FunctionEntity generalIsTestImplementation = _findRtiFunction(
|
|
'_generalIsTestImplementation',
|
|
);
|
|
|
|
late final FunctionEntity generalNullableIsTestImplementation =
|
|
_findRtiFunction('_generalNullableIsTestImplementation');
|
|
|
|
late final FunctionEntity generalAsCheckImplementation = _findRtiFunction(
|
|
'_generalAsCheckImplementation',
|
|
);
|
|
|
|
late final FunctionEntity generalNullableAsCheckImplementation =
|
|
_findRtiFunction('_generalNullableAsCheckImplementation');
|
|
|
|
late final FunctionEntity specializedIsObject = _findRtiFunction('_isObject');
|
|
|
|
late final FunctionEntity specializedAsObject = _findRtiFunction('_asObject');
|
|
|
|
FunctionEntity get specializedIsTop => _findRtiFunction('_isTop');
|
|
|
|
FunctionEntity get specializedAsTop => _findRtiFunction('_asTop');
|
|
|
|
FunctionEntity get specializedIsBool => _findRtiFunction('_isBool');
|
|
|
|
FunctionEntity get specializedAsBool => _findRtiFunction('_asBool');
|
|
|
|
FunctionEntity get specializedAsBoolNullable => _findRtiFunction('_asBoolQ');
|
|
|
|
FunctionEntity get specializedAsDouble => _findRtiFunction('_asDouble');
|
|
|
|
FunctionEntity get specializedAsDoubleNullable =>
|
|
_findRtiFunction('_asDoubleQ');
|
|
|
|
FunctionEntity get specializedIsInt => _findRtiFunction('_isInt');
|
|
|
|
FunctionEntity get specializedAsInt => _findRtiFunction('_asInt');
|
|
|
|
FunctionEntity get specializedAsIntNullable => _findRtiFunction('_asIntQ');
|
|
|
|
FunctionEntity get specializedIsNum => _findRtiFunction('_isNum');
|
|
|
|
FunctionEntity get specializedAsNum => _findRtiFunction('_asNum');
|
|
|
|
FunctionEntity get specializedAsNumNullable => _findRtiFunction('_asNumQ');
|
|
|
|
FunctionEntity get specializedIsString => _findRtiFunction('_isString');
|
|
|
|
FunctionEntity get specializedAsString => _findRtiFunction('_asString');
|
|
|
|
FunctionEntity get specializedAsStringNullable =>
|
|
_findRtiFunction('_asStringQ');
|
|
|
|
FunctionEntity get instantiatedGenericFunctionType =>
|
|
_findRtiFunction('instantiatedGenericFunctionType');
|
|
|
|
FunctionEntity get closureFunctionType =>
|
|
_findRtiFunction('closureFunctionType');
|
|
|
|
// From dart:_internal
|
|
|
|
late final ClassEntity symbolImplementationClass = _findClass(
|
|
internalLibrary,
|
|
'Symbol',
|
|
);
|
|
|
|
/// Used to annotate items that have the keyword "native".
|
|
late final ClassEntity externalNameClass = _findClass(
|
|
internalLibrary,
|
|
'ExternalName',
|
|
);
|
|
|
|
InterfaceType get externalNameType => _getRawType(externalNameClass);
|
|
|
|
// From dart:_js_embedded_names
|
|
|
|
late final ClassEntity jsGetNameEnum = _findClass(
|
|
sharedEmbeddedNamesLibrary,
|
|
'JsGetName',
|
|
);
|
|
|
|
/// Returns `true` if [member] is a "foreign helper", that is, a member whose
|
|
/// semantics is defined synthetically and not through Dart code.
|
|
///
|
|
/// Most foreign helpers are located in the `dart:_foreign_helper` library.
|
|
bool isForeignHelper(MemberEntity member) {
|
|
return member.library == foreignLibrary ||
|
|
isLateReadCheck(member) ||
|
|
isLateWriteOnceCheck(member) ||
|
|
isLateInitializeOnceCheck(member) ||
|
|
isCreateInvocationMirrorHelper(member);
|
|
}
|
|
|
|
bool _isTopLevelFunctionNamed(String name, MemberEntity member) =>
|
|
member.name == name && member.isFunction && member.isTopLevel;
|
|
|
|
/// Returns `true` if [member] is the `createJsSentinel` function defined in
|
|
/// dart:_foreign_helper.
|
|
bool isCreateJsSentinel(MemberEntity member) =>
|
|
member.library == foreignLibrary &&
|
|
_isTopLevelFunctionNamed('createJsSentinel', member);
|
|
|
|
/// Returns `true` if [member] is the `isJsSentinel` function defined in
|
|
/// dart:_foreign_helper.
|
|
bool isIsJsSentinel(MemberEntity member) =>
|
|
member.library == foreignLibrary &&
|
|
_isTopLevelFunctionNamed('isJsSentinel', member);
|
|
|
|
/// Returns `true` if [member] is the `_lateReadCheck` function defined in
|
|
/// dart:_late_helper.
|
|
bool isLateReadCheck(MemberEntity member) =>
|
|
member.library == lateHelperLibrary &&
|
|
_isTopLevelFunctionNamed('_lateReadCheck', member);
|
|
|
|
/// Returns `true` if [member] is the `_lateWriteOnceCheck` function defined
|
|
/// in dart:_late_helper.
|
|
bool isLateWriteOnceCheck(MemberEntity member) =>
|
|
member.library == lateHelperLibrary &&
|
|
_isTopLevelFunctionNamed('_lateWriteOnceCheck', member);
|
|
|
|
/// Returns `true` if [member] is the `_lateInitializeOnceCheck` function
|
|
/// defined in dart:_late_helper.
|
|
bool isLateInitializeOnceCheck(MemberEntity member) =>
|
|
member.library == lateHelperLibrary &&
|
|
_isTopLevelFunctionNamed('_lateInitializeOnceCheck', member);
|
|
|
|
/// Returns `true` if [member] is the `createSentinel` function defined in
|
|
/// dart:_internal.
|
|
bool isCreateSentinel(MemberEntity member) =>
|
|
member.library == internalLibrary &&
|
|
_isTopLevelFunctionNamed('createSentinel', member);
|
|
|
|
/// Returns `true` if [member] is the `isSentinel` function defined in
|
|
/// dart:_internal.
|
|
bool isIsSentinel(MemberEntity member) =>
|
|
member.library == internalLibrary &&
|
|
_isTopLevelFunctionNamed('isSentinel', member);
|
|
|
|
/// Returns `true` if [member] is the `allowInterop` function defined in
|
|
/// dart:js_util.
|
|
bool isAllowInterop(MemberEntity member) =>
|
|
member.library == dartJsUtilLibrary &&
|
|
_isTopLevelFunctionNamed('allowInterop', member);
|
|
|
|
ClassEntity getDefaultSuperclass(
|
|
ClassEntity cls,
|
|
NativeBasicData nativeBasicData,
|
|
) {
|
|
final defaultedClass = defaultReceiverClass(this, nativeBasicData, cls);
|
|
if (defaultedClass != cls) return defaultedClass;
|
|
// Native classes inherit from Interceptor.
|
|
return nativeBasicData.isNativeClass(cls)
|
|
? jsInterceptorClass
|
|
: objectClass;
|
|
}
|
|
|
|
// From dart:js_util
|
|
late final FunctionEntity? jsAllowInterop = _findLibraryMember(
|
|
dartJsUtilLibrary,
|
|
'allowInterop',
|
|
required: false,
|
|
);
|
|
|
|
bool isCreateInvocationMirrorHelper(MemberEntity member) {
|
|
return member.isTopLevel &&
|
|
member.name == '_createInvocationMirror' &&
|
|
member.library == coreLibrary;
|
|
}
|
|
}
|
|
|
|
class KCommonElements extends CommonElements {
|
|
KCommonElements(super.dartTypes, super.env);
|
|
|
|
// From package:js
|
|
|
|
late final ClassEntity? jsAnnotationClass1 = _findClassOrNull(
|
|
packageJsLibrary,
|
|
'JS',
|
|
);
|
|
|
|
late final ClassEntity? jsAnonymousClass1 = _findClassOrNull(
|
|
packageJsLibrary,
|
|
'_Anonymous',
|
|
);
|
|
|
|
// From dart:_js_annotations
|
|
|
|
late final ClassEntity? jsAnnotationClass2 = _findClassOrNull(
|
|
dartJsAnnotationsLibrary,
|
|
'JS',
|
|
);
|
|
|
|
late final ClassEntity? jsAnonymousClass2 = _findClassOrNull(
|
|
dartJsAnnotationsLibrary,
|
|
'_Anonymous',
|
|
);
|
|
|
|
// From dart:js_interop
|
|
|
|
late final ClassEntity? jsAnnotationClass3 = _findClassOrNull(
|
|
dartJsInteropLibrary,
|
|
'JS',
|
|
);
|
|
|
|
/// Returns `true` if [cls] is a @JS() annotation.
|
|
///
|
|
/// The class can come from either `package:js`, `dart:_js_annotations`, or
|
|
/// `dart:js_interop`.
|
|
bool isJsAnnotationClass(ClassEntity cls) {
|
|
return cls == jsAnnotationClass1 ||
|
|
cls == jsAnnotationClass2 ||
|
|
cls == jsAnnotationClass3;
|
|
}
|
|
|
|
/// Returns `true` if [cls] is an @anonymous annotation.
|
|
///
|
|
/// The class can come from either `package:js` or `dart:_js_annotations`.
|
|
bool isJsAnonymousClass(ClassEntity cls) {
|
|
return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
|
|
}
|
|
|
|
late final ClassEntity pragmaClass = _findClass(coreLibrary, 'pragma');
|
|
|
|
late final FieldEntity pragmaClassNameField = _findClassMember(
|
|
pragmaClass,
|
|
'name',
|
|
);
|
|
|
|
late final FieldEntity pragmaClassOptionsField = _findClassMember(
|
|
pragmaClass,
|
|
'options',
|
|
);
|
|
}
|
|
|
|
class JCommonElements extends CommonElements {
|
|
JCommonElements(super.dartTypes, super.env);
|
|
|
|
/// Returns `true` if [element] is the named constructor of `List`,
|
|
/// e.g. `List.of`.
|
|
///
|
|
/// This will not resolve the constructor if it hasn't been seen yet during
|
|
/// compilation.
|
|
bool isNamedListConstructor(String name, ConstructorEntity element) =>
|
|
element.name == name && element.enclosingClass == listClass;
|
|
|
|
/// Returns `true` if [element] is the named constructor of `JSArray`,
|
|
/// e.g. `JSArray.fixed`.
|
|
///
|
|
/// This will not resolve the constructor if it hasn't been seen yet during
|
|
/// compilation.
|
|
bool isNamedJSArrayConstructor(String name, ConstructorEntity element) =>
|
|
element.name == name && element.enclosingClass == jsArrayClass;
|
|
|
|
bool isDefaultEqualityImplementation(MemberEntity element) {
|
|
assert(element.name == '==');
|
|
ClassEntity? classElement = element.enclosingClass;
|
|
return classElement == objectClass ||
|
|
classElement == jsInterceptorClass ||
|
|
classElement == jsNullClass;
|
|
}
|
|
|
|
/// Returns `true` if [selector] applies to `JSIndexable.length`.
|
|
bool appliesToJsIndexableLength(Selector selector) {
|
|
return selector.name == 'length' && (selector.isGetter || selector.isCall);
|
|
}
|
|
|
|
late final FunctionEntity jsArrayRemoveLast = _findClassMember(
|
|
jsArrayClass,
|
|
'removeLast',
|
|
);
|
|
|
|
late final FunctionEntity jsArrayAdd = _findClassMember(jsArrayClass, 'add');
|
|
|
|
bool _isJsStringClass(ClassEntity cls) {
|
|
return cls.name == 'JSString' && cls.library == interceptorsLibrary;
|
|
}
|
|
|
|
bool isJsStringSplit(MemberEntity member) {
|
|
return member.name == 'split' &&
|
|
member.isInstanceMember &&
|
|
_isJsStringClass(member.enclosingClass!);
|
|
}
|
|
|
|
/// Returns `true` if [selector] applies to `JSString.split` on [receiver]
|
|
/// in the given [world].
|
|
///
|
|
/// Returns `false` if `JSString.split` is not available (e.g. the
|
|
/// method was tree-shaken in an earlier compilation phase).
|
|
bool appliesToJsStringSplit(
|
|
Selector selector,
|
|
AbstractValue? receiver,
|
|
AbstractValueDomain abstractValueDomain,
|
|
) {
|
|
final splitMember = jsStringSplit;
|
|
if (splitMember == null) return false;
|
|
return selector.applies(splitMember) &&
|
|
(receiver == null ||
|
|
abstractValueDomain
|
|
.isTargetingMember(receiver, splitMember, selector.memberName)
|
|
.isPotentiallyTrue);
|
|
}
|
|
|
|
late final FunctionEntity? jsStringSplit = _findClassMemberOrNull(
|
|
jsStringClass,
|
|
'split',
|
|
);
|
|
|
|
late final FunctionEntity jsStringToString = _findClassMember(
|
|
jsStringClass,
|
|
'toString',
|
|
);
|
|
|
|
late final FunctionEntity jsStringOperatorAdd = _findClassMember(
|
|
jsStringClass,
|
|
'+',
|
|
);
|
|
|
|
late final ClassEntity jsConstClass = _findClass(foreignLibrary, 'JS_CONST');
|
|
|
|
/// Return `true` if [member] is the 'checkInt' function defined in
|
|
/// dart:_js_helpers.
|
|
bool isCheckInt(MemberEntity member) {
|
|
return member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary &&
|
|
member.name == 'checkInt';
|
|
}
|
|
|
|
/// Return `true` if [member] is the 'checkNum' function defined in
|
|
/// dart:_js_helpers.
|
|
bool isCheckNum(MemberEntity member) {
|
|
return member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary &&
|
|
member.name == 'checkNum';
|
|
}
|
|
|
|
/// Return `true` if [member] is the 'checkString' function defined in
|
|
/// dart:_js_helpers.
|
|
bool isCheckString(MemberEntity member) {
|
|
return member.isFunction &&
|
|
member.isTopLevel &&
|
|
member.library == jsHelperLibrary &&
|
|
member.name == 'checkString';
|
|
}
|
|
|
|
bool isInstantiationClass(ClassEntity cls) {
|
|
return cls.library == jsHelperLibrary &&
|
|
cls.name != 'Instantiation' &&
|
|
cls.name.startsWith('Instantiation');
|
|
}
|
|
|
|
// From dart:_native_typed_data
|
|
|
|
late final ClassEntity? typedArrayOfIntClass = _findClass(
|
|
typedDataLibrary,
|
|
'NativeTypedArrayOfInt',
|
|
);
|
|
|
|
late final ClassEntity typedArrayOfDoubleClass = _findClass(
|
|
typedDataLibrary,
|
|
'NativeTypedArrayOfDouble',
|
|
);
|
|
|
|
late final ClassEntity jsBuiltinEnum = _findClass(
|
|
sharedEmbeddedNamesLibrary,
|
|
'JsBuiltin',
|
|
);
|
|
|
|
bool isForeign(MemberEntity element) => element.library == foreignLibrary;
|
|
|
|
/// Returns `true` if the implementation of the 'operator ==' [function] is
|
|
/// known to handle `null` as argument.
|
|
bool operatorEqHandlesNullArgument(FunctionEntity function) {
|
|
assert(
|
|
function.name == '==',
|
|
failedAt(function, "Unexpected function $function."),
|
|
);
|
|
ClassEntity? cls = function.enclosingClass;
|
|
return cls == objectClass ||
|
|
cls == jsInterceptorClass ||
|
|
cls == jsNullClass;
|
|
}
|
|
}
|
|
|
|
/// Interface for accessing libraries, classes and members.
|
|
///
|
|
/// The element environment makes private and injected members directly
|
|
/// available and should therefore not be used to determine scopes.
|
|
///
|
|
/// The properties exposed are Dart-centric and should therefore, long-term, not
|
|
/// be used during codegen, expect for mirrors.
|
|
// TODO(johnniwinther): Split this into an element environment and a type query
|
|
// interface, the first should only be used during resolution and the latter in
|
|
// both resolution and codegen.
|
|
abstract class ElementEnvironment {
|
|
IrToElementMap get elementMap;
|
|
|
|
/// Returns the main library for the compilation.
|
|
LibraryEntity? get mainLibrary;
|
|
|
|
/// Returns the main method for the compilation.
|
|
FunctionEntity? get mainFunction;
|
|
|
|
/// Returns all known libraries.
|
|
Iterable<LibraryEntity> get libraries;
|
|
|
|
/// Returns the library name of [library] or '' if the library is unnamed.
|
|
String getLibraryName(LibraryEntity library);
|
|
|
|
/// Lookup the library with the canonical [uri], fail if the library is
|
|
/// missing and [required];
|
|
LibraryEntity? lookupLibrary(Uri uri, {bool required = false});
|
|
|
|
/// Calls [f] for every class declared in [library].
|
|
void forEachClass(LibraryEntity library, void Function(ClassEntity cls) f);
|
|
|
|
/// Lookup the class [name] in [library], fail if the class is missing and
|
|
/// [required].
|
|
ClassEntity? lookupClass(
|
|
LibraryEntity library,
|
|
String name, {
|
|
bool required = false,
|
|
});
|
|
|
|
/// Calls [f] for every top level member in [library].
|
|
void forEachLibraryMember(
|
|
LibraryEntity library,
|
|
void Function(MemberEntity member) f,
|
|
);
|
|
|
|
/// Lookup the member [name] in [library], fail if the class is missing and
|
|
/// [required].
|
|
MemberEntity? lookupLibraryMember(
|
|
LibraryEntity library,
|
|
String name, {
|
|
bool setter = false,
|
|
bool required = false,
|
|
});
|
|
|
|
/// Lookup the member [name] in [cls], fail if the class is missing and
|
|
/// [required].
|
|
MemberEntity? lookupLocalClassMember(
|
|
ClassEntity cls,
|
|
Name name, {
|
|
bool required = false,
|
|
});
|
|
|
|
/// Lookup the member [name] in [cls] and its superclasses.
|
|
///
|
|
/// Return `null` if the member is not found in the class or any superclass.
|
|
MemberEntity? lookupClassMember(ClassEntity cls, Name name) {
|
|
ClassEntity? clsLocal = cls;
|
|
while (clsLocal != null) {
|
|
final entity = lookupLocalClassMember(clsLocal, name);
|
|
if (entity != null) return entity;
|
|
|
|
clsLocal = getSuperClass(clsLocal);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Lookup the constructor [name] in [cls], fail if the class is missing and
|
|
/// [required].
|
|
ConstructorEntity? lookupConstructor(
|
|
ClassEntity cls,
|
|
String name, {
|
|
bool required = false,
|
|
});
|
|
|
|
/// Calls [f] for each class member declared in [cls].
|
|
void forEachLocalClassMember(
|
|
ClassEntity cls,
|
|
void Function(MemberEntity member) f,
|
|
);
|
|
|
|
/// Calls [f] for each class member declared or inherited in [cls] together
|
|
/// with the class that declared the member.
|
|
///
|
|
/// TODO(johnniwinther): This should not include static members of
|
|
/// superclasses.
|
|
void forEachClassMember(
|
|
ClassEntity cls,
|
|
void Function(ClassEntity declarer, MemberEntity member) f,
|
|
);
|
|
|
|
/// Calls [f] for every constructor declared in [cls].
|
|
///
|
|
/// Will ensure that the class and all constructors are resolved if
|
|
/// [ensureResolved] is `true`.
|
|
void forEachConstructor(
|
|
ClassEntity cls,
|
|
void Function(ConstructorEntity constructor) f,
|
|
);
|
|
|
|
/// Returns the superclass of [cls].
|
|
///
|
|
/// If [skipUnnamedMixinApplications] is `true`, unnamed mixin applications
|
|
/// are excluded, for instance for these classes
|
|
///
|
|
/// class S {}
|
|
/// class M {}
|
|
/// class C extends S with M {}
|
|
///
|
|
/// the result of `getSuperClass(C)` is the unnamed mixin application
|
|
/// typically named `S+M` and `getSuperClass(S+M)` is `S`, whereas
|
|
/// the result of `getSuperClass(C, skipUnnamedMixinApplications: false)` is
|
|
/// `S`.
|
|
ClassEntity? getSuperClass(
|
|
ClassEntity cls, {
|
|
bool skipUnnamedMixinApplications = false,
|
|
});
|
|
|
|
/// Calls [f] for each supertype of [cls].
|
|
void forEachSupertype(
|
|
ClassEntity cls,
|
|
void Function(InterfaceType supertype) f,
|
|
);
|
|
|
|
/// Calls [f] for each SuperClass of [cls].
|
|
void forEachSuperClass(
|
|
ClassEntity cls,
|
|
void Function(ClassEntity superClass) f,
|
|
) {
|
|
for (
|
|
var superClass = getSuperClass(cls);
|
|
superClass != null;
|
|
superClass = getSuperClass(superClass)
|
|
) {
|
|
f(superClass);
|
|
}
|
|
}
|
|
|
|
/// Create the instantiation of [cls] with the given [typeArguments] and
|
|
/// [nullability].
|
|
InterfaceType createInterfaceType(
|
|
ClassEntity cls,
|
|
List<DartType> typeArguments,
|
|
);
|
|
|
|
/// Returns the `dynamic` type.
|
|
DartType get dynamicType;
|
|
|
|
/// Returns the 'raw type' of [cls]. That is, the instantiation of [cls]
|
|
/// where all types arguments are `dynamic`.
|
|
InterfaceType getRawType(ClassEntity cls);
|
|
|
|
/// Returns the 'JS-interop type' of [cls]; that is, the instantiation of
|
|
/// [cls] where all type arguments are 'any'.
|
|
InterfaceType getJsInteropType(ClassEntity cls);
|
|
|
|
/// Returns the 'this type' of [cls]. That is, the instantiation of [cls]
|
|
/// where the type arguments are the type variables of [cls].
|
|
InterfaceType getThisType(ClassEntity cls);
|
|
|
|
/// Returns the instantiation of [cls] to bounds.
|
|
InterfaceType getClassInstantiationToBounds(ClassEntity cls);
|
|
|
|
/// Returns `true` if [cls] is generic.
|
|
bool isGenericClass(ClassEntity cls);
|
|
|
|
/// Returns `true` if [cls] is a mixin application (named or unnamed).
|
|
bool isMixinApplication(ClassEntity cls);
|
|
|
|
/// Returns `true` if [cls] is an unnamed mixin application.
|
|
bool isUnnamedMixinApplication(ClassEntity cls);
|
|
|
|
/// The upper bound on the [typeVariable]. If not explicitly declared, this is
|
|
/// `Object`.
|
|
DartType getTypeVariableBound(TypeVariableEntity typeVariable);
|
|
|
|
/// Returns the variances for each type parameter in [cls].
|
|
List<Variance> getTypeVariableVariances(ClassEntity cls);
|
|
|
|
/// Returns the type of [function].
|
|
FunctionType getFunctionType(FunctionEntity function);
|
|
|
|
/// Returns the function type variables defined on [function].
|
|
List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function);
|
|
|
|
/// Returns the type of the [local] function.
|
|
FunctionType getLocalFunctionType(Local local);
|
|
|
|
/// Returns the type of [field].
|
|
DartType getFieldType(FieldEntity field);
|
|
|
|
/// Returns `true` if [cls] is a Dart enum class.
|
|
bool isEnumClass(ClassEntity cls);
|
|
|
|
/// Returns the 'effective' mixin class if [cls] is a mixin application, and
|
|
/// `null` otherwise.
|
|
///
|
|
/// The 'effective' mixin class is the class from which members are mixed in.
|
|
/// Normally this is the mixin class itself, but not if the mixin class itself
|
|
/// is a mixin application.
|
|
///
|
|
/// Consider this hierarchy:
|
|
///
|
|
/// class A {}
|
|
/// class B = Object with A {}
|
|
/// class C = Object with B {}
|
|
///
|
|
/// The mixin classes of `B` and `C` are `A` and `B`, respectively, but the
|
|
/// _effective_ mixin class of both is `A`.
|
|
ClassEntity? getEffectiveMixinClass(ClassEntity cls);
|
|
}
|
|
|
|
abstract class KElementEnvironment extends ElementEnvironment {
|
|
/// Calls [f] for each class that is mixed into [cls] or one of its
|
|
/// superclasses.
|
|
void forEachMixin(ClassEntity cls, void Function(ClassEntity mixin) f);
|
|
|
|
/// Returns the imports seen in [library]
|
|
Iterable<ImportEntity> getImports(LibraryEntity library);
|
|
|
|
/// Returns the metadata constants declared on [member].
|
|
Iterable<ConstantValue> getMemberMetadata(
|
|
MemberEntity member, {
|
|
bool includeParameterMetadata = false,
|
|
});
|
|
|
|
/// `true` if field is the backing field for a `late` or `late final` instance
|
|
/// field.
|
|
bool isLateBackingField(FieldEntity field);
|
|
|
|
/// `true` if field is the backing field for a `late final` instance field. If
|
|
/// this is true, so is [isLateBackingField].
|
|
bool isLateFinalBackingField(FieldEntity field);
|
|
}
|
|
|
|
abstract class JElementEnvironment extends ElementEnvironment {
|
|
/// Calls [f] for each class member added to [cls] during compilation.
|
|
void forEachInjectedClassMember(
|
|
ClassEntity cls,
|
|
void Function(MemberEntity member) f,
|
|
);
|
|
|
|
/// Calls [f] for every constructor body in [cls].
|
|
void forEachConstructorBody(
|
|
ClassEntity cls,
|
|
void Function(ConstructorBodyEntity constructorBody) f,
|
|
);
|
|
|
|
/// Calls [f] for each nested closure in [member].
|
|
void forEachNestedClosure(
|
|
MemberEntity member,
|
|
void Function(FunctionEntity closure) f,
|
|
);
|
|
|
|
/// Returns `true` if [cls] is a mixin application with its own members.
|
|
///
|
|
/// This occurs when a mixin contains methods with super calls or when
|
|
/// the mixin application contains concrete forwarding stubs.
|
|
bool isMixinApplicationWithMembers(ClassEntity cls);
|
|
|
|
/// The default type of the [typeVariable].
|
|
///
|
|
/// This is the type used as the default type argument when no explicit type
|
|
/// argument is passed.
|
|
DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable);
|
|
|
|
/// Returns the 'element' type of a [function] with the async, async* or sync*
|
|
/// marker. [returnType] is the return type of the marked function.
|
|
DartType getAsyncOrSyncStarElementType(
|
|
FunctionEntity function,
|
|
DartType returnType,
|
|
);
|
|
|
|
/// Returns the 'element' type of a function with an async, async* or sync*
|
|
/// marker. The return type of the method is inspected to determine the type
|
|
/// parameter of the Future, Stream or Iterable.
|
|
DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function);
|
|
|
|
/// Returns `true` if [field] has an explicit `covariant` declaration.
|
|
bool isFieldCovariantByDeclaration(FieldEntity field);
|
|
|
|
/// Calls [f] with every instance field, together with its declarer, in an
|
|
/// instance of [cls]. All fields inherited from superclasses and mixins are
|
|
/// included.
|
|
///
|
|
/// If [isElided] is `true`, the field is not read and should therefore not
|
|
/// be emitted.
|
|
void forEachInstanceField(
|
|
ClassEntity cls,
|
|
void Function(ClassEntity declarer, FieldEntity field) f,
|
|
);
|
|
|
|
/// Calls [f] with every instance field declared directly in class [cls]
|
|
/// (i.e. no inherited fields). Fields are presented in initialization
|
|
/// (i.e. textual) order.
|
|
///
|
|
/// If [isElided] is `true`, the field is not read and should therefore not
|
|
/// be emitted.
|
|
void forEachDirectInstanceField(
|
|
ClassEntity cls,
|
|
void Function(FieldEntity field) f,
|
|
);
|
|
|
|
/// Calls [f] for each parameter of [function] providing the type and name of
|
|
/// the parameter and the [defaultValue] if the parameter is optional.
|
|
void forEachParameter(
|
|
covariant FunctionEntity function,
|
|
void Function(DartType type, String? name, ConstantValue? defaultValue) f,
|
|
);
|
|
|
|
/// Calls [f] for each parameter - given as a [Local] - of [function].
|
|
void forEachParameterAsLocal(
|
|
GlobalLocalsMap globalLocalsMap,
|
|
FunctionEntity function,
|
|
void Function(Local parameter) f,
|
|
);
|
|
}
|