mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[dart:js_interop] Re-enable type checks on external APIs
External APIs when using dart:js_interop should only allow primitives, JS types, and other static interop types. This was previously checked in a more restrictive mode called "strict mode" but is not checked everywhere where dart:js_interop APIs exist. Change-Id: Ic82a3ec0bf6062c25d7f8933e503820a21bc191f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316867 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
parent
cf5336c244
commit
2a669c571f
|
@ -96,7 +96,7 @@ constraint][language version] lower bound to 3.2 or greater (`sdk: '^3.2.0'`).
|
||||||
|
|
||||||
#### `dart:js_interop`
|
#### `dart:js_interop`
|
||||||
|
|
||||||
- **JSNumber.toDart and Object.toJS**:
|
- **Breaking Change on JSNumber.toDart and Object.toJS**:
|
||||||
`JSNumber.toDart` is removed in favor of `toDartDouble` and `toDartInt` to
|
`JSNumber.toDart` is removed in favor of `toDartDouble` and `toDartInt` to
|
||||||
make the type explicit. `Object.toJS` is also removed in favor of
|
make the type explicit. `Object.toJS` is also removed in favor of
|
||||||
`Object.toJSBox`. Previously, this function would allow Dart objects to flow
|
`Object.toJSBox`. Previously, this function would allow Dart objects to flow
|
||||||
|
@ -128,6 +128,11 @@ constraint][language version] lower bound to 3.2 or greater (`sdk: '^3.2.0'`).
|
||||||
number of cases, like when using older browser versions. `dart:js_interop`'s
|
number of cases, like when using older browser versions. `dart:js_interop`'s
|
||||||
`globalJSObject` is also renamed to `globalContext` and returns the global
|
`globalJSObject` is also renamed to `globalContext` and returns the global
|
||||||
context used in the lowerings.
|
context used in the lowerings.
|
||||||
|
- **Breaking Change on Types of `dart:js_interop` External APIs**:
|
||||||
|
External JS interop APIs when using `dart:js_interop` are restricted to a set
|
||||||
|
of allowed types. Namely, this include the primitive types like `String`, JS
|
||||||
|
types from `dart:js_interop`, and other static interop types (either through
|
||||||
|
`@staticInterop` or extension types).
|
||||||
|
|
||||||
### Tools
|
### Tools
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ import 'package:front_end/src/fasta/fasta_codes.dart'
|
||||||
show
|
show
|
||||||
templateJsInteropExtensionTypeNotInterop,
|
templateJsInteropExtensionTypeNotInterop,
|
||||||
templateJsInteropFunctionToJSRequiresStaticType,
|
templateJsInteropFunctionToJSRequiresStaticType,
|
||||||
templateJsInteropStrictModeViolation;
|
templateJsInteropStaticInteropExternalTypeViolation;
|
||||||
|
|
||||||
import 'package:kernel/class_hierarchy.dart';
|
import 'package:kernel/class_hierarchy.dart';
|
||||||
import 'package:kernel/core_types.dart';
|
import 'package:kernel/core_types.dart';
|
||||||
|
@ -73,18 +73,12 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
bool _classHasJSAnnotation = false;
|
bool _classHasJSAnnotation = false;
|
||||||
bool _classHasAnonymousAnnotation = false;
|
bool _classHasAnonymousAnnotation = false;
|
||||||
bool _classHasStaticInteropAnnotation = false;
|
bool _classHasStaticInteropAnnotation = false;
|
||||||
|
final _checkDisallowedInterop = false;
|
||||||
bool _inTearoff = false;
|
bool _inTearoff = false;
|
||||||
bool _libraryHasDartJSInteropAnnotation = false;
|
bool _libraryHasDartJSInteropAnnotation = false;
|
||||||
bool _libraryHasJSAnnotation = false;
|
bool _libraryHasJSAnnotation = false;
|
||||||
bool _libraryIsGlobalNamespace = false;
|
bool _libraryIsGlobalNamespace = false;
|
||||||
|
|
||||||
// TODO(joshualitt): Today strict mode is just for testing, but we should find
|
|
||||||
// a way to expose this to users who want strict mode guarantees.
|
|
||||||
bool _enforceStrictMode = false;
|
|
||||||
|
|
||||||
/// If [enableStrictMode] is true, then static interop methods must use JS
|
|
||||||
/// types.
|
|
||||||
final bool enableStrictMode;
|
|
||||||
final ExportChecker exportChecker;
|
final ExportChecker exportChecker;
|
||||||
final bool isDart2Wasm;
|
final bool isDart2Wasm;
|
||||||
|
|
||||||
|
@ -144,7 +138,7 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
|
|
||||||
JsInteropChecks(this._coreTypes, ClassHierarchy hierarchy, this._reporter,
|
JsInteropChecks(this._coreTypes, ClassHierarchy hierarchy, this._reporter,
|
||||||
this._nativeClasses,
|
this._nativeClasses,
|
||||||
{this.isDart2Wasm = false, this.enableStrictMode = false})
|
{this.isDart2Wasm = false})
|
||||||
: exportChecker = ExportChecker(_reporter, _coreTypes.objectClass),
|
: exportChecker = ExportChecker(_reporter, _coreTypes.objectClass),
|
||||||
_functionToJSTarget = _coreTypes.index.getTopLevelProcedure(
|
_functionToJSTarget = _coreTypes.index.getTopLevelProcedure(
|
||||||
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
|
'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'),
|
||||||
|
@ -303,11 +297,11 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
_libraryHasJSAnnotation =
|
_libraryHasJSAnnotation =
|
||||||
_libraryHasDartJSInteropAnnotation || hasJSInteropAnnotation(node);
|
_libraryHasDartJSInteropAnnotation || hasJSInteropAnnotation(node);
|
||||||
_libraryIsGlobalNamespace = _isLibraryGlobalNamespace(node);
|
_libraryIsGlobalNamespace = _isLibraryGlobalNamespace(node);
|
||||||
_enforceStrictMode = _shouldEnforceStrictMode(node);
|
|
||||||
|
|
||||||
if (_enforceStrictMode && !node.importUri.isScheme('dart')) {
|
// TODO(srujzs): Should we still keep around this check? Currently, it's
|
||||||
_checkDisallowedLibrariesInStrictMode(node);
|
// unused since we allow the old interop on dart2wasm, but we should
|
||||||
}
|
// disallow them eventually.
|
||||||
|
if (_checkDisallowedInterop) _checkDisallowedLibrariesForDart2Wasm(node);
|
||||||
|
|
||||||
super.visitLibrary(node);
|
super.visitLibrary(node);
|
||||||
exportChecker.visitLibrary(node);
|
exportChecker.visitLibrary(node);
|
||||||
|
@ -364,18 +358,6 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
report(messageJsInteropInvalidStaticClassMemberName);
|
report(messageJsInteropInvalidStaticClassMemberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In strict mode, check all types are JS types.
|
|
||||||
if (enableStrictMode) {
|
|
||||||
final function = node.function;
|
|
||||||
_reportProcedureIfNotJSType(function.returnType, node);
|
|
||||||
for (final parameter in function.positionalParameters) {
|
|
||||||
_reportProcedureIfNotJSType(parameter.type, node);
|
|
||||||
}
|
|
||||||
for (final parameter in function.namedParameters) {
|
|
||||||
_reportProcedureIfNotJSType(parameter.type, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_classHasStaticInteropAnnotation ||
|
if (_classHasStaticInteropAnnotation ||
|
||||||
node.isExtensionTypeMember ||
|
node.isExtensionTypeMember ||
|
||||||
node.isExtensionMember ||
|
node.isExtensionMember ||
|
||||||
|
@ -403,8 +385,16 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
if (annotatable == null ||
|
if (annotatable == null ||
|
||||||
((hasDartJSInteropAnnotation(annotatable) ||
|
((hasDartJSInteropAnnotation(annotatable) ||
|
||||||
annotatable is ExtensionTypeDeclaration))) {
|
annotatable is ExtensionTypeDeclaration))) {
|
||||||
// Only restrict type parameters for dart:js_interop.
|
// Checks for dart:js_interop APIs only.
|
||||||
_checkStaticInteropMemberUsesValidTypeParameters(node);
|
_checkStaticInteropMemberUsesValidTypeParameters(node);
|
||||||
|
final function = node.function;
|
||||||
|
_reportProcedureIfNotAllowedType(function.returnType, node);
|
||||||
|
for (final parameter in function.positionalParameters) {
|
||||||
|
_reportProcedureIfNotAllowedType(parameter.type, node);
|
||||||
|
}
|
||||||
|
for (final parameter in function.namedParameters) {
|
||||||
|
_reportProcedureIfNotAllowedType(parameter.type, node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,14 +520,7 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
|
|
||||||
// JS interop library checks
|
// JS interop library checks
|
||||||
|
|
||||||
/// Determine if [node] enforces strict mode checking. This is currently only
|
void _checkDisallowedLibrariesForDart2Wasm(Library node) {
|
||||||
/// enabled for testing.
|
|
||||||
bool _shouldEnforceStrictMode(Library node) {
|
|
||||||
return node.fileUri.toString().contains(RegExp(
|
|
||||||
r'(?<!generated_)tests/lib/js/static_interop_test/strict_mode_test.dart'));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _checkDisallowedLibrariesInStrictMode(Library node) {
|
|
||||||
for (final dependency in node.dependencies) {
|
for (final dependency in node.dependencies) {
|
||||||
final dependencyUriString = dependency.targetLibrary.importUri.toString();
|
final dependencyUriString = dependency.targetLibrary.importUri.toString();
|
||||||
if (_disallowedLibrariesInStrictMode.contains(dependencyUriString)) {
|
if (_disallowedLibrariesInStrictMode.contains(dependencyUriString)) {
|
||||||
|
@ -735,9 +718,9 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
node.name.text.length,
|
node.name.text.length,
|
||||||
node.location?.file);
|
node.location?.file);
|
||||||
} else {
|
} else {
|
||||||
_reportStaticInvocationIfNotJSType(functionType.returnType, node);
|
_reportStaticInvocationIfNotAllowedType(functionType.returnType, node);
|
||||||
for (final parameter in functionType.positionalParameters) {
|
for (final parameter in functionType.positionalParameters) {
|
||||||
_reportStaticInvocationIfNotJSType(parameter, node);
|
_reportStaticInvocationIfNotAllowedType(parameter, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,8 +929,7 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reportIfNotJSType(
|
bool _isAllowedExternalType(DartType type) {
|
||||||
DartType type, TreeNode node, Name name, Uri? fileUri) {
|
|
||||||
// TODO(joshualitt): We allow only JS types on external JS interop APIs with
|
// TODO(joshualitt): We allow only JS types on external JS interop APIs with
|
||||||
// two exceptions: `void` and `Null`. Both of these exceptions exist largely
|
// two exceptions: `void` and `Null`. Both of these exceptions exist largely
|
||||||
// to support passing Dart functions to JS as callbacks. Furthermore, both
|
// to support passing Dart functions to JS as callbacks. Furthermore, both
|
||||||
|
@ -955,28 +937,54 @@ class JsInteropChecks extends RecursiveVisitor {
|
||||||
// said, for completeness, we may restrict these two types someday, and
|
// said, for completeness, we may restrict these two types someday, and
|
||||||
// provide JS types equivalents, but likely only if we have implicit
|
// provide JS types equivalents, but likely only if we have implicit
|
||||||
// conversions between Dart types and JS types.
|
// conversions between Dart types and JS types.
|
||||||
if (_enforceStrictMode &&
|
|
||||||
!(type is VoidType ||
|
// Type parameter types are checked elsewhere.
|
||||||
type is NullType ||
|
if (type is VoidType || type is NullType || type is TypeParameterType) {
|
||||||
(type is InterfaceType &&
|
return true;
|
||||||
hasStaticInteropAnnotation(type.classNode)) ||
|
}
|
||||||
(type is ExtensionType &&
|
if (type is InterfaceType) {
|
||||||
_extensionIndex
|
final cls = type.classNode;
|
||||||
.isInteropExtensionType(type.extensionTypeDeclaration)))) {
|
if (cls == _coreTypes.boolClass ||
|
||||||
|
cls == _coreTypes.numClass ||
|
||||||
|
cls == _coreTypes.doubleClass ||
|
||||||
|
cls == _coreTypes.intClass ||
|
||||||
|
cls == _coreTypes.stringClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (hasStaticInteropAnnotation(cls)) return true;
|
||||||
|
}
|
||||||
|
if (type is ExtensionType) {
|
||||||
|
if (_extensionIndex
|
||||||
|
.isInteropExtensionType(type.extensionTypeDeclaration)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Extension types where the representation type is allowed are okay.
|
||||||
|
// TODO(srujzs): Once the CFE pre-computes the concrete type, don't
|
||||||
|
// recurse.
|
||||||
|
return _isAllowedExternalType(type.typeErasure);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _reportIfNotAllowedExternalType(
|
||||||
|
DartType type, TreeNode node, Name name, Uri? fileUri) {
|
||||||
|
if (!_isAllowedExternalType(type)) {
|
||||||
_reporter.report(
|
_reporter.report(
|
||||||
templateJsInteropStrictModeViolation.withArguments(type, true),
|
templateJsInteropStaticInteropExternalTypeViolation.withArguments(
|
||||||
|
type, true),
|
||||||
node.fileOffset,
|
node.fileOffset,
|
||||||
name.text.length,
|
name.text.length,
|
||||||
fileUri);
|
fileUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reportProcedureIfNotJSType(DartType type, Procedure node) =>
|
void _reportProcedureIfNotAllowedType(DartType type, Procedure node) =>
|
||||||
_reportIfNotJSType(type, node, node.name, node.fileUri);
|
_reportIfNotAllowedExternalType(type, node, node.name, node.fileUri);
|
||||||
|
|
||||||
void _reportStaticInvocationIfNotJSType(
|
void _reportStaticInvocationIfNotAllowedType(
|
||||||
DartType type, StaticInvocation node) =>
|
DartType type, StaticInvocation node) =>
|
||||||
_reportIfNotJSType(type, node, node.name, node.location?.file);
|
_reportIfNotAllowedExternalType(
|
||||||
|
type, node, node.name, node.location?.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor used to check that all usages of type parameter types of an external
|
/// Visitor used to check that all usages of type parameter types of an external
|
||||||
|
|
|
@ -166,7 +166,7 @@ class WasmTarget extends Target {
|
||||||
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>);
|
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>);
|
||||||
final jsInteropChecks = JsInteropChecks(
|
final jsInteropChecks = JsInteropChecks(
|
||||||
coreTypes, hierarchy, jsInteropReporter, _nativeClasses!,
|
coreTypes, hierarchy, jsInteropReporter, _nativeClasses!,
|
||||||
isDart2Wasm: true, enableStrictMode: true);
|
isDart2Wasm: true);
|
||||||
// Process and validate first before doing anything with exports.
|
// Process and validate first before doing anything with exports.
|
||||||
for (Library library in interopDependentLibraries) {
|
for (Library library in interopDependentLibraries) {
|
||||||
jsInteropChecks.visitLibrary(library);
|
jsInteropChecks.visitLibrary(library);
|
||||||
|
|
|
@ -4108,6 +4108,38 @@ Message _withArgumentsJsInteropFunctionToJSRequiresStaticType(
|
||||||
arguments: {'type': _type});
|
arguments: {'type': _type});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
|
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
||||||
|
templateJsInteropStaticInteropExternalTypeViolation = const Template<
|
||||||
|
Message Function(DartType _type, bool isNonNullableByDefault)>(
|
||||||
|
"JsInteropStaticInteropExternalTypeViolation",
|
||||||
|
problemMessageTemplate:
|
||||||
|
r"""Type '#type' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.""",
|
||||||
|
correctionMessageTemplate: r"""Use one of the valid types instead.""",
|
||||||
|
withArguments:
|
||||||
|
_withArgumentsJsInteropStaticInteropExternalTypeViolation);
|
||||||
|
|
||||||
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
|
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
|
||||||
|
codeJsInteropStaticInteropExternalTypeViolation =
|
||||||
|
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
|
||||||
|
"JsInteropStaticInteropExternalTypeViolation",
|
||||||
|
);
|
||||||
|
|
||||||
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
|
Message _withArgumentsJsInteropStaticInteropExternalTypeViolation(
|
||||||
|
DartType _type, bool isNonNullableByDefault) {
|
||||||
|
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
|
||||||
|
List<Object> typeParts = labeler.labelType(_type);
|
||||||
|
String type = typeParts.join();
|
||||||
|
return new Message(codeJsInteropStaticInteropExternalTypeViolation,
|
||||||
|
problemMessage:
|
||||||
|
"""Type '${type}' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.""" +
|
||||||
|
labeler.originMessages,
|
||||||
|
correctionMessage: """Use one of the valid types instead.""",
|
||||||
|
arguments: {'type': _type});
|
||||||
|
}
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
||||||
templateJsInteropStaticInteropMockNotStaticInteropType = const Template<
|
templateJsInteropStaticInteropMockNotStaticInteropType = const Template<
|
||||||
|
@ -4173,37 +4205,6 @@ Message _withArgumentsJsInteropStaticInteropMockTypeParametersNotAllowed(
|
||||||
arguments: {'type': _type});
|
arguments: {'type': _type});
|
||||||
}
|
}
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
|
||||||
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
|
|
||||||
templateJsInteropStrictModeViolation = const Template<
|
|
||||||
Message Function(DartType _type, bool isNonNullableByDefault)>(
|
|
||||||
"JsInteropStrictModeViolation",
|
|
||||||
problemMessageTemplate:
|
|
||||||
r"""JS interop requires JS types when strict mode is enabled, but Type '#type' is not a type or subtype of a type from `dart:js_interop`.""",
|
|
||||||
correctionMessageTemplate: r"""Use a JS type instead.""",
|
|
||||||
withArguments: _withArgumentsJsInteropStrictModeViolation);
|
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
|
||||||
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
|
|
||||||
codeJsInteropStrictModeViolation =
|
|
||||||
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
|
|
||||||
"JsInteropStrictModeViolation",
|
|
||||||
);
|
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
|
||||||
Message _withArgumentsJsInteropStrictModeViolation(
|
|
||||||
DartType _type, bool isNonNullableByDefault) {
|
|
||||||
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
|
|
||||||
List<Object> typeParts = labeler.labelType(_type);
|
|
||||||
String type = typeParts.join();
|
|
||||||
return new Message(codeJsInteropStrictModeViolation,
|
|
||||||
problemMessage:
|
|
||||||
"""JS interop requires JS types when strict mode is enabled, but Type '${type}' is not a type or subtype of a type from `dart:js_interop`.""" +
|
|
||||||
labeler.originMessages,
|
|
||||||
correctionMessage: """Use a JS type instead.""",
|
|
||||||
arguments: {'type': _type});
|
|
||||||
}
|
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
const Template<
|
const Template<
|
||||||
Message Function(
|
Message Function(
|
||||||
|
|
|
@ -624,6 +624,8 @@ JsInteropObjectLiteralConstructorPositionalParameters/analyzerCode: Fail # Web c
|
||||||
JsInteropObjectLiteralConstructorPositionalParameters/example: Fail # Web compiler specific
|
JsInteropObjectLiteralConstructorPositionalParameters/example: Fail # Web compiler specific
|
||||||
JsInteropStaticInteropExternalMemberWithInvalidTypeParameters/analyzerCode: Fail # Web compiler specific
|
JsInteropStaticInteropExternalMemberWithInvalidTypeParameters/analyzerCode: Fail # Web compiler specific
|
||||||
JsInteropStaticInteropExternalMemberWithInvalidTypeParameters/example: Fail # Web compiler specific
|
JsInteropStaticInteropExternalMemberWithInvalidTypeParameters/example: Fail # Web compiler specific
|
||||||
|
JsInteropStaticInteropExternalTypeViolation/analyzerCode: Fail # Web compiler specific
|
||||||
|
JsInteropStaticInteropExternalTypeViolation/example: Fail # Web compiler specific
|
||||||
JsInteropStaticInteropGenerativeConstructor/analyzerCode: Fail # Web compiler specific
|
JsInteropStaticInteropGenerativeConstructor/analyzerCode: Fail # Web compiler specific
|
||||||
JsInteropStaticInteropGenerativeConstructor/example: Fail # Web compiler specific
|
JsInteropStaticInteropGenerativeConstructor/example: Fail # Web compiler specific
|
||||||
JsInteropStaticInteropMockMissingGetterOrSetter/analyzerCode: Fail # Web compiler specific
|
JsInteropStaticInteropMockMissingGetterOrSetter/analyzerCode: Fail # Web compiler specific
|
||||||
|
@ -654,8 +656,6 @@ JsInteropStaticInteropWithNonStaticSupertype/analyzerCode: Fail # Web compiler s
|
||||||
JsInteropStaticInteropWithNonStaticSupertype/example: Fail # Web compiler specific
|
JsInteropStaticInteropWithNonStaticSupertype/example: Fail # Web compiler specific
|
||||||
JsInteropFunctionToJSRequiresStaticType/analyzerCode: Fail # Web compiler specific
|
JsInteropFunctionToJSRequiresStaticType/analyzerCode: Fail # Web compiler specific
|
||||||
JsInteropFunctionToJSRequiresStaticType/example: Fail # Web compiler specific
|
JsInteropFunctionToJSRequiresStaticType/example: Fail # Web compiler specific
|
||||||
JsInteropStrictModeViolation/analyzerCode: Fail # Web compiler specific
|
|
||||||
JsInteropStrictModeViolation/example: Fail # Web compiler specific
|
|
||||||
JsInteropStrictModeForbiddenLibrary/analyzerCode: Fail # Web compiler specific
|
JsInteropStrictModeForbiddenLibrary/analyzerCode: Fail # Web compiler specific
|
||||||
JsInteropStrictModeForbiddenLibrary/example: Fail # Web compiler specific
|
JsInteropStrictModeForbiddenLibrary/example: Fail # Web compiler specific
|
||||||
LanguageVersionInvalidInDotPackages/analyzerCode: Fail
|
LanguageVersionInvalidInDotPackages/analyzerCode: Fail
|
||||||
|
|
|
@ -5669,6 +5669,10 @@ JsInteropStaticInteropExternalMemberWithInvalidTypeParameters:
|
||||||
problemMessage: "External static interop members can only use type parameters that extend either a static interop type or one of the 'dart:js_interop' types."
|
problemMessage: "External static interop members can only use type parameters that extend either a static interop type or one of the 'dart:js_interop' types."
|
||||||
correctionMessage: "Try adding a valid bound to the type parameters used in this member."
|
correctionMessage: "Try adding a valid bound to the type parameters used in this member."
|
||||||
|
|
||||||
|
JsInteropStaticInteropExternalTypeViolation:
|
||||||
|
problemMessage: "Type '#type' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types."
|
||||||
|
correctionMessage: "Use one of the valid types instead."
|
||||||
|
|
||||||
JsInteropStaticInteropGenerativeConstructor:
|
JsInteropStaticInteropGenerativeConstructor:
|
||||||
problemMessage: "`@staticInterop` classes should not contain any generative constructors."
|
problemMessage: "`@staticInterop` classes should not contain any generative constructors."
|
||||||
correctionMessage: "Use factory constructors instead."
|
correctionMessage: "Use factory constructors instead."
|
||||||
|
@ -5726,10 +5730,6 @@ JsInteropStaticInteropWithNonStaticSupertype:
|
||||||
problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which does not."
|
problemMessage: "JS interop class '#name' has an `@staticInterop` annotation, but has supertype '#name2', which does not."
|
||||||
correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
|
correctionMessage: "Try marking the supertype as a static interop class using `@staticInterop`."
|
||||||
|
|
||||||
JsInteropStrictModeViolation:
|
|
||||||
problemMessage: "JS interop requires JS types when strict mode is enabled, but Type '#type' is not a type or subtype of a type from `dart:js_interop`."
|
|
||||||
correctionMessage: "Use a JS type instead."
|
|
||||||
|
|
||||||
JsInteropStrictModeForbiddenLibrary:
|
JsInteropStrictModeForbiddenLibrary:
|
||||||
problemMessage: "Library '#name' is forbidden when strict mode is enabled."
|
problemMessage: "Library '#name' is forbidden when strict mode is enabled."
|
||||||
correctionMessage: "Remove the import of a forbidden library."
|
correctionMessage: "Remove the import of a forbidden library."
|
||||||
|
|
|
@ -15,6 +15,7 @@ abispecificintegermapping
|
||||||
adjusting
|
adjusting
|
||||||
annotate
|
annotate
|
||||||
api
|
api
|
||||||
|
apis
|
||||||
argument(s)
|
argument(s)
|
||||||
assigning
|
assigning
|
||||||
augment
|
augment
|
||||||
|
|
|
@ -12,13 +12,15 @@ import 'dart:js_interop';
|
||||||
|
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
// To test non-JS types for @staticInterop.
|
||||||
|
import 'package:js/js.dart' as pkgJs;
|
||||||
import 'package:js/js_util.dart' as js_util;
|
import 'package:js/js_util.dart' as js_util;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external void eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@pkgJs.JS()
|
||||||
@staticInterop
|
@pkgJs.staticInterop
|
||||||
class Foo<T extends JSAny?, U extends Nested> {
|
class Foo<T extends JSAny?, U extends Nested> {
|
||||||
external factory Foo(int a);
|
external factory Foo(int a);
|
||||||
}
|
}
|
||||||
|
@ -64,8 +66,8 @@ extension FooExt<T extends JSAny?, U extends Nested> on Foo<T, U> {
|
||||||
external R combineNestedGeneric<R extends Nested>(R a, [R b]);
|
external R combineNestedGeneric<R extends Nested>(R a, [R b]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JS('module.Bar')
|
@pkgJs.JS('module.Bar')
|
||||||
@staticInterop
|
@pkgJs.staticInterop
|
||||||
class Bar {
|
class Bar {
|
||||||
external factory Bar(int a);
|
external factory Bar(int a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ external T invalidTopLevel<T>(T t);
|
||||||
|
|
||||||
typedef Typedef<T> = T Function();
|
typedef Typedef<T> = T Function();
|
||||||
|
|
||||||
|
extension type JSList<T>._(JSAny? _) {}
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
class Uninstantiated<W, X extends Instantiated?> {
|
class Uninstantiated<W, X extends Instantiated?> {
|
||||||
|
@ -68,12 +70,11 @@ extension UninstantiatedExtension<T, U extends JSAny?, V extends Instantiated>
|
||||||
external void consumeV(V v);
|
external void consumeV(V v);
|
||||||
|
|
||||||
// Test type parameters in a nested type context.
|
// Test type parameters in a nested type context.
|
||||||
Set<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
JSList<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
||||||
external Set<Typedef<T>> get getNestedT;
|
// No error as JSList is an interop extension type.
|
||||||
// ^
|
external JSList<Typedef<T>> get getNestedT;
|
||||||
// [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 JSList<Typedef<U>> get getNestedU;
|
||||||
external Set<Typedef<U>> get getNestedU;
|
external JSList<Typedef<V>> get getNestedV;
|
||||||
external Set<Typedef<V>> get getNestedV;
|
|
||||||
|
|
||||||
// Test type parameters that are declared by the member.
|
// Test type parameters that are declared by the member.
|
||||||
W returnWDart<W>() => throw UnimplementedError();
|
W returnWDart<W>() => throw UnimplementedError();
|
||||||
|
@ -126,12 +127,11 @@ extension type UninstantiatedExtensionType<T, U extends JSAny?,
|
||||||
external void consumeV(V v);
|
external void consumeV(V v);
|
||||||
|
|
||||||
// Test type parameters in a nested type context.
|
// Test type parameters in a nested type context.
|
||||||
Set<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
JSList<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
||||||
external Set<Typedef<T>> get getNestedT;
|
// No error as JSList is an interop extension type.
|
||||||
// ^
|
external JSList<Typedef<T>> get getNestedT;
|
||||||
// [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 JSList<Typedef<U>> get getNestedU;
|
||||||
external Set<Typedef<U>> get getNestedU;
|
external JSList<Typedef<V>> get getNestedV;
|
||||||
external Set<Typedef<V>> get getNestedV;
|
|
||||||
|
|
||||||
// Test type parameters that are declared by the member.
|
// Test type parameters that are declared by the member.
|
||||||
W returnWDart<W>() => throw UnimplementedError();
|
W returnWDart<W>() => throw UnimplementedError();
|
||||||
|
@ -178,25 +178,25 @@ extension PkgJsExtension<T> on PkgJs<T> {
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
class Instantiated {
|
class Instantiated {
|
||||||
external factory Instantiated(List<JSNumber> list);
|
external factory Instantiated(JSList<JSNumber> list);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InstantiatedExtension on Instantiated {
|
extension InstantiatedExtension on Instantiated {
|
||||||
external List<Instantiated> fieldList;
|
external JSList<int> fieldList;
|
||||||
external List<Instantiated> get getList;
|
external JSList<int> get getList;
|
||||||
external set setList(List<Instantiated> list);
|
external set setList(JSList<int> list);
|
||||||
external List<Instantiated> returnList();
|
external JSList<int> returnList();
|
||||||
external void consumeList(List<Instantiated> list);
|
external void consumeList(JSList<int> list);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension type InstantiatedExtensionType._(JSObject _) {
|
extension type InstantiatedExtensionType._(JSObject _) {
|
||||||
// Test generic types where all the type parameters are instantiated.
|
// Test generic types where all the type parameters are instantiated.
|
||||||
external InstantiatedExtensionType(List<JSNumber> list);
|
external InstantiatedExtensionType(JSList<int> list);
|
||||||
external List<InstantiatedExtensionType> fieldList;
|
external JSList<int> fieldList;
|
||||||
external List<InstantiatedExtensionType> get getList;
|
external JSList<int> get getList;
|
||||||
external set setList(List<InstantiatedExtensionType> list);
|
external set setList(JSList<int> list);
|
||||||
external List<InstantiatedExtensionType> returnList();
|
external JSList<int> returnList();
|
||||||
external void consumeList(List<InstantiatedExtensionType> list);
|
external void consumeList(JSList<int> list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {}
|
void main() {}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'dart:js_interop';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:expect/minitest.dart';
|
||||||
import 'package:js/js.dart' show trustTypes;
|
import 'package:js/js.dart' show trustTypes;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS('ExternalStatic')
|
@JS('ExternalStatic')
|
||||||
@staticInterop
|
@staticInterop
|
||||||
|
|
|
@ -12,7 +12,7 @@ import 'dart:js_interop';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
extension type ExtensionType._(JSObject _) {
|
extension type ExtensionType._(JSObject _) {
|
||||||
external ExtensionType();
|
external ExtensionType();
|
||||||
|
|
|
@ -13,7 +13,7 @@ import 'package:expect/expect.dart';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
extension type External<T extends JSAny?, U extends Nested>._(JSObject _) {
|
extension type External<T extends JSAny?, U extends Nested>._(JSObject _) {
|
||||||
external External();
|
external External();
|
||||||
|
|
|
@ -13,7 +13,7 @@ import 'dart:js_util' as js_util;
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
extension type ExternalStatic._(JSObject obj) {
|
extension type ExternalStatic._(JSObject obj) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import 'dart:js_util' as js_util;
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS('library3.ExternalStatic')
|
@JS('library3.ExternalStatic')
|
||||||
extension type ExternalStatic._(JSObject obj) {
|
extension type ExternalStatic._(JSObject obj) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ library js_array_test;
|
||||||
import 'dart:js_interop';
|
import 'dart:js_interop';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
// dart:js_interop top-levels do return-type checks so if the call to these
|
// dart:js_interop top-levels do return-type checks so if the call to these
|
||||||
// getters succeed, it's enough to know they can be interoperable.
|
// getters succeed, it's enough to know they can be interoperable.
|
||||||
|
|
|
@ -12,10 +12,10 @@ import 'dart:js_interop';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external Object get obj;
|
external JSAny get obj;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
eval('''
|
eval('''
|
||||||
|
|
|
@ -10,7 +10,7 @@ library native_error_test;
|
||||||
import 'dart:js_interop';
|
import 'dart:js_interop';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
// dart:js_interop top-levels do return-type checks so if the call to these
|
// dart:js_interop top-levels do return-type checks so if the call to these
|
||||||
// getters succeed, it's enough to know they can be interoperable.
|
// getters succeed, it's enough to know they can be interoperable.
|
||||||
|
|
|
@ -16,60 +16,60 @@ class StaticInterop {}
|
||||||
extension _ on StaticInterop {
|
extension _ on StaticInterop {
|
||||||
// https://dart.dev/guides/language/language-tour#_operators for the list of
|
// https://dart.dev/guides/language/language-tour#_operators for the list of
|
||||||
// operators allowed by the language.
|
// operators allowed by the language.
|
||||||
external void operator <(_);
|
external void operator <(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >(_);
|
external void operator >(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator <=(_);
|
external void operator <=(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >=(_);
|
external void operator >=(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator -(_);
|
external void operator -(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator +(_);
|
external void operator +(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator /(_);
|
external void operator /(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator ~/(_);
|
external void operator ~/(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator *(_);
|
external void operator *(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator %(_);
|
external void operator %(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator |(_);
|
external void operator |(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator ^(_);
|
external void operator ^(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator &(_);
|
external void operator &(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator <<(_);
|
external void operator <<(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >>(_);
|
external void operator >>(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >>>(_);
|
external void operator >>>(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
@JS('rename')
|
@JS('rename')
|
||||||
external void operator [](_);
|
external void operator [](JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
||||||
@JS('rename')
|
@JS('rename')
|
||||||
external void operator []=(_, __);
|
external void operator []=(JSAny _, JSAny __);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
||||||
external void operator ~();
|
external void operator ~();
|
||||||
|
@ -81,60 +81,60 @@ extension _ on StaticInterop {
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
extension type ExtensionType(JSObject _) {
|
extension type ExtensionType(JSObject _) {
|
||||||
external void operator <(_);
|
external void operator <(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >(_);
|
external void operator >(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator <=(_);
|
external void operator <=(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >=(_);
|
external void operator >=(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator -(_);
|
external void operator -(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator +(_);
|
external void operator +(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator /(_);
|
external void operator /(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator ~/(_);
|
external void operator ~/(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator *(_);
|
external void operator *(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator %(_);
|
external void operator %(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator |(_);
|
external void operator |(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator ^(_);
|
external void operator ^(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator &(_);
|
external void operator &(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator <<(_);
|
external void operator <<(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >>(_);
|
external void operator >>(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
external void operator >>>(_);
|
external void operator >>>(JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
// [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop.
|
||||||
@JS('rename')
|
@JS('rename')
|
||||||
external void operator [](_);
|
external void operator [](JSAny _);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
||||||
@JS('rename')
|
@JS('rename')
|
||||||
external void operator []=(_, __);
|
external void operator []=(JSAny _, JSAny __);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
// [web] JS interop operator methods cannot be renamed using the '@JS' annotation.
|
||||||
external void operator ~();
|
external void operator ~();
|
||||||
|
|
|
@ -8,74 +8,49 @@
|
||||||
library strict_mode_test;
|
library strict_mode_test;
|
||||||
|
|
||||||
import 'dart:js_interop';
|
import 'dart:js_interop';
|
||||||
/**/ import 'dart:js';
|
import 'dart:js';
|
||||||
// ^
|
import 'dart:js_util';
|
||||||
// [web] Library 'dart:js' is forbidden when strict mode is enabled.
|
|
||||||
|
|
||||||
/**/ import 'dart:js_util';
|
|
||||||
// ^
|
|
||||||
// [web] Library 'dart:js_util' is forbidden when strict mode is enabled.
|
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
class JSClass {
|
class JSClass {
|
||||||
external factory JSClass(List<int> baz);
|
external factory JSClass(List<int> baz);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'List<int>' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'List<int>' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external factory JSClass.other(Object blu);
|
external factory JSClass.other(Object blu);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'Object' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'Object' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external static int foo();
|
external static dynamic foo();
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'int' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'dynamic' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external static JSClass foo1(String bar);
|
external static Function get fooGet;
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'String' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'Function' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external static Function foo2();
|
external static set fooSet(void Function() bar);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'Function' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'void Function()' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external static JSClass foo3(void Function() bar);
|
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'void Function()' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
|
|
||||||
external static double get fooGet;
|
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'double' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
|
|
||||||
external static set fooSet(String bar);
|
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'String' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension JSClassExtension on JSClass {
|
extension JSClassExtension on JSClass {
|
||||||
external dynamic extFoo();
|
external dynamic extFoo();
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'dynamic' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'dynamic' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external JSClass extFoo2(List<Object?> bar);
|
external JSClass extFoo2(List<Object?> bar);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'List<Object?>' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'List<Object?>' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external Function extFoo3(JSClass bar);
|
external Function get extFooGet;
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'Function' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'Function' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external JSClass extFoo4(void Function() bar);
|
external set extFooSet(void Function() bar);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'void Function()' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'void Function()' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
external double get extFooGet;
|
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'double' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
|
|
||||||
external set extFooSet(String bar);
|
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'String' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
|
@ -92,12 +67,16 @@ external void useStaticInteropExtensionType(ExtensionType foo);
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
jsFunctionTest(((double foo) => 4.0.toJS).toJS);
|
jsFunctionTest(((double foo) => 4.0.toJS).toJS);
|
||||||
// ^
|
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'double' is not a type or subtype of a type from `dart:js_interop`.
|
|
||||||
|
|
||||||
jsFunctionTest(((JSNumber foo) => 4.0).toJS);
|
jsFunctionTest(((JSNumber foo) => 4.0).toJS);
|
||||||
|
|
||||||
|
jsFunctionTest(((List foo) => 4.0).toJS);
|
||||||
// ^
|
// ^
|
||||||
// [web] JS interop requires JS types when strict mode is enabled, but Type 'double' is not a type or subtype of a type from `dart:js_interop`.
|
// [web] Type 'List<dynamic>' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
|
jsFunctionTest(((JSNumber foo) => () {}).toJS);
|
||||||
|
// ^
|
||||||
|
// [web] Type 'Null Function()' is not a valid type for external `dart:js_interop` APIs. The only valid types are: @staticInterop types, JS types from `dart:js_interop`, void, bool, num, double, int, String, and any extension type that erases to one of these types.
|
||||||
|
|
||||||
jsFunctionTest(((((JSNumber foo) => 4.0) as dynamic) as Function).toJS);
|
jsFunctionTest(((((JSNumber foo) => 4.0) as dynamic) as Function).toJS);
|
||||||
// ^
|
// ^
|
||||||
|
|
|
@ -22,7 +22,7 @@ external int get getter;
|
||||||
// ^
|
// ^
|
||||||
// [web] Only JS interop members may be 'external'.
|
// [web] Only JS interop members may be 'external'.
|
||||||
|
|
||||||
external set setter(_);
|
external set setter(int _);
|
||||||
// ^
|
// ^
|
||||||
// [web] Only JS interop members may be 'external'.
|
// [web] Only JS interop members may be 'external'.
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ external int annotatedFinalField;
|
||||||
external int get annotatedGetter;
|
external int get annotatedGetter;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external set annotatedSetter(_);
|
external set annotatedSetter(int _);
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external int annotatedMethod();
|
external int annotatedMethod();
|
||||||
|
|
|
@ -11,7 +11,7 @@ library typed_data_test;
|
||||||
import 'dart:js_interop';
|
import 'dart:js_interop';
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
// dart:js_interop top-levels do return-type checks so if the call to these
|
// dart:js_interop top-levels do return-type checks so if the call to these
|
||||||
// getters succeed, it's enough to know they can be interoperable.
|
// getters succeed, it's enough to know they can be interoperable.
|
||||||
|
|
|
@ -14,13 +14,15 @@ import 'dart:js_interop';
|
||||||
|
|
||||||
import 'package:expect/expect.dart';
|
import 'package:expect/expect.dart';
|
||||||
import 'package:expect/minitest.dart';
|
import 'package:expect/minitest.dart';
|
||||||
|
// To test non-JS types for @staticInterop.
|
||||||
|
import 'package:js/js.dart' as pkgJs;
|
||||||
import 'package:js/js_util.dart' as js_util;
|
import 'package:js/js_util.dart' as js_util;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external void eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@pkgJs.JS()
|
||||||
@staticInterop
|
@pkgJs.staticInterop
|
||||||
class Foo<T extends JSAny, U extends Nested> {
|
class Foo<T extends JSAny, U extends Nested> {
|
||||||
external factory Foo(int a);
|
external factory Foo(int a);
|
||||||
}
|
}
|
||||||
|
@ -66,8 +68,8 @@ extension FooExt<T extends JSAny, U extends Nested> on Foo<T, U> {
|
||||||
external R combineNestedGeneric<R extends Nested>(R a, [R b]);
|
external R combineNestedGeneric<R extends Nested>(R a, [R b]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JS('module.Bar')
|
@pkgJs.JS('module.Bar')
|
||||||
@staticInterop
|
@pkgJs.staticInterop
|
||||||
class Bar {
|
class Bar {
|
||||||
external factory Bar(int a);
|
external factory Bar(int a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ external T invalidTopLevel<T>(T t);
|
||||||
|
|
||||||
typedef Typedef<T> = T Function();
|
typedef Typedef<T> = T Function();
|
||||||
|
|
||||||
|
@JS()
|
||||||
|
@staticInterop
|
||||||
|
class JSList<T> {}
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
class Uninstantiated<W, X extends Instantiated> {
|
class Uninstantiated<W, X extends Instantiated> {
|
||||||
|
@ -66,12 +70,11 @@ extension UninstantiatedExtension<T, U extends JSAny, V extends Instantiated>
|
||||||
external void consumeV(V v);
|
external void consumeV(V v);
|
||||||
|
|
||||||
// Test type parameters in a nested type context.
|
// Test type parameters in a nested type context.
|
||||||
Set<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
JSList<Typedef<T>> get getNestedTDart => throw UnimplementedError();
|
||||||
external Set<Typedef<T>> get getNestedT;
|
// No error as JSList is an interop type.
|
||||||
// ^
|
external JSList<Typedef<T>> get getNestedT;
|
||||||
// [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 JSList<Typedef<U>> get getNestedU;
|
||||||
external Set<Typedef<U>> get getNestedU;
|
external JSList<Typedef<V>> get getNestedV;
|
||||||
external Set<Typedef<V>> get getNestedV;
|
|
||||||
|
|
||||||
// Test type parameters that are declared by the member.
|
// Test type parameters that are declared by the member.
|
||||||
W returnWDart<W>() => throw UnimplementedError();
|
W returnWDart<W>() => throw UnimplementedError();
|
||||||
|
@ -109,15 +112,15 @@ extension PkgJsExtension<T> on PkgJs<T> {
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
class Instantiated {
|
class Instantiated {
|
||||||
external factory Instantiated(List<JSNumber> list);
|
external factory Instantiated(JSList<JSNumber> list);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InstantiatedExtension on Instantiated {
|
extension InstantiatedExtension on Instantiated {
|
||||||
external List<Instantiated> fieldList;
|
external JSList<int> fieldList;
|
||||||
external List<Instantiated> get getList;
|
external JSList<int> get getList;
|
||||||
external set setList(List<Instantiated> list);
|
external set setList(JSList<int> list);
|
||||||
external List<Instantiated> returnList();
|
external JSList<int> returnList();
|
||||||
external void consumeList(List<Instantiated> list);
|
external void consumeList(JSList<int> list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {}
|
void main() {}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:expect/minitest.dart';
|
||||||
import 'package:js/js.dart' show staticInterop;
|
import 'package:js/js.dart' show staticInterop;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
@staticInterop
|
@staticInterop
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:expect/minitest.dart';
|
||||||
import 'package:js/js.dart' show trustTypes, staticInterop;
|
import 'package:js/js.dart' show trustTypes, staticInterop;
|
||||||
|
|
||||||
@JS()
|
@JS()
|
||||||
external dynamic eval(String code);
|
external void eval(String code);
|
||||||
|
|
||||||
@JS('ExternalStatic')
|
@JS('ExternalStatic')
|
||||||
@staticInterop
|
@staticInterop
|
||||||
|
|
Loading…
Reference in a new issue