mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:11:19 +00:00
[dart:js_interop/ddc/dart2wasm] Refactor inline class to extension types
Does several refactorings now that inline class -> extension type: - InlineExtensionIndex becomes ExtensionIndex - Comments mentioning inline classes now reference extension types - Tests are moved to extension types - Errors now reference extension types instead of inline classes Change-Id: I26ede8e3aaf6bba5f73847238edeed266fc6a043 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317805 Reviewed-by: Sigmund Cherem <sigmund@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
38d30c57e6
commit
d485ef46ce
|
@ -7734,9 +7734,9 @@ const Code<Null> codeJsInteropDartJsInteropAnnotationForStaticInteropOnly =
|
|||
const MessageCode messageJsInteropDartJsInteropAnnotationForStaticInteropOnly =
|
||||
const MessageCode("JsInteropDartJsInteropAnnotationForStaticInteropOnly",
|
||||
problemMessage:
|
||||
r"""The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through inline classes or '@staticInterop'.""",
|
||||
r"""The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through extension types or '@staticInterop' classes.""",
|
||||
correctionMessage:
|
||||
r"""Try making this class an inline class or marking it as '@staticInterop'.""");
|
||||
r"""Try making this class an extension type or marking it as '@staticInterop'.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropEnclosingClassJSAnnotation =
|
||||
|
@ -7909,6 +7909,30 @@ Message _withArgumentsJsInteropExportNoExportableMembers(String name) {
|
|||
arguments: {'name': name});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropExtensionTypeMemberNotInterop =
|
||||
messageJsInteropExtensionTypeMemberNotInterop;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageJsInteropExtensionTypeMemberNotInterop = const MessageCode(
|
||||
"JsInteropExtensionTypeMemberNotInterop",
|
||||
problemMessage:
|
||||
r"""Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type.""",
|
||||
correctionMessage:
|
||||
r"""Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop extension types.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropExtensionTypeUsedWithWrongJsAnnotation =
|
||||
messageJsInteropExtensionTypeUsedWithWrongJsAnnotation;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageJsInteropExtensionTypeUsedWithWrongJsAnnotation =
|
||||
const MessageCode("JsInteropExtensionTypeUsedWithWrongJsAnnotation",
|
||||
problemMessage:
|
||||
r"""Extension types should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'.""",
|
||||
correctionMessage:
|
||||
r"""Try using the '@JS' annotation from 'dart:js_interop' annotation on this extension type instead.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropExternalExtensionMemberOnTypeInvalid =
|
||||
messageJsInteropExternalExtensionMemberOnTypeInvalid;
|
||||
|
@ -7944,30 +7968,6 @@ const MessageCode messageJsInteropExternalMemberNotJSAnnotated = const MessageCo
|
|||
correctionMessage:
|
||||
r"""Try removing the 'external' keyword or adding a JS interop annotation.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropInlineClassMemberNotInterop =
|
||||
messageJsInteropInlineClassMemberNotInterop;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageJsInteropInlineClassMemberNotInterop = const MessageCode(
|
||||
"JsInteropInlineClassMemberNotInterop",
|
||||
problemMessage:
|
||||
r"""Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.""",
|
||||
correctionMessage:
|
||||
r"""Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop inline types.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropInlineClassUsedWithWrongJsAnnotation =
|
||||
messageJsInteropInlineClassUsedWithWrongJsAnnotation;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageJsInteropInlineClassUsedWithWrongJsAnnotation =
|
||||
const MessageCode("JsInteropInlineClassUsedWithWrongJsAnnotation",
|
||||
problemMessage:
|
||||
r"""Inline classes should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'.""",
|
||||
correctionMessage:
|
||||
r"""Try using the '@JS' annotation from 'dart:js_interop' annotation on this inline class instead.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeJsInteropInvalidStaticClassMemberName =
|
||||
messageJsInteropInvalidStaticClassMemberName;
|
||||
|
|
|
@ -11,11 +11,11 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
|
|||
messageJsInteropDartJsInteropAnnotationForStaticInteropOnly,
|
||||
messageJsInteropEnclosingClassJSAnnotation,
|
||||
messageJsInteropEnclosingClassJSAnnotationContext,
|
||||
messageJsInteropExtensionTypeMemberNotInterop,
|
||||
messageJsInteropExtensionTypeUsedWithWrongJsAnnotation,
|
||||
messageJsInteropExternalExtensionMemberOnTypeInvalid,
|
||||
messageJsInteropExternalExtensionMemberWithStaticDisallowed,
|
||||
messageJsInteropExternalMemberNotJSAnnotated,
|
||||
messageJsInteropInlineClassMemberNotInterop,
|
||||
messageJsInteropInlineClassUsedWithWrongJsAnnotation,
|
||||
messageJsInteropInvalidStaticClassMemberName,
|
||||
messageJsInteropNamedParameters,
|
||||
messageJsInteropNonExternalConstructor,
|
||||
|
@ -46,8 +46,8 @@ import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
|
|||
import 'package:front_end/src/api_prototype/lowering_predicates.dart';
|
||||
import 'package:front_end/src/fasta/fasta_codes.dart'
|
||||
show
|
||||
templateJsInteropExtensionTypeNotInterop,
|
||||
templateJsInteropFunctionToJSRequiresStaticType,
|
||||
templateJsInteropInlineClassNotInterop,
|
||||
templateJsInteropStrictModeViolation;
|
||||
|
||||
import 'package:kernel/class_hierarchy.dart';
|
||||
|
@ -61,8 +61,8 @@ import 'src/js_interop.dart';
|
|||
class JsInteropChecks extends RecursiveVisitor {
|
||||
final Set<Constant> _constantCache = {};
|
||||
final CoreTypes _coreTypes;
|
||||
late final ExtensionIndex _extensionIndex;
|
||||
final Procedure _functionToJSTarget;
|
||||
late final InlineExtensionIndex _inlineExtensionIndex;
|
||||
// Errors on constants need source information, so we use the surrounding
|
||||
// `ConstantExpression` as the source.
|
||||
ConstantExpression? _lastConstantExpression;
|
||||
|
@ -150,10 +150,9 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
|
||||
_staticTypeContext = StatefulStaticTypeContext.stacked(
|
||||
TypeEnvironment(_coreTypes, hierarchy)) {
|
||||
_inlineExtensionIndex =
|
||||
InlineExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
_typeParameterBoundChecker =
|
||||
_TypeParameterBoundChecker(_inlineExtensionIndex);
|
||||
_extensionIndex =
|
||||
ExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
_typeParameterBoundChecker = _TypeParameterBoundChecker(_extensionIndex);
|
||||
}
|
||||
|
||||
/// Verifies given [member] is an external extension member on a static
|
||||
|
@ -197,13 +196,13 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
@override
|
||||
void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
|
||||
if (hasPackageJSAnnotation(node)) {
|
||||
_reporter.report(messageJsInteropInlineClassUsedWithWrongJsAnnotation,
|
||||
_reporter.report(messageJsInteropExtensionTypeUsedWithWrongJsAnnotation,
|
||||
node.fileOffset, node.name.length, node.fileUri);
|
||||
}
|
||||
if (hasDartJSInteropAnnotation(node) &&
|
||||
!_inlineExtensionIndex.isInteropInlineClass(node)) {
|
||||
!_extensionIndex.isInteropExtensionType(node)) {
|
||||
_reporter.report(
|
||||
templateJsInteropInlineClassNotInterop.withArguments(
|
||||
templateJsInteropExtensionTypeNotInterop.withArguments(
|
||||
node.name, node.declaredRepresentationType, true),
|
||||
node.fileOffset,
|
||||
node.name.length,
|
||||
|
@ -257,8 +256,8 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
_checkSuperclassOfStaticInteropClass(node, supertype.classNode);
|
||||
}
|
||||
} else {
|
||||
// For non-inline classes, `dart:js_interop`'s `@JS` can only be used
|
||||
// with `@staticInterop`.
|
||||
// For classes, `dart:js_interop`'s `@JS` can only be used with
|
||||
// `@staticInterop`.
|
||||
if (hasDartJSInteropAnnotation(node)) {
|
||||
report(messageJsInteropDartJsInteropAnnotationForStaticInteropOnly);
|
||||
}
|
||||
|
@ -324,7 +323,7 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
message, node.fileOffset, node.name.text.length, node.fileUri);
|
||||
|
||||
// TODO(joshualitt): Add a check that only supported operators are allowed
|
||||
// in external extension members / inline classes.
|
||||
// in external extension members and extension types.
|
||||
_checkInstanceMemberJSAnnotation(node);
|
||||
if (_classHasJSAnnotation &&
|
||||
!node.isExternal &&
|
||||
|
@ -345,9 +344,9 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
// can only have named parameters, and every other interop member can only
|
||||
// have positional parameters.
|
||||
final isObjectLiteralConstructor = node.isExtensionTypeMember &&
|
||||
(_inlineExtensionIndex.getInlineDescriptor(node)!.kind ==
|
||||
(_extensionIndex.getExtensionTypeDescriptor(node)!.kind ==
|
||||
ExtensionTypeMemberKind.Constructor ||
|
||||
_inlineExtensionIndex.getInlineDescriptor(node)!.kind ==
|
||||
_extensionIndex.getExtensionTypeDescriptor(node)!.kind ==
|
||||
ExtensionTypeMemberKind.Factory) &&
|
||||
node.function.namedParameters.isNotEmpty;
|
||||
final isAnonymousFactory = _classHasAnonymousAnnotation && node.isFactory;
|
||||
|
@ -386,13 +385,13 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
_checkNoParamInitializersForStaticInterop(node.function);
|
||||
late Annotatable? annotatable;
|
||||
if (node.isExtensionTypeMember) {
|
||||
annotatable = _inlineExtensionIndex.getInlineClass(node);
|
||||
annotatable = _extensionIndex.getExtensionType(node);
|
||||
} else if (node.isExtensionMember) {
|
||||
annotatable = _inlineExtensionIndex.getExtensionAnnotatable(node);
|
||||
annotatable = _extensionIndex.getExtensionAnnotatable(node);
|
||||
if (annotatable != null) {
|
||||
// We do not support external extension members with the 'static'
|
||||
// keyword currently.
|
||||
if (_inlineExtensionIndex.getExtensionDescriptor(node)!.isStatic) {
|
||||
if (_extensionIndex.getExtensionDescriptor(node)!.isStatic) {
|
||||
report(
|
||||
messageJsInteropExternalExtensionMemberWithStaticDisallowed);
|
||||
}
|
||||
|
@ -633,16 +632,15 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
if (member.isExternal) {
|
||||
if (_isAllowedExternalUsage(member)) return;
|
||||
if (member.isExtensionMember) {
|
||||
final annotatable =
|
||||
_inlineExtensionIndex.getExtensionAnnotatable(member);
|
||||
final annotatable = _extensionIndex.getExtensionAnnotatable(member);
|
||||
if (annotatable == null) {
|
||||
_reporter.report(messageJsInteropExternalExtensionMemberOnTypeInvalid,
|
||||
member.fileOffset, member.name.text.length, member.fileUri);
|
||||
}
|
||||
} else if (member.isExtensionTypeMember) {
|
||||
final inlineClass = _inlineExtensionIndex.getInlineClass(member);
|
||||
if (inlineClass == null) {
|
||||
_reporter.report(messageJsInteropInlineClassMemberNotInterop,
|
||||
final extensionType = _extensionIndex.getExtensionType(member);
|
||||
if (extensionType == null) {
|
||||
_reporter.report(messageJsInteropExtensionTypeMemberNotInterop,
|
||||
member.fileOffset, member.name.text.length, member.fileUri);
|
||||
}
|
||||
} else if (!hasJSInteropAnnotation(member)) {
|
||||
|
@ -660,11 +658,11 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
///
|
||||
/// Tear-offs of the following are disallowed when using dart:js_interop:
|
||||
///
|
||||
/// - External inline class constructors and factories (TODO(srujzs): Add
|
||||
/// - External extension type constructors and factories (TODO(srujzs): Add
|
||||
/// checks for factories once they're added.)
|
||||
/// - External factories of @staticInterop classes
|
||||
/// - External interop inline methods
|
||||
/// - External interop extension methods on @staticInterop or inline classes
|
||||
/// - External interop extension type methods
|
||||
/// - External interop extension methods on @staticInterop or extension types
|
||||
/// - Synthetic generative @staticInterop constructors
|
||||
/// - External top-level methods
|
||||
///
|
||||
|
@ -675,22 +673,21 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
var memberKind = '';
|
||||
var memberName = '';
|
||||
if (member.isExtensionTypeMember) {
|
||||
// Inline class interop members can not be torn off.
|
||||
if (_inlineExtensionIndex.getInlineClass(member) == null) {
|
||||
// Extension type interop members can not be torn off.
|
||||
if (_extensionIndex.getExtensionType(member) == null) {
|
||||
return false;
|
||||
}
|
||||
memberKind = 'inline class interop member';
|
||||
memberKind = 'extension type interop member';
|
||||
memberName =
|
||||
_inlineExtensionIndex.getInlineDescriptor(member)!.name.text;
|
||||
_extensionIndex.getExtensionTypeDescriptor(member)!.name.text;
|
||||
if (memberName.isEmpty) memberName = 'new';
|
||||
} else if (member.isExtensionMember) {
|
||||
// JS interop members can not be torn off.
|
||||
if (_inlineExtensionIndex.getExtensionAnnotatable(member) == null) {
|
||||
if (_extensionIndex.getExtensionAnnotatable(member) == null) {
|
||||
return false;
|
||||
}
|
||||
memberKind = 'extension interop member';
|
||||
memberName =
|
||||
_inlineExtensionIndex.getExtensionDescriptor(member)!.name.text;
|
||||
memberName = _extensionIndex.getExtensionDescriptor(member)!.name.text;
|
||||
} else if (member.enclosingClass != null) {
|
||||
// @staticInterop members can not be torn off.
|
||||
final enclosingClass = member.enclosingClass!;
|
||||
|
@ -775,14 +772,14 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
var isInvalidOperator = false;
|
||||
var operatorHasRenaming = false;
|
||||
if ((node.isExtensionTypeMember &&
|
||||
_inlineExtensionIndex.getInlineDescriptor(node)?.kind ==
|
||||
_extensionIndex.getExtensionTypeDescriptor(node)?.kind ==
|
||||
ExtensionTypeMemberKind.Operator) ||
|
||||
(node.isExtensionMember &&
|
||||
_inlineExtensionIndex.getExtensionDescriptor(node)?.kind ==
|
||||
_extensionIndex.getExtensionDescriptor(node)?.kind ==
|
||||
ExtensionMemberKind.Operator)) {
|
||||
final operator =
|
||||
_inlineExtensionIndex.getInlineDescriptor(node)?.name.text ??
|
||||
_inlineExtensionIndex.getExtensionDescriptor(node)?.name.text;
|
||||
_extensionIndex.getExtensionTypeDescriptor(node)?.name.text ??
|
||||
_extensionIndex.getExtensionDescriptor(node)?.name.text;
|
||||
isInvalidOperator = operator != '[]' && operator != '[]=';
|
||||
operatorHasRenaming = getJSName(node).isNotEmpty;
|
||||
} else if (!node.isStatic && node.kind == ProcedureKind.Operator) {
|
||||
|
@ -893,8 +890,8 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
/// Otherwise, return null.
|
||||
Member? _getTornOffFromGeneratedTearOff(Procedure procedure) {
|
||||
final tornOff =
|
||||
_inlineExtensionIndex.getInlineMemberForTearOff(procedure) ??
|
||||
_inlineExtensionIndex.getExtensionMemberForTearOff(procedure);
|
||||
_extensionIndex.getExtensionTypeMemberForTearOff(procedure) ??
|
||||
_extensionIndex.getExtensionMemberForTearOff(procedure);
|
||||
if (tornOff != null) return tornOff.asMember;
|
||||
final name = extractConstructorNameFromTearOff(procedure.name);
|
||||
if (name == null) return null;
|
||||
|
@ -923,17 +920,17 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
/// which can be:
|
||||
/// - inside a JS interop class
|
||||
/// - inside an extension on a JS interop or @Native annotatable
|
||||
/// - inside a JS interop inline class
|
||||
/// - inside a JS interop extension type
|
||||
/// - a top level member that is JS interop annotated or in a package:js JS
|
||||
/// interop library
|
||||
bool _isJSInteropMember(Member member) {
|
||||
if (member.isExternal) {
|
||||
if (_classHasJSAnnotation) return true;
|
||||
if (member.isExtensionMember) {
|
||||
return _inlineExtensionIndex.getExtensionAnnotatable(member) != null;
|
||||
return _extensionIndex.getExtensionAnnotatable(member) != null;
|
||||
}
|
||||
if (member.isExtensionTypeMember) {
|
||||
return _inlineExtensionIndex.getInlineClass(member) != null;
|
||||
return _extensionIndex.getExtensionType(member) != null;
|
||||
}
|
||||
if (member.enclosingClass == null) {
|
||||
// dart:js_interop requires top-levels to be @JS-annotated. package:js
|
||||
|
@ -965,8 +962,8 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
(type is InterfaceType &&
|
||||
hasStaticInteropAnnotation(type.classNode)) ||
|
||||
(type is ExtensionType &&
|
||||
_inlineExtensionIndex
|
||||
.isInteropInlineClass(type.extensionTypeDeclaration)))) {
|
||||
_extensionIndex
|
||||
.isInteropExtensionType(type.extensionTypeDeclaration)))) {
|
||||
_reporter.report(
|
||||
templateJsInteropStrictModeViolation.withArguments(type, true),
|
||||
node.fileOffset,
|
||||
|
@ -986,9 +983,9 @@ class JsInteropChecks extends RecursiveVisitor {
|
|||
/// Visitor used to check that all usages of type parameter types of an external
|
||||
/// static interop member is a valid static interop type.
|
||||
class _TypeParameterBoundChecker extends RecursiveVisitor {
|
||||
final InlineExtensionIndex _inlineExtensionIndex;
|
||||
final ExtensionIndex _extensionIndex;
|
||||
|
||||
_TypeParameterBoundChecker(this._inlineExtensionIndex);
|
||||
_TypeParameterBoundChecker(this._extensionIndex);
|
||||
|
||||
bool _containsInvalidTypeBound = false;
|
||||
|
||||
|
@ -1011,8 +1008,9 @@ class _TypeParameterBoundChecker extends RecursiveVisitor {
|
|||
|
||||
@override
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
if (_inlineExtensionIndex
|
||||
.isInteropInlineClass(node.extensionTypeDeclaration)) return;
|
||||
if (_extensionIndex.isInteropExtensionType(node.extensionTypeDeclaration)) {
|
||||
return;
|
||||
}
|
||||
super.visitExtensionType(node);
|
||||
}
|
||||
|
||||
|
@ -1020,8 +1018,8 @@ class _TypeParameterBoundChecker extends RecursiveVisitor {
|
|||
void visitTypeParameterType(TypeParameterType node) {
|
||||
final bound = node.bound;
|
||||
if (bound is ExtensionType &&
|
||||
!_inlineExtensionIndex
|
||||
.isInteropInlineClass(bound.extensionTypeDeclaration)) {
|
||||
!_extensionIndex
|
||||
.isInteropExtensionType(bound.extensionTypeDeclaration)) {
|
||||
_containsInvalidTypeBound = true;
|
||||
}
|
||||
if (bound is InterfaceType &&
|
||||
|
|
|
@ -65,7 +65,7 @@ class JsUtilOptimizer extends Transformer {
|
|||
final CoreTypes _coreTypes;
|
||||
final StatefulStaticTypeContext _staticTypeContext;
|
||||
|
||||
late final InlineExtensionIndex _inlineExtensionIndex;
|
||||
late final ExtensionIndex _extensionIndex;
|
||||
|
||||
JsUtilOptimizer(this._coreTypes, ClassHierarchy hierarchy)
|
||||
: _callMethodTarget =
|
||||
|
@ -108,8 +108,8 @@ class JsUtilOptimizer extends Transformer {
|
|||
_coreTypes.index.getProcedure('dart:core', 'List', 'empty'),
|
||||
_staticTypeContext = StatefulStaticTypeContext.stacked(
|
||||
TypeEnvironment(_coreTypes, hierarchy)) {
|
||||
_inlineExtensionIndex =
|
||||
InlineExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
_extensionIndex =
|
||||
ExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -136,15 +136,15 @@ class JsUtilOptimizer extends Transformer {
|
|||
/// returns null.
|
||||
_InvocationBuilder? _getExternalInvocationBuilder(Procedure node) {
|
||||
if (node.isExternal) {
|
||||
if (_inlineExtensionIndex.isInstanceInteropMember(node)) {
|
||||
var shouldTrustType = _inlineExtensionIndex.isTrustTypesMember(node);
|
||||
if (_inlineExtensionIndex.isGetter(node)) {
|
||||
if (_extensionIndex.isInstanceInteropMember(node)) {
|
||||
var shouldTrustType = _extensionIndex.isTrustTypesMember(node);
|
||||
if (_extensionIndex.isGetter(node)) {
|
||||
return _getExternalGetterInvocationBuilder(node, shouldTrustType);
|
||||
} else if (_inlineExtensionIndex.isSetter(node)) {
|
||||
} else if (_extensionIndex.isSetter(node)) {
|
||||
return _getExternalSetterInvocationBuilder(node);
|
||||
} else if (_inlineExtensionIndex.isMethod(node)) {
|
||||
} else if (_extensionIndex.isMethod(node)) {
|
||||
return _getExternalMethodInvocationBuilder(node, shouldTrustType);
|
||||
} else if (_inlineExtensionIndex.isOperator(node)) {
|
||||
} else if (_extensionIndex.isOperator(node)) {
|
||||
return _getExternalOperatorInvocationBuilder(node, shouldTrustType);
|
||||
}
|
||||
} else {
|
||||
|
@ -156,15 +156,15 @@ class JsUtilOptimizer extends Transformer {
|
|||
node, dottedPrefix.isEmpty ? [] : dottedPrefix.split('.'));
|
||||
var shouldTrustType = node.enclosingClass != null &&
|
||||
hasTrustTypesAnnotation(node.enclosingClass!);
|
||||
if (_inlineExtensionIndex.isGetter(node)) {
|
||||
if (_extensionIndex.isGetter(node)) {
|
||||
return _getExternalGetterInvocationBuilder(
|
||||
node, shouldTrustType, receiver);
|
||||
} else if (_inlineExtensionIndex.isSetter(node)) {
|
||||
} else if (_extensionIndex.isSetter(node)) {
|
||||
return _getExternalSetterInvocationBuilder(node, receiver);
|
||||
} else if (_inlineExtensionIndex.isMethod(node)) {
|
||||
} else if (_extensionIndex.isMethod(node)) {
|
||||
return _getExternalMethodInvocationBuilder(
|
||||
node, shouldTrustType, receiver);
|
||||
} else if (_inlineExtensionIndex.isNonLiteralConstructor(node)) {
|
||||
} else if (_extensionIndex.isNonLiteralConstructor(node)) {
|
||||
// Get the constructor object using the class name.
|
||||
return _getExternalConstructorInvocationBuilder(
|
||||
node, _getObjectOffGlobalThis(node, dottedPrefix.split('.')));
|
||||
|
@ -182,8 +182,8 @@ class JsUtilOptimizer extends Transformer {
|
|||
/// 1. A top-level member
|
||||
/// 2. A `@staticInterop` factory
|
||||
/// 3. A `@staticInterop` static member
|
||||
/// 4. A `@JS` inline class constructor
|
||||
/// 5. A `@JS` inline class static member
|
||||
/// 4. A `@JS` extension type constructor
|
||||
/// 5. A `@JS` extension type static member
|
||||
String? _getDottedPrefixForStaticallyResolvableMember(Procedure node) {
|
||||
if (!node.isExternal || node.isExtensionMember) return null;
|
||||
|
||||
|
@ -206,14 +206,14 @@ class JsUtilOptimizer extends Transformer {
|
|||
} else {
|
||||
Annotatable enclosingClass;
|
||||
if (node.isExtensionTypeMember) {
|
||||
var descriptor = _inlineExtensionIndex.getInlineDescriptor(node);
|
||||
var descriptor = _extensionIndex.getExtensionTypeDescriptor(node);
|
||||
if (descriptor == null ||
|
||||
(!descriptor.isStatic &&
|
||||
descriptor.kind != ExtensionTypeMemberKind.Constructor &&
|
||||
descriptor.kind != ExtensionTypeMemberKind.Factory)) {
|
||||
return null;
|
||||
}
|
||||
enclosingClass = _inlineExtensionIndex.getInlineClass(node)!;
|
||||
enclosingClass = _extensionIndex.getExtensionType(node)!;
|
||||
} else if (node.enclosingClass != null &&
|
||||
hasStaticInteropAnnotation(node.enclosingClass!)) {
|
||||
if (!node.isFactory && !node.isStatic) return null;
|
||||
|
@ -221,7 +221,7 @@ class JsUtilOptimizer extends Transformer {
|
|||
} else {
|
||||
return null;
|
||||
}
|
||||
// `@staticInterop` or `@JS` inline class
|
||||
// `@staticInterop` or `@JS` extension type
|
||||
// factory/constructor/static member, use the class name as part of the
|
||||
// dotted prefix.
|
||||
var className = getJSName(enclosingClass);
|
||||
|
@ -273,13 +273,13 @@ class JsUtilOptimizer extends Transformer {
|
|||
[Expression? maybeReceiver]) {
|
||||
final target =
|
||||
shouldTrustType ? _getPropertyTrustTypeTarget : _getPropertyTarget;
|
||||
final isOperator = _inlineExtensionIndex.isOperator(node);
|
||||
final isOperator = _extensionIndex.isOperator(node);
|
||||
final isInstanceInteropMember =
|
||||
_inlineExtensionIndex.isInstanceInteropMember(node);
|
||||
_extensionIndex.isInstanceInteropMember(node);
|
||||
final name = _getMemberJSName(node);
|
||||
return (Arguments arguments, Expression invocation) {
|
||||
// Parameter `this` only exists for inline and extension instance members.
|
||||
// Operators take a `this` and an index.
|
||||
// Parameter `this` only exists for extension and extension type instance
|
||||
// members. Operators take a `this` and an index.
|
||||
final positionalArgs = arguments.positional;
|
||||
assert(positionalArgs.length ==
|
||||
(isOperator
|
||||
|
@ -310,13 +310,13 @@ class JsUtilOptimizer extends Transformer {
|
|||
/// positional argument as the receiver for `js_util.setProperty`.
|
||||
_InvocationBuilder _getExternalSetterInvocationBuilder(Procedure node,
|
||||
[Expression? maybeReceiver]) {
|
||||
final isOperator = _inlineExtensionIndex.isOperator(node);
|
||||
final isOperator = _extensionIndex.isOperator(node);
|
||||
final isInstanceInteropMember =
|
||||
_inlineExtensionIndex.isInstanceInteropMember(node);
|
||||
_extensionIndex.isInstanceInteropMember(node);
|
||||
final name = _getMemberJSName(node);
|
||||
return (Arguments arguments, Expression invocation) {
|
||||
// Parameter `this` only exists for inline and extension instance members.
|
||||
// Operators take a `this`, an index, and a value.
|
||||
// Parameter `this` only exists for extension and extension type instance
|
||||
// members. Operators take a `this`, an index, and a value.
|
||||
final positionalArgs = arguments.positional;
|
||||
assert(positionalArgs.length ==
|
||||
(isOperator
|
||||
|
@ -353,7 +353,7 @@ class JsUtilOptimizer extends Transformer {
|
|||
final target =
|
||||
shouldTrustType ? _callMethodTrustTypeTarget : _callMethodTarget;
|
||||
final isInstanceInteropMember =
|
||||
_inlineExtensionIndex.isInstanceInteropMember(node);
|
||||
_extensionIndex.isInstanceInteropMember(node);
|
||||
final name = _getMemberJSName(node);
|
||||
return (Arguments arguments, Expression invocation) {
|
||||
var positional = arguments.positional;
|
||||
|
@ -361,7 +361,7 @@ class JsUtilOptimizer extends Transformer {
|
|||
? positional.first
|
||||
: _cloner.clone(maybeReceiver);
|
||||
if (isInstanceInteropMember) {
|
||||
// Ignore `this` for inline and extension members.
|
||||
// Ignore `this` for extension and extension type members.
|
||||
positional = positional.sublist(1);
|
||||
}
|
||||
final callMethodInvocation = StaticInvocation(
|
||||
|
@ -386,8 +386,8 @@ class JsUtilOptimizer extends Transformer {
|
|||
_InvocationBuilder? _getExternalOperatorInvocationBuilder(
|
||||
Procedure node, bool shouldTrustType) {
|
||||
final operator =
|
||||
_inlineExtensionIndex.getInlineDescriptor(node)?.name.text ??
|
||||
_inlineExtensionIndex.getExtensionDescriptor(node)?.name.text;
|
||||
_extensionIndex.getExtensionTypeDescriptor(node)?.name.text ??
|
||||
_extensionIndex.getExtensionDescriptor(node)?.name.text;
|
||||
switch (operator) {
|
||||
case '[]':
|
||||
return _getExternalGetterInvocationBuilder(node, shouldTrustType);
|
||||
|
@ -423,7 +423,7 @@ class JsUtilOptimizer extends Transformer {
|
|||
/// Returns the underlying JS name.
|
||||
///
|
||||
/// Returns either the name from the `@JS` annotation if non-empty, or the
|
||||
/// declared name of the member. In the case of an extension or inline class
|
||||
/// declared name of the member. In the case of an extension or extension type
|
||||
/// member, this does not return the CFE generated name for the top level
|
||||
/// member, but rather the name of the original member.
|
||||
String _getMemberJSName(Procedure node) {
|
||||
|
@ -434,9 +434,9 @@ class JsUtilOptimizer extends Transformer {
|
|||
// receiver to the lowerings. Here, we just take the final identifier.
|
||||
return jsAnnotationName.split('.').last;
|
||||
} else if (node.isExtensionMember) {
|
||||
return _inlineExtensionIndex.getExtensionDescriptor(node)!.name.text;
|
||||
return _extensionIndex.getExtensionDescriptor(node)!.name.text;
|
||||
} else if (node.isExtensionTypeMember) {
|
||||
return _inlineExtensionIndex.getInlineDescriptor(node)!.name.text;
|
||||
return _extensionIndex.getExtensionTypeDescriptor(node)!.name.text;
|
||||
} else {
|
||||
return node.name.text;
|
||||
}
|
||||
|
@ -678,27 +678,28 @@ class JsUtilOptimizer extends Transformer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Lazily-initialized indexes for extension and inline class interop members.
|
||||
/// Lazily-initialized indexes for extension and extension type interop members.
|
||||
///
|
||||
/// As the query APIs are called, we process the enclosing libraries of the
|
||||
/// member in question if needed. We only process JS interop inline classes and
|
||||
/// member in question if needed. We only process JS interop extension types and
|
||||
/// extensions on either JS interop or @Native classes.
|
||||
class InlineExtensionIndex {
|
||||
class ExtensionIndex {
|
||||
final CoreTypes _coreTypes;
|
||||
final Map<Reference, Annotatable> _extensionAnnotatableIndex = {};
|
||||
final Map<Reference, Extension> _extensionIndex = {};
|
||||
final Map<Reference, ExtensionMemberDescriptor> _extensionMemberIndex = {};
|
||||
final Map<Reference, Reference> _extensionTearOffIndex = {};
|
||||
final Map<Reference, ExtensionTypeDeclaration> _inlineClassIndex = {};
|
||||
final Map<Reference, ExtensionTypeMemberDescriptor> _inlineMemberIndex = {};
|
||||
final Map<Reference, Reference> _inlineTearOffIndex = {};
|
||||
final Map<Reference, bool> _interopInlineClassIndex = {};
|
||||
final Map<Reference, ExtensionTypeDeclaration> _extensionTypeIndex = {};
|
||||
final Map<Reference, ExtensionTypeMemberDescriptor>
|
||||
_extensionTypeMemberIndex = {};
|
||||
final Map<Reference, Reference> _extensionTypeTearOffIndex = {};
|
||||
final Map<Reference, bool> _interopExtensionTypeIndex = {};
|
||||
final Set<Library> _processedExtensionLibraries = {};
|
||||
final Set<Library> _processedInlineLibraries = {};
|
||||
final Set<Library> _processedExtensionTypeLibraries = {};
|
||||
final Set<Reference> _shouldTrustType = {};
|
||||
final TypeEnvironment _typeEnvironment;
|
||||
|
||||
InlineExtensionIndex(this._coreTypes, this._typeEnvironment);
|
||||
ExtensionIndex(this._coreTypes, this._typeEnvironment);
|
||||
|
||||
/// If unprocessed, for all extension members in [library] whose on-type is a
|
||||
/// JS interop or `@Native` class, does the following:
|
||||
|
@ -723,17 +724,17 @@ class InlineExtensionIndex {
|
|||
Annotatable? cls;
|
||||
if (onType is InterfaceType) {
|
||||
cls = onType.classNode;
|
||||
// For now, `@trustTypes` can only be used on non-inline
|
||||
// classes.
|
||||
// For now, `@trustTypes` can only be used on classes and not
|
||||
// extension types.
|
||||
if (hasTrustTypesAnnotation(cls)) {
|
||||
_shouldTrustType.add(reference);
|
||||
}
|
||||
isInteropOnType =
|
||||
hasJSInteropAnnotation(cls) || hasNativeAnnotation(cls);
|
||||
} else if (onType is ExtensionType) {
|
||||
final inlineClass = onType.extensionTypeDeclaration;
|
||||
cls = inlineClass;
|
||||
isInteropOnType = isInteropInlineClass(inlineClass);
|
||||
final extensionType = onType.extensionTypeDeclaration;
|
||||
cls = extensionType;
|
||||
isInteropOnType = isInteropExtensionType(extensionType);
|
||||
}
|
||||
if (!isInteropOnType) continue;
|
||||
_extensionMemberIndex[reference] = descriptor;
|
||||
|
@ -789,19 +790,19 @@ class InlineExtensionIndex {
|
|||
}
|
||||
|
||||
/// Caches and returns whether the ultimate representation type that
|
||||
/// corresponds to [inlineClass]' representation type is an interop type that
|
||||
/// can be statically interoperable.
|
||||
/// corresponds to [extensionType]'s representation type is an interop type
|
||||
/// that can be statically interoperable.
|
||||
///
|
||||
/// This currently allows the interface type to be:
|
||||
/// - all package:js classes
|
||||
/// - dart:js_types types
|
||||
/// - @Native types that implement JavaScriptObject
|
||||
bool isInteropInlineClass(ExtensionTypeDeclaration inlineClass) {
|
||||
final reference = inlineClass.reference;
|
||||
if (_interopInlineClassIndex.containsKey(reference)) {
|
||||
return _interopInlineClassIndex[reference]!;
|
||||
bool isInteropExtensionType(ExtensionTypeDeclaration extensionType) {
|
||||
final reference = extensionType.reference;
|
||||
if (_interopExtensionTypeIndex.containsKey(reference)) {
|
||||
return _interopExtensionTypeIndex[reference]!;
|
||||
}
|
||||
DartType repType = inlineClass.declaredRepresentationType;
|
||||
DartType repType = extensionType.declaredRepresentationType;
|
||||
// TODO(srujzs): This iteration is currently needed since
|
||||
// `instantiatedRepresentationType` doesn't do this for us. Remove this
|
||||
// iteration when the CFE changes this getter.
|
||||
|
@ -823,31 +824,31 @@ class InlineExtensionIndex {
|
|||
repType,
|
||||
InterfaceType(javaScriptObject, Nullability.nullable),
|
||||
SubtypeCheckMode.withNullabilities))) {
|
||||
_interopInlineClassIndex[reference] = true;
|
||||
_interopExtensionTypeIndex[reference] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_interopInlineClassIndex[reference] = false;
|
||||
_interopExtensionTypeIndex[reference] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// If unprocessed, for all inline class members in [library] whose inline
|
||||
/// class is static interop, does the following:
|
||||
/// If unprocessed, for all extension type members in [library] whose
|
||||
/// extension type is static interop, does the following:
|
||||
///
|
||||
/// - Maps the inline class to its interop type
|
||||
/// - Maps the member to its inline class in `_inlineClassIndex`.
|
||||
/// - Maps the member to its descriptor in `_inlineMemberIndex`.
|
||||
/// - Maps the extension type to its interop type
|
||||
/// - Maps the member to its extension type in `_extensionTypeIndex`.
|
||||
/// - Maps the member to its descriptor in `_extensionTypeMemberIndex`.
|
||||
/// - Maps the tear-off member to the member it tears off in
|
||||
/// `inlineTearOffIndex`.
|
||||
void _indexInlineClasses(Library library) {
|
||||
if (_processedInlineLibraries.contains(library)) return;
|
||||
for (var inlineClass in library.extensionTypeDeclarations) {
|
||||
if (isInteropInlineClass(inlineClass)) {
|
||||
/// `_extensionTearOffIndex`.
|
||||
void _indexExtensionTypes(Library library) {
|
||||
if (_processedExtensionTypeLibraries.contains(library)) return;
|
||||
for (var extensionType in library.extensionTypeDeclarations) {
|
||||
if (isInteropExtensionType(extensionType)) {
|
||||
final descriptorNames = <String, ExtensionTypeMemberDescriptor>{};
|
||||
for (var descriptor in inlineClass.members) {
|
||||
for (var descriptor in extensionType.members) {
|
||||
final reference = descriptor.member;
|
||||
_inlineMemberIndex[reference] = descriptor;
|
||||
_inlineClassIndex[reference] = inlineClass;
|
||||
_extensionTypeMemberIndex[reference] = descriptor;
|
||||
_extensionTypeIndex[reference] = extensionType;
|
||||
if (descriptor.kind == ExtensionTypeMemberKind.Method ||
|
||||
descriptor.kind == ExtensionTypeMemberKind.Constructor ||
|
||||
descriptor.kind == ExtensionTypeMemberKind.TearOff) {
|
||||
|
@ -855,9 +856,11 @@ class InlineExtensionIndex {
|
|||
if (descriptorNames.containsKey(descriptorName)) {
|
||||
final previousDesc = descriptorNames[descriptorName]!;
|
||||
if (previousDesc.kind == ExtensionTypeMemberKind.TearOff) {
|
||||
_inlineTearOffIndex[previousDesc.member] = descriptor.member;
|
||||
_extensionTypeTearOffIndex[previousDesc.member] =
|
||||
descriptor.member;
|
||||
} else {
|
||||
_inlineTearOffIndex[descriptor.member] = previousDesc.member;
|
||||
_extensionTypeTearOffIndex[descriptor.member] =
|
||||
previousDesc.member;
|
||||
}
|
||||
} else {
|
||||
descriptorNames[descriptorName] = descriptor;
|
||||
|
@ -866,36 +869,36 @@ class InlineExtensionIndex {
|
|||
}
|
||||
}
|
||||
}
|
||||
_processedInlineLibraries.add(library);
|
||||
_processedExtensionTypeLibraries.add(library);
|
||||
}
|
||||
|
||||
ExtensionTypeMemberDescriptor? getInlineDescriptor(Member member) {
|
||||
ExtensionTypeMemberDescriptor? getExtensionTypeDescriptor(Member member) {
|
||||
if (!member.isExtensionTypeMember) return null;
|
||||
_indexInlineClasses(member.enclosingLibrary);
|
||||
return _inlineMemberIndex[member.reference];
|
||||
_indexExtensionTypes(member.enclosingLibrary);
|
||||
return _extensionTypeMemberIndex[member.reference];
|
||||
}
|
||||
|
||||
ExtensionTypeDeclaration? getInlineClass(Member member) {
|
||||
ExtensionTypeDeclaration? getExtensionType(Member member) {
|
||||
if (!member.isExtensionTypeMember) return null;
|
||||
_indexInlineClasses(member.enclosingLibrary);
|
||||
return _inlineClassIndex[member.reference];
|
||||
_indexExtensionTypes(member.enclosingLibrary);
|
||||
return _extensionTypeIndex[member.reference];
|
||||
}
|
||||
|
||||
Reference? getInlineMemberForTearOff(Member member) {
|
||||
Reference? getExtensionTypeMemberForTearOff(Member member) {
|
||||
if (!member.isExtensionTypeMember) return null;
|
||||
_indexInlineClasses(member.enclosingLibrary);
|
||||
return _inlineTearOffIndex[member.reference];
|
||||
_indexExtensionTypes(member.enclosingLibrary);
|
||||
return _extensionTypeTearOffIndex[member.reference];
|
||||
}
|
||||
|
||||
/// Return whether [node] is either an extension member that's declared as
|
||||
/// non-`static` or an inline class member that's declared as non-`static`
|
||||
/// non-`static` or an extension type member that's declared as non-`static`
|
||||
/// and is not a factory or constructor.
|
||||
bool isInstanceInteropMember(Member node) {
|
||||
if (node.isExtensionMember) {
|
||||
var descriptor = getExtensionDescriptor(node);
|
||||
return descriptor != null && !descriptor.isStatic;
|
||||
} else if (node.isExtensionTypeMember) {
|
||||
var descriptor = getInlineDescriptor(node);
|
||||
var descriptor = getExtensionTypeDescriptor(node);
|
||||
return descriptor != null &&
|
||||
!descriptor.isStatic &&
|
||||
descriptor.kind != ExtensionTypeMemberKind.Constructor &&
|
||||
|
@ -904,10 +907,10 @@ class InlineExtensionIndex {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool _isOneOfKinds(Procedure node, ExtensionTypeMemberKind inlineKind,
|
||||
bool _isOneOfKinds(Procedure node, ExtensionTypeMemberKind extensionTypeKind,
|
||||
ExtensionMemberKind extensionKind, ProcedureKind procedureKind) {
|
||||
if (node.isExtensionTypeMember) {
|
||||
return getInlineDescriptor(node)?.kind == inlineKind;
|
||||
return getExtensionTypeDescriptor(node)?.kind == extensionTypeKind;
|
||||
} else if (node.isExtensionMember) {
|
||||
return getExtensionDescriptor(node)?.kind == extensionKind;
|
||||
} else {
|
||||
|
@ -946,7 +949,7 @@ class InlineExtensionIndex {
|
|||
bool _isStaticInteropConstructor(Procedure node, {required bool literal}) {
|
||||
if (!node.isExternal) return false;
|
||||
if (node.isExtensionTypeMember) {
|
||||
final kind = getInlineDescriptor(node)?.kind;
|
||||
final kind = getExtensionTypeDescriptor(node)?.kind;
|
||||
final namedParams = node.function.namedParameters;
|
||||
return (kind == ExtensionTypeMemberKind.Constructor ||
|
||||
kind == ExtensionTypeMemberKind.Factory) &&
|
||||
|
@ -972,7 +975,7 @@ class InlineExtensionIndex {
|
|||
if (type is InterfaceType) {
|
||||
return hasStaticInteropAnnotation(type.classNode);
|
||||
} else if (type is ExtensionType) {
|
||||
return isInteropInlineClass(type.extensionTypeDeclaration);
|
||||
return isInteropExtensionType(type.extensionTypeDeclaration);
|
||||
} else if (type is TypeParameterType) {
|
||||
return isStaticInteropType(type.bound);
|
||||
}
|
||||
|
|
|
@ -65,10 +65,10 @@ class StaticInteropMockValidator {
|
|||
/// even more complex when you have to account for extensions and supertypes
|
||||
/// having their own type parameters too. In order to properly handle all
|
||||
/// these cases, we'd have to keep constraints around and see what extensions
|
||||
/// apply and what extensions don't. This may be simpler to do for inline
|
||||
/// classes/extension types, as all the members are in the class and not in an
|
||||
/// extension, but for now, we require that users must implement members with
|
||||
/// type parameters based on their bounds.
|
||||
/// apply and what extensions don't. This may be simpler to do for extension
|
||||
/// types, as all the members are in the class and not in an extension, but
|
||||
/// for now, we require that users must implement members with type parameters
|
||||
/// based on their bounds.
|
||||
///
|
||||
/// Returns whether the validation passed.
|
||||
bool _validateNoTypeParametersInTypeArgument(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// 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_interop_checks/src/transformations/js_util_optimizer.dart'
|
||||
show InlineExtensionIndex;
|
||||
show ExtensionIndex;
|
||||
import 'package:dart2wasm/js/method_collector.dart';
|
||||
import 'package:dart2wasm/js/util.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
|
@ -13,10 +13,10 @@ class CallbackSpecializer {
|
|||
final StatefulStaticTypeContext _staticTypeContext;
|
||||
final MethodCollector _methodCollector;
|
||||
final CoreTypesUtil _util;
|
||||
final InlineExtensionIndex _inlineExtensionIndex;
|
||||
final ExtensionIndex _extensionIndex;
|
||||
|
||||
CallbackSpecializer(this._staticTypeContext, this._util,
|
||||
this._methodCollector, this._inlineExtensionIndex) {}
|
||||
this._methodCollector, this._extensionIndex) {}
|
||||
|
||||
bool _needsArgumentsLength(FunctionType type) =>
|
||||
type.requiredParameterCount < type.positionalParameters.length;
|
||||
|
@ -32,7 +32,7 @@ class CallbackSpecializer {
|
|||
DartType callbackParameterType = function.positionalParameters[i];
|
||||
Expression expression;
|
||||
VariableGet v = VariableGet(positionalParameters[i]);
|
||||
if (_inlineExtensionIndex.isStaticInteropType(callbackParameterType) &&
|
||||
if (_extensionIndex.isStaticInteropType(callbackParameterType) &&
|
||||
boxExternRef) {
|
||||
expression = _createJSValue(v);
|
||||
} else {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import 'package:_js_interop_checks/src/js_interop.dart'
|
||||
show getJSName, hasAnonymousAnnotation, hasJSInteropAnnotation;
|
||||
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
|
||||
show InlineExtensionIndex;
|
||||
show ExtensionIndex;
|
||||
import 'package:dart2wasm/js/method_collector.dart';
|
||||
import 'package:dart2wasm/js/util.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
|
@ -21,7 +21,7 @@ abstract class _Specializer {
|
|||
final Procedure interopMethod;
|
||||
final String jsString;
|
||||
late final bool firstParameterIsObject =
|
||||
factory._inlineExtensionIndex.isInstanceInteropMember(interopMethod);
|
||||
factory._extensionIndex.isInstanceInteropMember(interopMethod);
|
||||
|
||||
_Specializer(this.factory, this.interopMethod, this.jsString);
|
||||
|
||||
|
@ -330,8 +330,7 @@ class _ObjectLiteralSpecializer extends _InvocationSpecializer {
|
|||
_util.jsifyTarget(expr.getStaticType(_staticTypeContext)),
|
||||
Arguments([expr])))
|
||||
.toList();
|
||||
assert(
|
||||
factory._inlineExtensionIndex.isStaticInteropType(function.returnType));
|
||||
assert(factory._extensionIndex.isStaticInteropType(function.returnType));
|
||||
return invokeOneArg(_util.jsValueBoxTarget,
|
||||
StaticInvocation(interopProcedure, Arguments(positionalArgs)));
|
||||
}
|
||||
|
@ -344,10 +343,10 @@ class InteropSpecializerFactory {
|
|||
final Map<Procedure, Map<int, Procedure>> _overloadedProcedures = {};
|
||||
final Map<Procedure, Map<String, Procedure>> _jsObjectLiteralMethods = {};
|
||||
late String _libraryJSString;
|
||||
late final InlineExtensionIndex _inlineExtensionIndex;
|
||||
late final ExtensionIndex _extensionIndex;
|
||||
|
||||
InteropSpecializerFactory(this._staticTypeContext, this._util,
|
||||
this._methodCollector, this._inlineExtensionIndex);
|
||||
this._methodCollector, this._extensionIndex);
|
||||
|
||||
void enterLibrary(Library library) {
|
||||
_libraryJSString = getJSName(library);
|
||||
|
@ -373,17 +372,17 @@ class InteropSpecializerFactory {
|
|||
_Specializer? _getSpecializerForMember(Procedure node, String jsString,
|
||||
[StaticInvocation? invocation]) {
|
||||
if (invocation == null) {
|
||||
if (_inlineExtensionIndex.isGetter(node)) {
|
||||
if (_extensionIndex.isGetter(node)) {
|
||||
return _GetterSpecializer(this, node, jsString);
|
||||
} else if (_inlineExtensionIndex.isSetter(node)) {
|
||||
} else if (_extensionIndex.isSetter(node)) {
|
||||
return _SetterSpecializer(this, node, jsString);
|
||||
} else if (_inlineExtensionIndex.isOperator(node)) {
|
||||
} else if (_extensionIndex.isOperator(node)) {
|
||||
return _OperatorSpecializer(this, node, jsString);
|
||||
} else if (_inlineExtensionIndex.isMethod(node)) {
|
||||
} else if (_extensionIndex.isMethod(node)) {
|
||||
return _MethodSpecializer(this, node, jsString);
|
||||
}
|
||||
} else {
|
||||
if (_inlineExtensionIndex.isMethod(node)) {
|
||||
if (_extensionIndex.isMethod(node)) {
|
||||
return _MethodInvocationSpecializer(this, node, jsString, invocation);
|
||||
}
|
||||
}
|
||||
|
@ -432,15 +431,15 @@ class InteropSpecializerFactory {
|
|||
node, '$clsString.$memberSelectorString', invocation);
|
||||
}
|
||||
} else if (node.isExtensionTypeMember) {
|
||||
final nodeDescriptor = _inlineExtensionIndex.getInlineDescriptor(node);
|
||||
final nodeDescriptor = _extensionIndex.getExtensionTypeDescriptor(node);
|
||||
if (nodeDescriptor != null) {
|
||||
final cls = _inlineExtensionIndex.getInlineClass(node)!;
|
||||
final cls = _extensionIndex.getExtensionType(node)!;
|
||||
final clsString = _getTopLevelJSString(cls, cls.name);
|
||||
final kind = nodeDescriptor.kind;
|
||||
if ((kind == ExtensionTypeMemberKind.Constructor ||
|
||||
kind == ExtensionTypeMemberKind.Factory)) {
|
||||
return _getSpecializerForConstructor(
|
||||
_inlineExtensionIndex.isLiteralConstructor(node),
|
||||
_extensionIndex.isLiteralConstructor(node),
|
||||
node,
|
||||
clsString,
|
||||
invocation);
|
||||
|
@ -457,7 +456,7 @@ class InteropSpecializerFactory {
|
|||
}
|
||||
}
|
||||
} else if (node.isExtensionMember) {
|
||||
final nodeDescriptor = _inlineExtensionIndex.getExtensionDescriptor(node);
|
||||
final nodeDescriptor = _extensionIndex.getExtensionDescriptor(node);
|
||||
if (nodeDescriptor != null && !nodeDescriptor.isStatic) {
|
||||
return _getSpecializerForMember(
|
||||
node, _getJSString(node, nodeDescriptor.name.text), invocation);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
|
||||
show InlineExtensionIndex;
|
||||
show ExtensionIndex;
|
||||
import 'package:dart2wasm/js/callback_specializer.dart';
|
||||
import 'package:dart2wasm/js/inline_expander.dart';
|
||||
import 'package:dart2wasm/js/interop_specializer.dart';
|
||||
|
@ -34,27 +34,23 @@ class InteropTransformer extends Transformer {
|
|||
final CoreTypesUtil _util;
|
||||
|
||||
InteropTransformer._(this._staticTypeContext, this._util,
|
||||
this._methodCollector, inlineExtensionIndex)
|
||||
this._methodCollector, extensionIndex)
|
||||
: _callbackSpecializer = CallbackSpecializer(
|
||||
_staticTypeContext, _util, _methodCollector, inlineExtensionIndex),
|
||||
_staticTypeContext, _util, _methodCollector, extensionIndex),
|
||||
_inlineExpander =
|
||||
InlineExpander(_staticTypeContext, _util, _methodCollector),
|
||||
_interopSpecializerFactory = InteropSpecializerFactory(
|
||||
_staticTypeContext,
|
||||
_util,
|
||||
_methodCollector,
|
||||
inlineExtensionIndex) {}
|
||||
_staticTypeContext, _util, _methodCollector, extensionIndex) {}
|
||||
|
||||
factory InteropTransformer(CoreTypes coreTypes, ClassHierarchy hierarchy) {
|
||||
final typeEnvironment = TypeEnvironment(coreTypes, hierarchy);
|
||||
final inlineExtensionIndex =
|
||||
InlineExtensionIndex(coreTypes, typeEnvironment);
|
||||
final util = CoreTypesUtil(coreTypes, inlineExtensionIndex);
|
||||
final extensionIndex = ExtensionIndex(coreTypes, typeEnvironment);
|
||||
final util = CoreTypesUtil(coreTypes, extensionIndex);
|
||||
return InteropTransformer._(
|
||||
StatefulStaticTypeContext.stacked(typeEnvironment),
|
||||
util,
|
||||
MethodCollector(util),
|
||||
inlineExtensionIndex);
|
||||
extensionIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
|
||||
show InlineExtensionIndex;
|
||||
show ExtensionIndex;
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
|
||||
|
@ -11,7 +11,7 @@ enum AnnotationType { import, export }
|
|||
|
||||
/// A utility wrapper for [CoreTypes].
|
||||
class CoreTypesUtil {
|
||||
final InlineExtensionIndex _inlineExtensionIndex;
|
||||
final ExtensionIndex _extensionIndex;
|
||||
final CoreTypes coreTypes;
|
||||
final Procedure allowInteropTarget;
|
||||
final Procedure dartifyRawTarget;
|
||||
|
@ -27,7 +27,7 @@ class CoreTypesUtil {
|
|||
final Class wasmExternRefClass;
|
||||
final Procedure wrapDartFunctionTarget;
|
||||
|
||||
CoreTypesUtil(this.coreTypes, this._inlineExtensionIndex)
|
||||
CoreTypesUtil(this.coreTypes, this._extensionIndex)
|
||||
: allowInteropTarget = coreTypes.index
|
||||
.getTopLevelProcedure('dart:js_util', 'allowInterop'),
|
||||
dartifyRawTarget = coreTypes.index
|
||||
|
@ -73,7 +73,7 @@ class CoreTypesUtil {
|
|||
wasmExternRefClass.getThisType(coreTypes, Nullability.nullable);
|
||||
|
||||
Procedure jsifyTarget(DartType type) =>
|
||||
_inlineExtensionIndex.isStaticInteropType(type)
|
||||
_extensionIndex.isStaticInteropType(type)
|
||||
? jsValueUnboxTarget
|
||||
: jsifyRawTarget;
|
||||
|
||||
|
@ -112,7 +112,7 @@ class CoreTypesUtil {
|
|||
return invokeOneArg(dartifyRawTarget, invocation);
|
||||
} else {
|
||||
Expression expression;
|
||||
if (_inlineExtensionIndex.isStaticInteropType(returnType)) {
|
||||
if (_extensionIndex.isStaticInteropType(returnType)) {
|
||||
// TODO(joshualitt): Expose boxed `JSNull` and `JSUndefined` to Dart
|
||||
// code after migrating existing users of js interop on Dart2Wasm.
|
||||
// expression = _createJSValue(invocation);
|
||||
|
|
|
@ -8,7 +8,7 @@ import 'dart:io' as io;
|
|||
import 'dart:math' show max, min;
|
||||
|
||||
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart'
|
||||
show InlineExtensionIndex;
|
||||
show ExtensionIndex;
|
||||
import 'package:_js_interop_checks/src/transformations/static_interop_class_eraser.dart'
|
||||
show eraseStaticInteropTypesForJSCompilers;
|
||||
import 'package:collection/collection.dart'
|
||||
|
@ -275,11 +275,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
/// Maps uri strings in asserts and elsewhere to hoisted identifiers.
|
||||
var _uriContainer = ModuleItemContainer<String>.asArray('I');
|
||||
|
||||
/// Index of inline and extension members in order to filter static interop
|
||||
/// members.
|
||||
/// Index of extension and extension type members in order to filter static
|
||||
/// interop members.
|
||||
// TODO(srujzs): Is there some way to share this from the js_util_optimizer to
|
||||
// avoid having to recompute?
|
||||
final InlineExtensionIndex _inlineExtensionIndex;
|
||||
final ExtensionIndex _extensionIndex;
|
||||
|
||||
final Class _jsArrayClass;
|
||||
final Class _privateSymbolClass;
|
||||
|
@ -368,8 +368,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
'dart:_runtime', 'assertInterop') as Procedure,
|
||||
_futureOrNormalizer = FutureOrNormalizer(_coreTypes),
|
||||
_typeRecipeGenerator = TypeRecipeGenerator(_coreTypes, _hierarchy),
|
||||
_inlineExtensionIndex = InlineExtensionIndex(
|
||||
_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
_extensionIndex =
|
||||
ExtensionIndex(_coreTypes, _staticTypeContext.typeEnvironment);
|
||||
|
||||
@override
|
||||
Library? get currentLibrary => _currentLibrary;
|
||||
|
@ -3089,13 +3089,14 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
/// Users are disallowed from using these tear-offs, so we should avoid
|
||||
/// emitting them.
|
||||
bool _isStaticInteropTearOff(Procedure p) {
|
||||
final extensionMember =
|
||||
_inlineExtensionIndex.getExtensionMemberForTearOff(p);
|
||||
final extensionMember = _extensionIndex.getExtensionMemberForTearOff(p);
|
||||
if (extensionMember != null && extensionMember.asProcedure.isExternal) {
|
||||
return true;
|
||||
}
|
||||
final inlineMember = _inlineExtensionIndex.getInlineMemberForTearOff(p);
|
||||
if (inlineMember != null && inlineMember.asProcedure.isExternal) {
|
||||
final extensionTypeMember =
|
||||
_extensionIndex.getExtensionTypeMemberForTearOff(p);
|
||||
if (extensionTypeMember != null &&
|
||||
extensionTypeMember.asProcedure.isExternal) {
|
||||
return true;
|
||||
}
|
||||
final enclosingClass = p.enclosingClass;
|
||||
|
@ -6380,9 +6381,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
if (target.isExternal &&
|
||||
target.isExtensionTypeMember &&
|
||||
target.function.namedParameters.isNotEmpty) {
|
||||
// JS interop checks assert that only external inline class factories have
|
||||
// named parameters. We could do a more robust check by visiting all
|
||||
// inline classes and recording descriptors, but that's expensive.
|
||||
// JS interop checks assert that only external extension type constructors
|
||||
// and factories have named parameters.
|
||||
assert(target.function.positionalParameters.isEmpty);
|
||||
return _emitObjectLiteral(
|
||||
Arguments(node.arguments.positional,
|
||||
|
|
|
@ -3836,6 +3836,45 @@ Message _withArgumentsJsInteropExportInvalidTypeArgument(
|
|||
arguments: {'type': _type});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>
|
||||
templateJsInteropExtensionTypeNotInterop = const Template<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>(
|
||||
problemMessageTemplate:
|
||||
r"""Extension type '#name' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '#type'.""",
|
||||
correctionMessageTemplate:
|
||||
r"""Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop extension types.""",
|
||||
withArguments: _withArgumentsJsInteropExtensionTypeNotInterop);
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>
|
||||
codeJsInteropExtensionTypeNotInterop = const Code<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>(
|
||||
"JsInteropExtensionTypeNotInterop",
|
||||
);
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
Message _withArgumentsJsInteropExtensionTypeNotInterop(
|
||||
String name, DartType _type, bool isNonNullableByDefault) {
|
||||
if (name.isEmpty) throw 'No name provided';
|
||||
name = demangleMixinApplicationName(name);
|
||||
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
|
||||
List<Object> typeParts = labeler.labelType(_type);
|
||||
String type = typeParts.join();
|
||||
return new Message(codeJsInteropExtensionTypeNotInterop,
|
||||
problemMessage:
|
||||
"""Extension type '${name}' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '${type}'.""" +
|
||||
labeler.originMessages,
|
||||
correctionMessage: """Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop extension types.""",
|
||||
arguments: {'name': name, 'type': _type});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
||||
templateJsInteropFunctionToJSRequiresStaticType = const Template<
|
||||
|
@ -3867,45 +3906,6 @@ Message _withArgumentsJsInteropFunctionToJSRequiresStaticType(
|
|||
arguments: {'type': _type});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>
|
||||
templateJsInteropInlineClassNotInterop = const Template<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>(
|
||||
problemMessageTemplate:
|
||||
r"""Inline class '#name' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '#type'.""",
|
||||
correctionMessageTemplate:
|
||||
r"""Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop inline types.""",
|
||||
withArguments: _withArgumentsJsInteropInlineClassNotInterop);
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>
|
||||
codeJsInteropInlineClassNotInterop = const Code<
|
||||
Message Function(
|
||||
String name, DartType _type, bool isNonNullableByDefault)>(
|
||||
"JsInteropInlineClassNotInterop",
|
||||
);
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
Message _withArgumentsJsInteropInlineClassNotInterop(
|
||||
String name, DartType _type, bool isNonNullableByDefault) {
|
||||
if (name.isEmpty) throw 'No name provided';
|
||||
name = demangleMixinApplicationName(name);
|
||||
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
|
||||
List<Object> typeParts = labeler.labelType(_type);
|
||||
String type = typeParts.join();
|
||||
return new Message(codeJsInteropInlineClassNotInterop,
|
||||
problemMessage:
|
||||
"""Inline class '${name}' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '${type}'.""" +
|
||||
labeler.originMessages,
|
||||
correctionMessage: """Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop inline types.""",
|
||||
arguments: {'name': name, 'type': _type});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
||||
templateJsInteropStaticInteropMockNotStaticInteropType = const Template<
|
||||
|
|
|
@ -588,18 +588,18 @@ JsInteropExportMemberCollision/analyzerCode: Fail # Web compiler specific
|
|||
JsInteropExportMemberCollision/example: Fail # Web compiler specific
|
||||
JsInteropExportNoExportableMembers/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExportNoExportableMembers/example: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeNotInterop/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeNotInterop/example: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeMemberNotInterop/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeMemberNotInterop/example: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeUsedWithWrongJsAnnotation/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExtensionTypeUsedWithWrongJsAnnotation/example: Fail # Web compiler specific
|
||||
JsInteropExternalExtensionMemberOnTypeInvalid/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExternalExtensionMemberOnTypeInvalid/example: Fail # Web compiler specific
|
||||
JsInteropExternalExtensionMemberWithStaticDisallowed/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExternalExtensionMemberWithStaticDisallowed/example: Fail # Web compiler specific
|
||||
JsInteropExternalMemberNotJSAnnotated/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropExternalMemberNotJSAnnotated/example: Fail # Web compiler specific
|
||||
JsInteropInlineClassNotInterop/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropInlineClassNotInterop/example: Fail # Web compiler specific
|
||||
JsInteropInlineClassMemberNotInterop/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropInlineClassMemberNotInterop/example: Fail # Web compiler specific
|
||||
JsInteropInlineClassUsedWithWrongJsAnnotation/analyzerCode: Fail # Web compiler specific
|
||||
JsInteropInlineClassUsedWithWrongJsAnnotation/example: Fail # Web compiler specific
|
||||
JsInteropInvalidStaticClassMemberName/analyzerCode: Fail
|
||||
JsInteropInvalidStaticClassMemberName/example: Fail
|
||||
JsInteropJSClassExtendsDartClass/analyzerCode: Fail # Web compiler specific
|
||||
|
|
|
@ -5474,8 +5474,8 @@ JsInteropDartClassExtendsJSClass:
|
|||
correctionMessage: "Try adding the JS interop annotation or removing it from the parent class."
|
||||
|
||||
JsInteropDartJsInteropAnnotationForStaticInteropOnly:
|
||||
problemMessage: "The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through inline classes or '@staticInterop'."
|
||||
correctionMessage: "Try making this class an inline class or marking it as '@staticInterop'."
|
||||
problemMessage: "The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through extension types or '@staticInterop' classes."
|
||||
correctionMessage: "Try making this class an extension type or marking it as '@staticInterop'."
|
||||
|
||||
JsInteropEnclosingClassJSAnnotation:
|
||||
problemMessage: "Member has a JS interop annotation but the enclosing class does not."
|
||||
|
@ -5514,6 +5514,18 @@ JsInteropExportNoExportableMembers:
|
|||
problemMessage: "Class '#name' has no exportable members in the class or the inheritance chain."
|
||||
correctionMessage: "Using `@JSExport`, annotate at least one instance member with a body or annotate a class that has such a member in the inheritance chain."
|
||||
|
||||
JsInteropExtensionTypeNotInterop:
|
||||
problemMessage: "Extension type '#name' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '#type'."
|
||||
correctionMessage: "Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop extension types."
|
||||
|
||||
JsInteropExtensionTypeMemberNotInterop:
|
||||
problemMessage: "Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type."
|
||||
correctionMessage: "Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop extension types."
|
||||
|
||||
JsInteropExtensionTypeUsedWithWrongJsAnnotation:
|
||||
problemMessage: "Extension types should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'."
|
||||
correctionMessage: "Try using the '@JS' annotation from 'dart:js_interop' annotation on this extension type instead."
|
||||
|
||||
JsInteropExternalExtensionMemberOnTypeInvalid:
|
||||
problemMessage: "JS interop or Native class required for 'external' extension members."
|
||||
correctionMessage: "Try adding a JS interop annotation to the on type class of the extension."
|
||||
|
@ -5526,18 +5538,6 @@ JsInteropExternalMemberNotJSAnnotated:
|
|||
problemMessage: "Only JS interop members may be 'external'."
|
||||
correctionMessage: "Try removing the 'external' keyword or adding a JS interop annotation."
|
||||
|
||||
JsInteropInlineClassNotInterop:
|
||||
problemMessage: "Inline class '#name' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: '#type'."
|
||||
correctionMessage: "Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop inline types."
|
||||
|
||||
JsInteropInlineClassMemberNotInterop:
|
||||
problemMessage: "Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type."
|
||||
correctionMessage: "Try declaring a valid JS interop representation type, which may include 'dart:js_interop' types, '@staticInterop' types, 'dart:html' types, or other interop inline types."
|
||||
|
||||
JsInteropInlineClassUsedWithWrongJsAnnotation:
|
||||
problemMessage: "Inline classes should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'."
|
||||
correctionMessage: "Try using the '@JS' annotation from 'dart:js_interop' annotation on this inline class instead."
|
||||
|
||||
JsInteropInvalidStaticClassMemberName:
|
||||
problemMessage: "JS interop static class members cannot have '.' in their JS name."
|
||||
|
||||
|
|
|
@ -10,16 +10,14 @@ import 'dart:js_interop';
|
|||
external void topLevel();
|
||||
|
||||
@JS()
|
||||
inline class Inline {
|
||||
final JSObject obj;
|
||||
external Inline();
|
||||
external Inline.named();
|
||||
external Inline.literal({JSNumber? a});
|
||||
Inline.nonExternal(this.obj);
|
||||
// TODO(srujzs): Once we have inline class factories, test these.
|
||||
// external factory Inline.fact();
|
||||
// external factory Inline.literalFact({JSNumber? a});
|
||||
// factory Inline.nonExternalFact() => Inline();
|
||||
extension type ExtensionType.nonExternal(JSObject _) {
|
||||
external ExtensionType();
|
||||
external ExtensionType.named();
|
||||
external ExtensionType.literal({JSNumber? a});
|
||||
// TODO(srujzs): Once we have extension type factories, test these.
|
||||
// external factory ExtensionType.fact();
|
||||
// external factory ExtensionType.literalFact({JSNumber? a});
|
||||
// factory ExtensionType.nonExternalFact() => ExtensionType();
|
||||
|
||||
external static void externalStatic();
|
||||
static void nonExternalStatic() {}
|
||||
|
@ -28,7 +26,7 @@ inline class Inline {
|
|||
void nonExternalMethod() {}
|
||||
}
|
||||
|
||||
extension on Inline {
|
||||
extension on ExtensionType {
|
||||
external void externalExtensionMethod();
|
||||
void nonExternalExtensionMethod() {}
|
||||
}
|
||||
|
@ -66,22 +64,22 @@ void testMethods() {
|
|||
//^
|
||||
// [web] Tear-offs of external top-level member 'topLevel' are disallowed.
|
||||
|
||||
Inline.externalStatic;
|
||||
// ^
|
||||
// [web] Tear-offs of external inline class interop member 'externalStatic' are disallowed.
|
||||
const [Inline.externalStatic];
|
||||
ExtensionType.externalStatic;
|
||||
// ^
|
||||
// [web] Tear-offs of external extension type interop member 'externalStatic' are disallowed.
|
||||
const [ExtensionType.externalStatic];
|
||||
//^
|
||||
// [web] Tear-offs of external inline class interop member 'externalStatic' are disallowed.
|
||||
Inline.nonExternalStatic;
|
||||
final inline = Inline();
|
||||
inline.externalMethod;
|
||||
// ^
|
||||
// [web] Tear-offs of external inline class interop member 'externalMethod' are disallowed.
|
||||
inline.nonExternalMethod;
|
||||
inline.externalExtensionMethod;
|
||||
// ^
|
||||
// [web] Tear-offs of external extension type interop member 'externalStatic' are disallowed.
|
||||
ExtensionType.nonExternalStatic;
|
||||
final extensionType = ExtensionType();
|
||||
extensionType.externalMethod;
|
||||
// ^
|
||||
// [web] Tear-offs of external extension type interop member 'externalMethod' are disallowed.
|
||||
extensionType.nonExternalMethod;
|
||||
extensionType.externalExtensionMethod;
|
||||
// ^
|
||||
// [web] Tear-offs of external extension interop member 'externalExtensionMethod' are disallowed.
|
||||
inline.nonExternalExtensionMethod;
|
||||
extensionType.nonExternalExtensionMethod;
|
||||
|
||||
StaticInterop.externalStatic;
|
||||
// ^
|
||||
|
@ -98,25 +96,25 @@ void testMethods() {
|
|||
}
|
||||
|
||||
void testConstructors() {
|
||||
Inline.new;
|
||||
ExtensionType.new;
|
||||
//^
|
||||
// [web] Tear-offs of external inline class interop member 'new' are disallowed.
|
||||
Inline.named;
|
||||
// [web] Tear-offs of external extension type interop member 'new' are disallowed.
|
||||
ExtensionType.named;
|
||||
//^
|
||||
// [web] Tear-offs of external inline class interop member 'named' are disallowed.
|
||||
Inline.literal;
|
||||
// [web] Tear-offs of external extension type interop member 'named' are disallowed.
|
||||
ExtensionType.literal;
|
||||
//^
|
||||
// [web] Tear-offs of external inline class interop member 'literal' are disallowed.
|
||||
Inline.nonExternal;
|
||||
const [Inline.new];
|
||||
// [web] Tear-offs of external extension type interop member 'literal' are disallowed.
|
||||
ExtensionType.nonExternal;
|
||||
const [ExtensionType.new];
|
||||
//^
|
||||
// [web] Tear-offs of external inline class interop member 'new' are disallowed.
|
||||
// [web] Tear-offs of external extension type interop member 'new' are disallowed.
|
||||
|
||||
// TODO(srujzs): Once we have factories available, test these.
|
||||
// Inline.fact;
|
||||
// Inline.literalFact;
|
||||
// Inline.nonExternalFact;
|
||||
// const [Inline.fact];
|
||||
// ExtensionType.fact;
|
||||
// ExtensionType.literalFact;
|
||||
// ExtensionType.nonExternalFact;
|
||||
// const [ExtensionType.fact];
|
||||
|
||||
StaticInterop.new;
|
||||
//^
|
||||
|
|
|
@ -83,13 +83,12 @@ extension UninstantiatedExtension<T, U extends JSAny?, V extends Instantiated>
|
|||
external X returnX<X extends JSArray>();
|
||||
}
|
||||
|
||||
inline class UninstantiatedInline<T, U extends JSAny?,
|
||||
V extends InstantiatedInline> {
|
||||
final JSObject obj;
|
||||
external UninstantiatedInline(T t);
|
||||
extension type UninstantiatedExtensionType<T, U extends JSAny?,
|
||||
V extends InstantiatedExtensionType>._(JSObject _) {
|
||||
external UninstantiatedExtensionType(T t);
|
||||
// ^
|
||||
// [web] External static interop members can only use type parameters that extend either a static interop type or one of the 'dart:js_interop' types.
|
||||
external factory UninstantiatedInline.named(U u);
|
||||
external factory UninstantiatedExtensionType.fact(U u);
|
||||
|
||||
// Test simple type parameters.
|
||||
external T fieldT;
|
||||
|
@ -142,8 +141,8 @@ inline class UninstantiatedInline<T, U extends JSAny?,
|
|||
external X returnX<X extends JSArray>();
|
||||
}
|
||||
|
||||
extension UninstantiatedInlineExtension<T, U extends JSAny?,
|
||||
V extends InstantiatedInline> on UninstantiatedInline<T, U, V> {
|
||||
extension UninstantiatedExtensionTypeExtension<T, U extends JSAny?,
|
||||
V extends InstantiatedExtensionType> on UninstantiatedExtensionType<T, U, V> {
|
||||
external T get extensionGetT;
|
||||
// ^
|
||||
// [web] External static interop members can only use type parameters that extend either a static interop type or one of the 'dart:js_interop' types.
|
||||
|
@ -190,15 +189,14 @@ extension InstantiatedExtension on Instantiated {
|
|||
external void consumeList(List<Instantiated> list);
|
||||
}
|
||||
|
||||
inline class InstantiatedInline {
|
||||
final JSObject obj;
|
||||
extension type InstantiatedExtensionType._(JSObject _) {
|
||||
// Test generic types where all the type parameters are instantiated.
|
||||
external InstantiatedInline(List<JSNumber> list);
|
||||
external List<InstantiatedInline> fieldList;
|
||||
external List<InstantiatedInline> get getList;
|
||||
external set setList(List<InstantiatedInline> list);
|
||||
external List<InstantiatedInline> returnList();
|
||||
external void consumeList(List<InstantiatedInline> list);
|
||||
external InstantiatedExtensionType(List<JSNumber> list);
|
||||
external List<InstantiatedExtensionType> fieldList;
|
||||
external List<InstantiatedExtensionType> get getList;
|
||||
external set setList(List<InstantiatedExtensionType> list);
|
||||
external List<InstantiatedExtensionType> returnList();
|
||||
external void consumeList(List<InstantiatedExtensionType> list);
|
||||
}
|
||||
|
||||
void main() {}
|
||||
|
|
|
@ -9,7 +9,6 @@ library external_operator_test;
|
|||
|
||||
import 'dart:js_interop';
|
||||
import 'package:expect/minitest.dart';
|
||||
import 'package:js/js.dart' hide JS;
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
@ -30,10 +29,7 @@ external Indexable get indexableArr;
|
|||
external Indexable get indexableObj;
|
||||
|
||||
@JS()
|
||||
inline class Indexable2 {
|
||||
final JSObject obj;
|
||||
external Indexable2();
|
||||
|
||||
extension type Indexable2(JSObject _) {
|
||||
external JSAny? operator [](JSNumber index);
|
||||
external void operator []=(JSNumber index, JSAny? value);
|
||||
}
|
||||
|
|
|
@ -14,12 +14,11 @@ import 'package:expect/minitest.dart';
|
|||
@JS()
|
||||
external dynamic eval(String code);
|
||||
|
||||
inline class Extension {
|
||||
final JSObject obj;
|
||||
external Extension();
|
||||
extension type ExtensionType._(JSObject _) {
|
||||
external ExtensionType();
|
||||
}
|
||||
|
||||
extension E on Extension {
|
||||
extension E on ExtensionType {
|
||||
external String field;
|
||||
@JS('field')
|
||||
external String renamedField;
|
||||
|
@ -40,7 +39,7 @@ extension E on Extension {
|
|||
|
||||
void main() {
|
||||
eval('''
|
||||
globalThis.Extension = function Extension() {
|
||||
globalThis.ExtensionType = function ExtensionType() {
|
||||
this.field = 'field';
|
||||
this.finalField = 'finalField';
|
||||
this.getSet = 'getSet';
|
||||
|
@ -52,7 +51,7 @@ void main() {
|
|||
}
|
||||
}
|
||||
''');
|
||||
var extension = Extension();
|
||||
var extension = ExtensionType();
|
||||
|
||||
// Fields.
|
||||
expect(extension.field, 'field');
|
||||
|
|
|
@ -15,8 +15,7 @@ import 'package:expect/minitest.dart';
|
|||
@JS()
|
||||
external dynamic eval(String code);
|
||||
|
||||
inline class External<T extends JSAny?, U extends Nested> {
|
||||
final JSObject obj;
|
||||
extension type External<T extends JSAny?, U extends Nested>._(JSObject _) {
|
||||
external External();
|
||||
|
||||
external String field;
|
||||
|
@ -54,8 +53,7 @@ inline class External<T extends JSAny?, U extends Nested> {
|
|||
external R combineNestedGeneric<R extends Nested>(R a, [R b]);
|
||||
}
|
||||
|
||||
inline class Nested<T extends JSAny?> {
|
||||
final JSObject obj;
|
||||
extension type Nested<T extends JSAny?>._(JSObject _) {
|
||||
external Nested(T value);
|
||||
|
||||
external T get value;
|
||||
|
|
|
@ -16,8 +16,7 @@ import 'package:expect/minitest.dart';
|
|||
external dynamic eval(String code);
|
||||
|
||||
@JS()
|
||||
inline class ExternalStatic {
|
||||
final JSObject obj;
|
||||
extension type ExternalStatic._(JSObject obj) {
|
||||
external ExternalStatic();
|
||||
// TODO(srujzs): Uncomment the external factory test once the CFE supports
|
||||
// them.
|
||||
|
|
|
@ -16,8 +16,7 @@ import 'package:expect/minitest.dart';
|
|||
external dynamic eval(String code);
|
||||
|
||||
@JS('library3.ExternalStatic')
|
||||
inline class ExternalStatic {
|
||||
final JSObject obj;
|
||||
extension type ExternalStatic._(JSObject obj) {
|
||||
external ExternalStatic();
|
||||
// TODO(srujzs): Uncomment the external factory test once the CFE supports
|
||||
// them.
|
||||
|
|
|
@ -20,23 +20,17 @@ external jsi.JSVoid jsiTopLevel();
|
|||
external jsi.JSVoid pkgJsTopLevel();
|
||||
|
||||
@jsi.JS()
|
||||
inline class JsiInlineClass {
|
||||
final jsi.JSObject obj;
|
||||
external JsiInlineClass();
|
||||
}
|
||||
extension type JsiExtensionType._(jsi.JSObject _) {}
|
||||
|
||||
@pkgJs.JS()
|
||||
inline class PkgJsInlineClass {
|
||||
// ^
|
||||
// [web] Inline classes should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'.
|
||||
final jsi.JSObject obj;
|
||||
external PkgJsInlineClass();
|
||||
}
|
||||
extension type PkgJsExtensionType._(jsi.JSObject _) {}
|
||||
// ^
|
||||
// [web] Extension types should use the '@JS' annotation from 'dart:js_interop' and not from 'package:js'.
|
||||
|
||||
@jsi.JS()
|
||||
class JsiClass {}
|
||||
// ^
|
||||
// [web] The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through inline classes or '@staticInterop'.
|
||||
// [web] The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through extension types or '@staticInterop' classes.
|
||||
|
||||
@pkgJs.JS()
|
||||
class PkgJsClass {}
|
||||
|
@ -45,7 +39,7 @@ class PkgJsClass {}
|
|||
@jsi.anonymous
|
||||
class JsiAnonymousClass {}
|
||||
// ^
|
||||
// [web] The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through inline classes or '@staticInterop'.
|
||||
// [web] The '@JS' annotation from 'dart:js_interop' can only be used for static interop, either through extension types or '@staticInterop' classes.
|
||||
|
||||
@pkgJs.JS()
|
||||
@pkgJs.anonymous
|
||||
|
|
|
@ -22,9 +22,8 @@ external set topLevelSetter(JSNumber _);
|
|||
external void topLevelMethod();
|
||||
|
||||
@JS()
|
||||
inline class InlineClass {
|
||||
final JSObject obj;
|
||||
external InlineClass();
|
||||
extension type ExtensionType._(JSObject _) {
|
||||
external ExtensionType();
|
||||
|
||||
external JSNumber field;
|
||||
external JSNumber get getter;
|
||||
|
@ -55,7 +54,7 @@ inline class InlineClass {
|
|||
external static JSVoid annotatedStaticMethod();
|
||||
}
|
||||
|
||||
extension InlineClassExtension on InlineClass {
|
||||
extension ExtensionTypeExtension on ExtensionType {
|
||||
external JSNumber extensionField;
|
||||
external JSNumber get extensionGetter;
|
||||
external set extensionSetter(JSNumber _);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// SharedOptions=--enable-experiment=inline-class
|
||||
|
||||
// Test that interop inline classes can only work on interop types.
|
||||
// Test that interop extension types can only work on interop types.
|
||||
|
||||
import 'dart:html';
|
||||
import 'dart:js_interop';
|
||||
|
@ -13,45 +13,32 @@ import 'package:js/js.dart' as pkgJs;
|
|||
// General non-interop types.
|
||||
|
||||
@JS()
|
||||
inline class IObject {
|
||||
// ^
|
||||
// [web] Inline class 'IObject' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'Object'.
|
||||
final Object obj;
|
||||
external IObject();
|
||||
// ^
|
||||
// [web] Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.
|
||||
}
|
||||
extension type EObject(Object _) {}
|
||||
// ^
|
||||
// [web] Extension type 'EObject' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'Object'.
|
||||
|
||||
inline class IList {
|
||||
final List<JSAny?> obj;
|
||||
external IList();
|
||||
extension type EList._(List<JSAny?> _) {
|
||||
external EList();
|
||||
// ^
|
||||
// [web] Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.
|
||||
// [web] Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type.
|
||||
}
|
||||
|
||||
// dart:js_interop types.
|
||||
|
||||
inline class IJSObject {
|
||||
final JSObject obj;
|
||||
external IJSObject();
|
||||
}
|
||||
extension type EJSObject(JSObject _) {}
|
||||
|
||||
@JS()
|
||||
inline class IJSString {
|
||||
final JSString obj;
|
||||
external IJSString();
|
||||
}
|
||||
extension type EJSString(JSString _) {}
|
||||
|
||||
// package:js types.
|
||||
|
||||
@pkgJs.JS()
|
||||
class PkgJs {}
|
||||
|
||||
inline class IPkgJs {
|
||||
final PkgJs obj;
|
||||
extension type EPkgJs._(PkgJs _) {
|
||||
external IPkgJs();
|
||||
// ^
|
||||
// [web] Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.
|
||||
// [web] Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type.
|
||||
}
|
||||
|
||||
@pkgJs.JS()
|
||||
|
@ -59,65 +46,44 @@ inline class IPkgJs {
|
|||
class Anonymous {}
|
||||
|
||||
@JS()
|
||||
inline class IAnonymous {
|
||||
// ^
|
||||
// [web] Inline class 'IAnonymous' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'Anonymous'.
|
||||
final Anonymous obj;
|
||||
external IAnonymous();
|
||||
extension type EAnonymous._(Anonymous _) {
|
||||
// ^
|
||||
// [web] Extension type 'EAnonymous' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'Anonymous'.
|
||||
external EAnonymous();
|
||||
// ^
|
||||
// [web] Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.
|
||||
// [web] Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type.
|
||||
}
|
||||
|
||||
@pkgJs.JS()
|
||||
@staticInterop
|
||||
class PkgJsStaticInterop {}
|
||||
|
||||
inline class IPkgJsStaticInterop {
|
||||
final PkgJsStaticInterop obj;
|
||||
external IPkgJsStaticInterop();
|
||||
}
|
||||
extension type EPkgJsStaticInterop(PkgJsStaticInterop _) {}
|
||||
|
||||
@JS()
|
||||
@staticInterop
|
||||
class StaticInterop {}
|
||||
|
||||
inline class IStaticInterop {
|
||||
final StaticInterop obj;
|
||||
external IStaticInterop();
|
||||
}
|
||||
extension type EStaticInterop(StaticInterop _) {}
|
||||
|
||||
// @Native types.
|
||||
|
||||
inline class IWindow {
|
||||
final Window obj;
|
||||
external IWindow();
|
||||
}
|
||||
extension type EWindow(Window _) {}
|
||||
|
||||
@JS()
|
||||
inline class IDocument {
|
||||
final Document obj;
|
||||
external IDocument();
|
||||
}
|
||||
extension type EDocument(Document _) {}
|
||||
|
||||
// Inline types.
|
||||
// Extension types.
|
||||
|
||||
inline class IInlineInterop {
|
||||
final IJSObject obj;
|
||||
external IInlineInterop();
|
||||
}
|
||||
extension type EExtensionType(EJSObject _) {}
|
||||
|
||||
@JS()
|
||||
inline class IInlineInterop2 {
|
||||
final IInlineInterop obj;
|
||||
external IInlineInterop2();
|
||||
}
|
||||
|
||||
extension type EExtensionType2(EExtensionType _) {}
|
||||
@JS()
|
||||
inline class IInlineNonInterop {
|
||||
// ^
|
||||
// [web] Inline class 'IInlineNonInterop' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'IObject'.
|
||||
final IObject obj;
|
||||
external IInlineNonInterop();
|
||||
extension type ENonInterop._(EObject _) {
|
||||
// ^
|
||||
// [web] Extension type 'ENonInterop' is marked with a '@JS' annotation, but its representation type is not a valid JS interop type: 'EObject'.
|
||||
external ENonInterop();
|
||||
// ^
|
||||
// [web] Inline class member is marked 'external', but the representation type of its inline class is not a valid JS interop type.
|
||||
// [web] Extension type member is marked 'external', but the representation type of its extension type is not a valid JS interop type.
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ import 'dart:js_util';
|
|||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
inline class Literal {
|
||||
final JSObject obj;
|
||||
extension type Literal._(JSObject _) {
|
||||
external Literal({double? a, String b, bool? c});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,9 @@ external void topLevel({JSNumber named});
|
|||
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
|
||||
|
||||
@JS()
|
||||
inline class Inline {
|
||||
final JSObject obj;
|
||||
external Inline.positionalNamed(JSNumber positional, {JSNumber named});
|
||||
// ^
|
||||
extension type ExtensionType(JSObject _) {
|
||||
external ExtensionType.positionalNamed(JSNumber positional, {JSNumber named});
|
||||
// ^
|
||||
// [web] Object literal constructors should not contain any positional parameters.
|
||||
external static void staticMethod({JSNumber named});
|
||||
// ^
|
||||
|
@ -25,7 +24,7 @@ inline class Inline {
|
|||
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
|
||||
}
|
||||
|
||||
extension on Inline {
|
||||
extension on ExtensionType {
|
||||
external void extensionMethod({JSNumber named});
|
||||
// ^
|
||||
// [web] Named parameters for JS interop functions are only allowed in object literal constructors or @anonymous factories.
|
||||
|
|
|
@ -80,10 +80,7 @@ extension _ on StaticInterop {
|
|||
}
|
||||
|
||||
@JS()
|
||||
inline class Inline {
|
||||
final JSObject obj;
|
||||
external Inline();
|
||||
|
||||
extension type ExtensionType(JSObject _) {
|
||||
external void operator <(_);
|
||||
// ^
|
||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||
|
|
|
@ -80,12 +80,9 @@ extension on StaticInterop {
|
|||
}
|
||||
|
||||
@JS()
|
||||
inline class InlineClass {
|
||||
final JSObject obj;
|
||||
external InlineClass();
|
||||
}
|
||||
extension type ExtensionType(JSObject _) {}
|
||||
|
||||
extension on InlineClass {
|
||||
extension on ExtensionType {
|
||||
external static JSNumber field;
|
||||
// ^
|
||||
// [web] External extension members with the keyword 'static' on JS interop and @Native types are disallowed.
|
||||
|
|
|
@ -79,10 +79,7 @@ extension JSClassExtension on JSClass {
|
|||
}
|
||||
|
||||
@JS()
|
||||
inline class Inline {
|
||||
final JSObject obj;
|
||||
external Inline();
|
||||
}
|
||||
extension type ExtensionType(JSObject _) {}
|
||||
|
||||
@JS()
|
||||
external void jsFunctionTest(JSFunction foo);
|
||||
|
@ -91,7 +88,7 @@ external void jsFunctionTest(JSFunction foo);
|
|||
external void useStaticInteropClass(JSClass foo);
|
||||
|
||||
@JS()
|
||||
external void useStaticInteropInlineClass(Inline foo);
|
||||
external void useStaticInteropExtensionType(ExtensionType foo);
|
||||
|
||||
void main() {
|
||||
jsFunctionTest(((double foo) => 4.0.toJS).toJS);
|
||||
|
@ -105,4 +102,4 @@ void main() {
|
|||
jsFunctionTest(((((JSNumber foo) => 4.0) as dynamic) as Function).toJS);
|
||||
// ^
|
||||
// [web] `Function.toJS` requires a statically known function type, but Type 'Function' is not a function type, e.g., `void Function()`.
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue