From db214e8c81aa00897ea8f0b081fb1f95c61ba494 Mon Sep 17 00:00:00 2001 From: Jackson Gardner Date: Mon, 11 Sep 2023 19:31:20 +0000 Subject: [PATCH] Revert "[dart:js_interop] Re-enable type checks on external APIs" This reverts commit 2a669c571f2bf66de2099d3ca2201a7365bf692c. Reason for revert: Failing dart -> Flutter Engine roller. We need to make some changes on the engine side to prepare for re-enabling these checks. Original change's description: > [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 > Commit-Queue: Srujan Gaddam Change-Id: I54caf06976e215b2b576cedfc0013ee79c6682f6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324902 Commit-Queue: Srujan Gaddam Reviewed-by: Srujan Gaddam Reviewed-by: Sigmund Cherem Bot-Commit: Rubber Stamper --- CHANGELOG.md | 7 +- .../lib/js_interop_checks.dart | 110 ++++++++---------- pkg/dart2wasm/lib/target.dart | 2 +- .../src/fasta/fasta_codes_cfe_generated.dart | 63 +++++----- pkg/front_end/messages.status | 4 +- pkg/front_end/messages.yaml | 8 +- .../test/spell_checking_list_messages.txt | 1 - .../external_extension_members_test.dart | 10 +- ...al_member_type_parameters_static_test.dart | 48 ++++---- ...external_static_member_lowerings_test.dart | 2 +- ...atic_member_lowerings_trusttypes_test.dart | 2 +- .../external_extension_member_test.dart | 2 +- .../inline_class/external_member_test.dart | 2 +- .../external_static_member_test.dart | 2 +- ...al_static_member_with_namespaces_test.dart | 2 +- .../js/static_interop_test/js_array_test.dart | 2 +- .../jsobject_type_test.dart | 4 +- .../native_error_test.dart | 2 +- .../operator_static_test.dart | 72 ++++++------ .../static_interop_test/strict_mode_test.dart | 79 ++++++++----- ...p_level_member_annotation_static_test.dart | 4 +- .../static_interop_test/typed_data_test.dart | 2 +- .../external_extension_members_test.dart | 10 +- ...al_member_type_parameters_static_test.dart | 27 ++--- ...external_static_member_lowerings_test.dart | 2 +- ...atic_member_lowerings_trusttypes_test.dart | 2 +- 26 files changed, 235 insertions(+), 236 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe393dc9992..a4df70e5b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,7 +96,7 @@ constraint][language version] lower bound to 3.2 or greater (`sdk: '^3.2.0'`). #### `dart:js_interop` -- **Breaking Change on JSNumber.toDart and Object.toJS**: +- **JSNumber.toDart and Object.toJS**: `JSNumber.toDart` is removed in favor of `toDartDouble` and `toDartInt` to make the type explicit. `Object.toJS` is also removed in favor of `Object.toJSBox`. Previously, this function would allow Dart objects to flow @@ -128,11 +128,6 @@ 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 `globalJSObject` is also renamed to `globalContext` and returns the global 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 diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart index 7d5ad59f288..9e4fb76cb71 100644 --- a/pkg/_js_interop_checks/lib/js_interop_checks.dart +++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart @@ -48,7 +48,7 @@ import 'package:front_end/src/fasta/fasta_codes.dart' show templateJsInteropExtensionTypeNotInterop, templateJsInteropFunctionToJSRequiresStaticType, - templateJsInteropStaticInteropExternalTypeViolation; + templateJsInteropStrictModeViolation; import 'package:kernel/class_hierarchy.dart'; import 'package:kernel/core_types.dart'; @@ -73,12 +73,18 @@ class JsInteropChecks extends RecursiveVisitor { bool _classHasJSAnnotation = false; bool _classHasAnonymousAnnotation = false; bool _classHasStaticInteropAnnotation = false; - final _checkDisallowedInterop = false; bool _inTearoff = false; bool _libraryHasDartJSInteropAnnotation = false; bool _libraryHasJSAnnotation = 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 bool isDart2Wasm; @@ -131,7 +137,7 @@ class JsInteropChecks extends RecursiveVisitor { JsInteropChecks(this._coreTypes, ClassHierarchy hierarchy, this._reporter, this._nativeClasses, - {this.isDart2Wasm = false}) + {this.isDart2Wasm = false, this.enableStrictMode = false}) : exportChecker = ExportChecker(_reporter, _coreTypes.objectClass), _functionToJSTarget = _coreTypes.index.getTopLevelProcedure( 'dart:js_interop', 'FunctionToJSExportedDartFunction|get#toJS'), @@ -287,11 +293,11 @@ class JsInteropChecks extends RecursiveVisitor { _libraryHasJSAnnotation = _libraryHasDartJSInteropAnnotation || hasJSInteropAnnotation(node); _libraryIsGlobalNamespace = _isLibraryGlobalNamespace(node); + _enforceStrictMode = _shouldEnforceStrictMode(node); - // TODO(srujzs): Should we still keep around this check? Currently, it's - // unused since we allow the old interop on dart2wasm, but we should - // disallow them eventually. - if (_checkDisallowedInterop) _checkDisallowedLibrariesForDart2Wasm(node); + if (_enforceStrictMode && !node.importUri.isScheme('dart')) { + _checkDisallowedLibrariesInStrictMode(node); + } super.visitLibrary(node); exportChecker.visitLibrary(node); @@ -348,6 +354,18 @@ class JsInteropChecks extends RecursiveVisitor { 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 || node.isExtensionTypeMember || node.isExtensionMember || @@ -375,16 +393,8 @@ class JsInteropChecks extends RecursiveVisitor { if (annotatable == null || ((hasDartJSInteropAnnotation(annotatable) || annotatable is ExtensionTypeDeclaration))) { - // Checks for dart:js_interop APIs only. + // Only restrict type parameters for dart:js_interop. _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); - } } } } @@ -510,7 +520,14 @@ class JsInteropChecks extends RecursiveVisitor { // JS interop library checks - void _checkDisallowedLibrariesForDart2Wasm(Library node) { + /// Determine if [node] enforces strict mode checking. This is currently only + /// enabled for testing. + bool _shouldEnforceStrictMode(Library node) { + return node.fileUri.toString().contains(RegExp( + r'(? - _reportIfNotAllowedExternalType(type, node, node.name, node.fileUri); + void _reportProcedureIfNotJSType(DartType type, Procedure node) => + _reportIfNotJSType(type, node, node.name, node.fileUri); - void _reportStaticInvocationIfNotAllowedType( + void _reportStaticInvocationIfNotJSType( DartType type, StaticInvocation node) => - _reportIfNotAllowedExternalType( - type, node, node.name, node.location?.file); + _reportIfNotJSType(type, node, node.name, node.location?.file); } /// Visitor used to check that all usages of type parameter types of an external diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart index c2730fed52c..6bd1600d18b 100644 --- a/pkg/dart2wasm/lib/target.dart +++ b/pkg/dart2wasm/lib/target.dart @@ -215,7 +215,7 @@ class WasmTarget extends Target { diagnosticReporter as DiagnosticReporter); final jsInteropChecks = JsInteropChecks( coreTypes, hierarchy, jsInteropReporter, _nativeClasses!, - isDart2Wasm: true); + isDart2Wasm: true, enableStrictMode: true); // Process and validate first before doing anything with exports. for (Library library in interopDependentLibraries) { jsInteropChecks.visitLibrary(library); diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart index 2c2e4923f92..f60be6c1ddf 100644 --- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart +++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart @@ -4108,38 +4108,6 @@ Message _withArgumentsJsInteropFunctionToJSRequiresStaticType( arguments: {'type': _type}); } -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Template - 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 - codeJsInteropStaticInteropExternalTypeViolation = - const Code( - "JsInteropStaticInteropExternalTypeViolation", -); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -Message _withArgumentsJsInteropStaticInteropExternalTypeViolation( - DartType _type, bool isNonNullableByDefault) { - TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault); - List 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. const Template templateJsInteropStaticInteropMockNotStaticInteropType = const Template< @@ -4205,6 +4173,37 @@ Message _withArgumentsJsInteropStaticInteropMockTypeParametersNotAllowed( arguments: {'type': _type}); } +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Template + 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 + codeJsInteropStrictModeViolation = + const Code( + "JsInteropStrictModeViolation", +); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +Message _withArgumentsJsInteropStrictModeViolation( + DartType _type, bool isNonNullableByDefault) { + TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault); + List 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. const Template< Message Function( diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status index 9080ed4a3ae..c84289737a0 100644 --- a/pkg/front_end/messages.status +++ b/pkg/front_end/messages.status @@ -624,8 +624,6 @@ JsInteropObjectLiteralConstructorPositionalParameters/analyzerCode: Fail # Web c JsInteropObjectLiteralConstructorPositionalParameters/example: Fail # Web compiler specific JsInteropStaticInteropExternalMemberWithInvalidTypeParameters/analyzerCode: 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/example: Fail # Web compiler specific JsInteropStaticInteropMockMissingGetterOrSetter/analyzerCode: Fail # Web compiler specific @@ -656,6 +654,8 @@ JsInteropStaticInteropWithNonStaticSupertype/analyzerCode: Fail # Web compiler s JsInteropStaticInteropWithNonStaticSupertype/example: Fail # Web compiler specific JsInteropFunctionToJSRequiresStaticType/analyzerCode: 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/example: Fail # Web compiler specific LanguageVersionInvalidInDotPackages/analyzerCode: Fail diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index a9dba5f751c..461840723ac 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -5669,10 +5669,6 @@ 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." 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: problemMessage: "`@staticInterop` classes should not contain any generative constructors." correctionMessage: "Use factory constructors instead." @@ -5730,6 +5726,10 @@ JsInteropStaticInteropWithNonStaticSupertype: 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`." +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: problemMessage: "Library '#name' is forbidden when strict mode is enabled." correctionMessage: "Remove the import of a forbidden library." diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt index 72fbec33edf..e5c2edbce50 100644 --- a/pkg/front_end/test/spell_checking_list_messages.txt +++ b/pkg/front_end/test/spell_checking_list_messages.txt @@ -15,7 +15,6 @@ abispecificintegermapping adjusting annotate api -apis argument(s) assigning augment diff --git a/tests/lib/js/static_interop_test/external_extension_members_test.dart b/tests/lib/js/static_interop_test/external_extension_members_test.dart index fd17276735f..1f3b2fae994 100644 --- a/tests/lib/js/static_interop_test/external_extension_members_test.dart +++ b/tests/lib/js/static_interop_test/external_extension_members_test.dart @@ -12,15 +12,13 @@ import 'dart:js_interop'; import 'package:expect/expect.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; @JS() external void eval(String code); -@pkgJs.JS() -@pkgJs.staticInterop +@JS() +@staticInterop class Foo { external factory Foo(int a); } @@ -66,8 +64,8 @@ extension FooExt on Foo { external R combineNestedGeneric(R a, [R b]); } -@pkgJs.JS('module.Bar') -@pkgJs.staticInterop +@JS('module.Bar') +@staticInterop class Bar { external factory Bar(int a); } diff --git a/tests/lib/js/static_interop_test/external_member_type_parameters_static_test.dart b/tests/lib/js/static_interop_test/external_member_type_parameters_static_test.dart index 3116e417c6a..b989973100d 100644 --- a/tests/lib/js/static_interop_test/external_member_type_parameters_static_test.dart +++ b/tests/lib/js/static_interop_test/external_member_type_parameters_static_test.dart @@ -22,8 +22,6 @@ external T invalidTopLevel(T t); typedef Typedef = T Function(); -extension type JSList._(JSAny? _) {} - @JS() @staticInterop class Uninstantiated { @@ -70,11 +68,12 @@ extension UninstantiatedExtension external void consumeV(V v); // Test type parameters in a nested type context. - JSList> get getNestedTDart => throw UnimplementedError(); - // No error as JSList is an interop extension type. - external JSList> get getNestedT; - external JSList> get getNestedU; - external JSList> get getNestedV; + Set> get getNestedTDart => throw UnimplementedError(); + external Set> 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 Set> get getNestedU; + external Set> get getNestedV; // Test type parameters that are declared by the member. W returnWDart() => throw UnimplementedError(); @@ -127,11 +126,12 @@ extension type UninstantiatedExtensionType> get getNestedTDart => throw UnimplementedError(); - // No error as JSList is an interop extension type. - external JSList> get getNestedT; - external JSList> get getNestedU; - external JSList> get getNestedV; + Set> get getNestedTDart => throw UnimplementedError(); + external Set> 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 Set> get getNestedU; + external Set> get getNestedV; // Test type parameters that are declared by the member. W returnWDart() => throw UnimplementedError(); @@ -178,25 +178,25 @@ extension PkgJsExtension on PkgJs { @JS() @staticInterop class Instantiated { - external factory Instantiated(JSList list); + external factory Instantiated(List list); } extension InstantiatedExtension on Instantiated { - external JSList fieldList; - external JSList get getList; - external set setList(JSList list); - external JSList returnList(); - external void consumeList(JSList list); + external List fieldList; + external List get getList; + external set setList(List list); + external List returnList(); + external void consumeList(List list); } extension type InstantiatedExtensionType._(JSObject _) { // Test generic types where all the type parameters are instantiated. - external InstantiatedExtensionType(JSList list); - external JSList fieldList; - external JSList get getList; - external set setList(JSList list); - external JSList returnList(); - external void consumeList(JSList list); + external InstantiatedExtensionType(List list); + external List fieldList; + external List get getList; + external set setList(List list); + external List returnList(); + external void consumeList(List list); } void main() {} diff --git a/tests/lib/js/static_interop_test/external_static_member_lowerings_test.dart b/tests/lib/js/static_interop_test/external_static_member_lowerings_test.dart index 730d93ff714..0ed69eafbec 100644 --- a/tests/lib/js/static_interop_test/external_static_member_lowerings_test.dart +++ b/tests/lib/js/static_interop_test/external_static_member_lowerings_test.dart @@ -10,7 +10,7 @@ import 'dart:js_interop'; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); @JS() @staticInterop diff --git a/tests/lib/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart b/tests/lib/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart index aa973cef8a8..ec5b1481cb4 100644 --- a/tests/lib/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart +++ b/tests/lib/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart @@ -11,7 +11,7 @@ import 'package:expect/minitest.dart'; import 'package:js/js.dart' show trustTypes; @JS() -external void eval(String code); +external dynamic eval(String code); @JS('ExternalStatic') @staticInterop diff --git a/tests/lib/js/static_interop_test/inline_class/external_extension_member_test.dart b/tests/lib/js/static_interop_test/inline_class/external_extension_member_test.dart index 25ede604783..eb0ee58dd9b 100644 --- a/tests/lib/js/static_interop_test/inline_class/external_extension_member_test.dart +++ b/tests/lib/js/static_interop_test/inline_class/external_extension_member_test.dart @@ -12,7 +12,7 @@ import 'dart:js_interop'; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); extension type ExtensionType._(JSObject _) { external ExtensionType(); diff --git a/tests/lib/js/static_interop_test/inline_class/external_member_test.dart b/tests/lib/js/static_interop_test/inline_class/external_member_test.dart index 18ad3848183..5280621ab87 100644 --- a/tests/lib/js/static_interop_test/inline_class/external_member_test.dart +++ b/tests/lib/js/static_interop_test/inline_class/external_member_test.dart @@ -13,7 +13,7 @@ import 'package:expect/expect.dart'; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); extension type External._(JSObject _) { external External(); diff --git a/tests/lib/js/static_interop_test/inline_class/external_static_member_test.dart b/tests/lib/js/static_interop_test/inline_class/external_static_member_test.dart index 4c950ea1e8d..d598c4f42ff 100644 --- a/tests/lib/js/static_interop_test/inline_class/external_static_member_test.dart +++ b/tests/lib/js/static_interop_test/inline_class/external_static_member_test.dart @@ -13,7 +13,7 @@ import 'dart:js_util' as js_util; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); @JS() extension type ExternalStatic._(JSObject obj) { diff --git a/tests/lib/js/static_interop_test/inline_class/external_static_member_with_namespaces_test.dart b/tests/lib/js/static_interop_test/inline_class/external_static_member_with_namespaces_test.dart index 59c0d9da24a..e37379c707f 100644 --- a/tests/lib/js/static_interop_test/inline_class/external_static_member_with_namespaces_test.dart +++ b/tests/lib/js/static_interop_test/inline_class/external_static_member_with_namespaces_test.dart @@ -13,7 +13,7 @@ import 'dart:js_util' as js_util; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); @JS('library3.ExternalStatic') extension type ExternalStatic._(JSObject obj) { diff --git a/tests/lib/js/static_interop_test/js_array_test.dart b/tests/lib/js/static_interop_test/js_array_test.dart index f0eb8d9c962..f32ca42cb0c 100644 --- a/tests/lib/js/static_interop_test/js_array_test.dart +++ b/tests/lib/js/static_interop_test/js_array_test.dart @@ -10,7 +10,7 @@ library js_array_test; import 'dart:js_interop'; @JS() -external void eval(String code); +external dynamic eval(String code); // 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. diff --git a/tests/lib/js/static_interop_test/jsobject_type_test.dart b/tests/lib/js/static_interop_test/jsobject_type_test.dart index d5e2234e13a..60249eb4e5f 100644 --- a/tests/lib/js/static_interop_test/jsobject_type_test.dart +++ b/tests/lib/js/static_interop_test/jsobject_type_test.dart @@ -12,10 +12,10 @@ import 'dart:js_interop'; import 'package:expect/minitest.dart'; @JS() -external void eval(String code); +external dynamic eval(String code); @JS() -external JSAny get obj; +external Object get obj; void main() { eval(''' diff --git a/tests/lib/js/static_interop_test/native_error_test.dart b/tests/lib/js/static_interop_test/native_error_test.dart index 746424f5214..d903cda930b 100644 --- a/tests/lib/js/static_interop_test/native_error_test.dart +++ b/tests/lib/js/static_interop_test/native_error_test.dart @@ -10,7 +10,7 @@ library native_error_test; import 'dart:js_interop'; @JS() -external void eval(String code); +external dynamic eval(String code); // 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. diff --git a/tests/lib/js/static_interop_test/operator_static_test.dart b/tests/lib/js/static_interop_test/operator_static_test.dart index 0c1bb26fe40..78de569a53d 100644 --- a/tests/lib/js/static_interop_test/operator_static_test.dart +++ b/tests/lib/js/static_interop_test/operator_static_test.dart @@ -16,60 +16,60 @@ class StaticInterop {} extension _ on StaticInterop { // https://dart.dev/guides/language/language-tour#_operators for the list of // operators allowed by the language. - external void operator <(JSAny _); + external void operator <(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >(JSAny _); + external void operator >(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator <=(JSAny _); + external void operator <=(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >=(JSAny _); + external void operator >=(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator -(JSAny _); + external void operator -(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator +(JSAny _); + external void operator +(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator /(JSAny _); + external void operator /(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator ~/(JSAny _); + external void operator ~/(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator *(JSAny _); + external void operator *(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator %(JSAny _); + external void operator %(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator |(JSAny _); + external void operator |(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator ^(JSAny _); + external void operator ^(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator &(JSAny _); + external void operator &(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator <<(JSAny _); + external void operator <<(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >>(JSAny _); + external void operator >>(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >>>(JSAny _); + external void operator >>>(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. @JS('rename') - external void operator [](JSAny _); + external void operator [](_); // ^ // [web] JS interop operator methods cannot be renamed using the '@JS' annotation. @JS('rename') - external void operator []=(JSAny _, JSAny __); + external void operator []=(_, __); // ^ // [web] JS interop operator methods cannot be renamed using the '@JS' annotation. external void operator ~(); @@ -81,60 +81,60 @@ extension _ on StaticInterop { @JS() extension type ExtensionType(JSObject _) { - external void operator <(JSAny _); + external void operator <(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >(JSAny _); + external void operator >(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator <=(JSAny _); + external void operator <=(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >=(JSAny _); + external void operator >=(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator -(JSAny _); + external void operator -(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator +(JSAny _); + external void operator +(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator /(JSAny _); + external void operator /(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator ~/(JSAny _); + external void operator ~/(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator *(JSAny _); + external void operator *(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator %(JSAny _); + external void operator %(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator |(JSAny _); + external void operator |(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator ^(JSAny _); + external void operator ^(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator &(JSAny _); + external void operator &(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator <<(JSAny _); + external void operator <<(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >>(JSAny _); + external void operator >>(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. - external void operator >>>(JSAny _); + external void operator >>>(_); // ^ // [web] JS interop classes do not support operator methods, with the exception of '[]' and '[]=' using static interop. @JS('rename') - external void operator [](JSAny _); + external void operator [](_); // ^ // [web] JS interop operator methods cannot be renamed using the '@JS' annotation. @JS('rename') - external void operator []=(JSAny _, JSAny __); + external void operator []=(_, __); // ^ // [web] JS interop operator methods cannot be renamed using the '@JS' annotation. external void operator ~(); diff --git a/tests/lib/js/static_interop_test/strict_mode_test.dart b/tests/lib/js/static_interop_test/strict_mode_test.dart index e85820dcfcc..868b562415f 100644 --- a/tests/lib/js/static_interop_test/strict_mode_test.dart +++ b/tests/lib/js/static_interop_test/strict_mode_test.dart @@ -8,49 +8,74 @@ library strict_mode_test; import 'dart:js_interop'; -import 'dart:js'; -import 'dart:js_util'; +/**/ import 'dart:js'; +// ^ +// [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() @staticInterop class JSClass { external factory JSClass(List baz); // ^ - // [web] Type 'List' 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. + // [web] JS interop requires JS types when strict mode is enabled, but Type 'List' is not a type or subtype of a type from `dart:js_interop`. external factory JSClass.other(Object blu); // ^ - // [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. + // [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`. - external static dynamic foo(); - // ^ - // [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 Function get fooGet; - // ^ - // [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 set fooSet(void Function() bar); + external static int foo(); // ^ - // [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. + // [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`. + + external static JSClass foo1(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`. + + external static Function foo2(); + // ^ + // [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`. + + 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 { external dynamic extFoo(); // ^ - // [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. + // [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`. external JSClass extFoo2(List bar); // ^ - // [web] Type 'List' 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. + // [web] JS interop requires JS types when strict mode is enabled, but Type 'List' is not a type or subtype of a type from `dart:js_interop`. - external Function get extFooGet; - // ^ - // [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 Function extFoo3(JSClass 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`. - external set extFooSet(void Function() bar); + external JSClass extFoo4(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 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] 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. + // [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() @@ -67,16 +92,12 @@ external void useStaticInteropExtensionType(ExtensionType foo); void main() { 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(((List foo) => 4.0).toJS); - // ^ - // [web] Type 'List' 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. + // ^ + // [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) as dynamic) as Function).toJS); // ^ diff --git a/tests/lib/js/static_interop_test/top_level_member_annotation_static_test.dart b/tests/lib/js/static_interop_test/top_level_member_annotation_static_test.dart index f6a8e2037dc..198947143e1 100644 --- a/tests/lib/js/static_interop_test/top_level_member_annotation_static_test.dart +++ b/tests/lib/js/static_interop_test/top_level_member_annotation_static_test.dart @@ -22,7 +22,7 @@ external int get getter; // ^ // [web] Only JS interop members may be 'external'. -external set setter(int _); +external set setter(_); // ^ // [web] Only JS interop members may be 'external'. @@ -40,7 +40,7 @@ external int annotatedFinalField; external int get annotatedGetter; @JS() -external set annotatedSetter(int _); +external set annotatedSetter(_); @JS() external int annotatedMethod(); diff --git a/tests/lib/js/static_interop_test/typed_data_test.dart b/tests/lib/js/static_interop_test/typed_data_test.dart index 4d66062dfc1..3aca176d420 100644 --- a/tests/lib/js/static_interop_test/typed_data_test.dart +++ b/tests/lib/js/static_interop_test/typed_data_test.dart @@ -11,7 +11,7 @@ library typed_data_test; import 'dart:js_interop'; @JS() -external void eval(String code); +external dynamic eval(String code); // 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. diff --git a/tests/lib_2/js/static_interop_test/external_extension_members_test.dart b/tests/lib_2/js/static_interop_test/external_extension_members_test.dart index db80c3fb8bf..dd5ad9d1863 100644 --- a/tests/lib_2/js/static_interop_test/external_extension_members_test.dart +++ b/tests/lib_2/js/static_interop_test/external_extension_members_test.dart @@ -14,15 +14,13 @@ import 'dart:js_interop'; import 'package:expect/expect.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; @JS() external void eval(String code); -@pkgJs.JS() -@pkgJs.staticInterop +@JS() +@staticInterop class Foo { external factory Foo(int a); } @@ -68,8 +66,8 @@ extension FooExt on Foo { external R combineNestedGeneric(R a, [R b]); } -@pkgJs.JS('module.Bar') -@pkgJs.staticInterop +@JS('module.Bar') +@staticInterop class Bar { external factory Bar(int a); } diff --git a/tests/lib_2/js/static_interop_test/external_member_type_parameters_static_test.dart b/tests/lib_2/js/static_interop_test/external_member_type_parameters_static_test.dart index ec682eeb223..1cbac170dc6 100644 --- a/tests/lib_2/js/static_interop_test/external_member_type_parameters_static_test.dart +++ b/tests/lib_2/js/static_interop_test/external_member_type_parameters_static_test.dart @@ -20,10 +20,6 @@ external T invalidTopLevel(T t); typedef Typedef = T Function(); -@JS() -@staticInterop -class JSList {} - @JS() @staticInterop class Uninstantiated { @@ -70,11 +66,12 @@ extension UninstantiatedExtension external void consumeV(V v); // Test type parameters in a nested type context. - JSList> get getNestedTDart => throw UnimplementedError(); - // No error as JSList is an interop type. - external JSList> get getNestedT; - external JSList> get getNestedU; - external JSList> get getNestedV; + Set> get getNestedTDart => throw UnimplementedError(); + external Set> 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 Set> get getNestedU; + external Set> get getNestedV; // Test type parameters that are declared by the member. W returnWDart() => throw UnimplementedError(); @@ -112,15 +109,15 @@ extension PkgJsExtension on PkgJs { @JS() @staticInterop class Instantiated { - external factory Instantiated(JSList list); + external factory Instantiated(List list); } extension InstantiatedExtension on Instantiated { - external JSList fieldList; - external JSList get getList; - external set setList(JSList list); - external JSList returnList(); - external void consumeList(JSList list); + external List fieldList; + external List get getList; + external set setList(List list); + external List returnList(); + external void consumeList(List list); } void main() {} diff --git a/tests/lib_2/js/static_interop_test/external_static_member_lowerings_test.dart b/tests/lib_2/js/static_interop_test/external_static_member_lowerings_test.dart index 0773976ee46..837425f7bac 100644 --- a/tests/lib_2/js/static_interop_test/external_static_member_lowerings_test.dart +++ b/tests/lib_2/js/static_interop_test/external_static_member_lowerings_test.dart @@ -11,7 +11,7 @@ import 'package:expect/minitest.dart'; import 'package:js/js.dart' show staticInterop; @JS() -external void eval(String code); +external dynamic eval(String code); @JS() @staticInterop diff --git a/tests/lib_2/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart b/tests/lib_2/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart index b81efb0f43b..4bac12bc4f8 100644 --- a/tests/lib_2/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart +++ b/tests/lib_2/js/static_interop_test/external_static_member_lowerings_trusttypes_test.dart @@ -11,7 +11,7 @@ import 'package:expect/minitest.dart'; import 'package:js/js.dart' show trustTypes, staticInterop; @JS() -external void eval(String code); +external dynamic eval(String code); @JS('ExternalStatic') @staticInterop