[pkg:js] Refactor createStaticInteropMock tests to account for new changes

Change-Id: I4de0c94bf1f00336432d61b174703fde9476545a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262863
Reviewed-by: Riley Porter <rileyporter@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam 2022-10-24 17:37:09 +00:00 committed by Commit Queue
parent 8c62ad7596
commit dbb793a330
16 changed files with 538 additions and 818 deletions

View file

@ -3,176 +3,102 @@
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks for extension member conflicts.
// We should only require users to implement one of these conflicts (or a
// getter/setter pair).
import 'package:js/js.dart';
import 'package:js/js_util.dart';
class EmptyDart {}
@JS()
@staticInterop
class Method {}
class SameKindConflict {}
extension on Method {
external void member();
extension E1 on SameKindConflict {
external int get getter;
external set setter(int val);
external int method();
}
@JS()
@staticInterop
class Getter {}
extension NamedExtension on Getter {
external int get member;
extension E2 on SameKindConflict {
external String get getter;
external set setter(int val);
external String method();
}
@JS()
@staticInterop
class Field {}
extension on Field {
external final String member;
@JSExport()
class DartSameKindConflict {
String getter = '';
set setter(int val) => throw '';
String method() => throw '';
}
@JS()
@staticInterop
class ExtendsImplementsConflict extends Method implements Getter {}
@JS()
@staticInterop
class ImplementsConflict implements Method, Getter {}
@JS()
@staticInterop
class ManyConflicts extends Method implements Getter, Field {}
@JS()
@staticInterop
class Override implements Method {}
extension on Override {
external int member();
@JSExport()
class IncorrectDartSameKindConflict {
bool getter = true;
set setter(bool val) => throw '';
bool method() => throw '';
}
@JS()
@staticInterop
class OverrideOneConflictButNotAll implements Override, Getter {}
@JS()
@staticInterop
class ConflictThroughInheritance implements OverrideOneConflictButNotAll {}
@JS()
@staticInterop
class ResolveThroughOverride implements ConflictThroughInheritance {}
extension on ResolveThroughOverride {
external int member;
}
class ResolveThroughOverrideDart {
int member = throw '';
}
@JS()
@staticInterop
class Setter {}
extension on Setter {
external set member(int val);
}
@JS()
@staticInterop
class NoConflictDueToSubtype implements Override, Method {}
class NoConflictDueToSubtypeDart {
int member() => throw '';
}
@JS()
@staticInterop
class GetterSetterConflict implements Setter, Getter {}
@JS()
@staticInterop
class GetterSetterSameExtension {}
extension on GetterSetterSameExtension {
external int get member;
external set member(int val);
}
class GetterSetterSameExtensionDart extends ResolveThroughOverrideDart {}
@JS()
@staticInterop
class GetterSetterMethodConflict implements GetterSetterSameExtension, Method {}
@JS()
@staticInterop
class NonExternal {}
extension on NonExternal {
int get member => throw '';
}
@JS()
@staticInterop
class ExternalNonExternal implements NonExternal, GetterSetterSameExtension {}
class ExternalNonExternalDart extends ResolveThroughOverrideDart {}
void main() {
// Test name conflicts between extended and implemented members.
createStaticInteropMock<ExtendsImplementsConflict, EmptyDart>(
void testSameKindConflict() {
// No error as one of the extension members are implemented for each export
// name.
createStaticInteropMock<SameKindConflict, DartSameKindConflict>(
DartSameKindConflict());
// Error as none of them are implemented for each export name.
createStaticInteropMock<SameKindConflict, IncorrectDartSameKindConflict>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Method.unnamed'.
EmptyDart());
// Test name conflicts between implemented members.
createStaticInteropMock<ImplementsConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Method.unnamed'.
// Test multiple name conflicts.
createStaticInteropMock<ManyConflicts, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Field.unnamed', 'Getter.NamedExtension', 'Method.unnamed'.
// Test name conflicts where one definition is overridden, but there is still
// a name conflict between the other two.
createStaticInteropMock<OverrideOneConflictButNotAll, EmptyDart>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Override.unnamed'.
EmptyDart());
// Test case where if we inherit a class with a conflict, the conflict still
// exists.
createStaticInteropMock<ConflictThroughInheritance, EmptyDart>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Override.unnamed'.
EmptyDart());
// Test case where name conflicts are resolved using derived class.
createStaticInteropMock<ResolveThroughOverride, ResolveThroughOverrideDart>(
ResolveThroughOverrideDart());
// Test case where you inherit two classes with the same member name but they
// have a subtype relation, so there is no conflict.
createStaticInteropMock<NoConflictDueToSubtype, NoConflictDueToSubtypeDart>(
NoConflictDueToSubtypeDart());
// Test conflict where getter and setter collide when they are in different
// extensions.
createStaticInteropMock<GetterSetterConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Setter.unnamed'.
// Test no conflict where getter and setter are on the same extension.
createStaticInteropMock<GetterSetterSameExtension,
GetterSetterSameExtensionDart>(GetterSetterSameExtensionDart());
// Test conflict where getter and setter are in one extension, but there is
// a conflict with another extension.
createStaticInteropMock<GetterSetterMethodConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'GetterSetterSameExtension.unnamed', 'Method.unnamed'.
// Test no conflict between external and non-external members.
createStaticInteropMock<ExternalNonExternal, ExternalNonExternalDart>(
ExternalNonExternalDart());
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'getter': E1.getter (FunctionType(int Function())), E2.getter (FunctionType(String Function())).
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'method': E1.method (FunctionType(int Function())), E2.method (FunctionType(String Function())).
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'setter': E1.setter= (FunctionType(void Function(int))), E2.setter= (FunctionType(void Function(int))).
IncorrectDartSameKindConflict());
}
@JS()
@staticInterop
class DifferentKindConflict {}
extension E3 on DifferentKindConflict {
external int getSet;
@JS('getSet')
external void method();
}
@JSExport()
class ImplementGetter {
int get getSet => throw '';
}
@JSExport()
class ImplementSetter {
set getSet(int val) => throw '';
}
@JSExport()
class ImplementBoth {
int getSet = 0;
}
@JSExport()
class ImplementMethod {
void getSet() {}
}
void testDifferentKindConflict() {
// Missing setter error.
createStaticInteropMock<DifferentKindConflict, ImplementGetter>(
//^
// [web] Dart class 'ImplementGetter' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet': E3.getSet= (FunctionType(void Function(int))).
ImplementGetter());
// Missing getter error.
createStaticInteropMock<DifferentKindConflict, ImplementSetter>(
//^
// [web] Dart class 'ImplementSetter' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'getSet': E3.getSet (FunctionType(int Function())).
ImplementSetter());
// No error as both getter and setter are there, and we've satisfied an export
// for `getSet`.
createStaticInteropMock<DifferentKindConflict, ImplementBoth>(
ImplementBoth());
// No error as we've satisfied an export for `getSet`.
createStaticInteropMock<DifferentKindConflict, ImplementMethod>(
ImplementMethod());
}

View file

@ -23,10 +23,11 @@ extension on Methods {
external int optionalAdd(int a, int b, [int c = 0, int? d]);
}
@JSExport()
class MethodsDart {
int add(int a, int b) => a + b;
int nonExternal() => 1;
int rename() => 1;
int _rename() => 1;
int optionalAdd(int a, int b, [int? c, int? d]) =>
a + b + (c ?? 0) + (d ?? 0);
}
@ -44,11 +45,12 @@ extension on Fields {
external final int renamedFinalField;
}
@JSExport()
class FieldsDart {
int field = 1;
int finalField = 1;
int renamedField = 1;
final int renamedFinalField = 1;
int _renamedField = 1;
final int _renamedFinalField = 1;
}
@JS()
@ -72,12 +74,13 @@ extension on GetSet {
external set differentNameSameRenameSet(int val);
}
@JSExport()
class GetSetDart {
int getSet = 1;
int renamedGetSet = 1;
int sameNameDifferentRename = 1;
int differentNameSameRenameGet = 1;
int differentNameSameRenameSet = 1;
int _renamedGetSet = 1;
int _sameNameDifferentRenameGet = 1;
int _sameNameDifferentRenameSet = 1;
int _differentNameSameRename = 1;
}
void test([Object? proto]) {
@ -99,11 +102,11 @@ void test([Object? proto]) {
jsFields.field = 2;
jsFields.renamedField = 2;
expect(dartFields.field, 2);
expect(dartFields.renamedField, 2);
expect(dartFields._renamedField, 2);
// Modify the Dart mock and check for updates in the JS mock.
dartFields.field = 3;
dartFields.finalField = 3;
dartFields.renamedField = 3;
dartFields._renamedField = 3;
expect(jsFields.field, 3);
expect(jsFields.finalField, 3);
expect(jsFields.renamedField, 3);
@ -119,17 +122,17 @@ void test([Object? proto]) {
jsGetSet.sameNameDifferentRename = 2;
jsGetSet.differentNameSameRenameSet = 2;
expect(dartGetSet.getSet, 2);
expect(dartGetSet.renamedGetSet, 2);
expect(dartGetSet.sameNameDifferentRename, 2);
expect(dartGetSet.differentNameSameRenameGet, 1);
expect(dartGetSet.differentNameSameRenameSet, 2);
expect(dartGetSet._renamedGetSet, 2);
expect(dartGetSet._sameNameDifferentRenameGet, 1);
expect(dartGetSet._sameNameDifferentRenameSet, 2);
expect(dartGetSet._differentNameSameRename, 2);
// Modify the Dart mock and check for updates in the JS mock.
dartGetSet.getSet = 3;
dartGetSet.renamedGetSet = 3;
dartGetSet.sameNameDifferentRename = 3;
dartGetSet._renamedGetSet = 3;
// Use different values to disambiguate.
dartGetSet.differentNameSameRenameGet = 3;
dartGetSet.differentNameSameRenameSet = 4;
dartGetSet._sameNameDifferentRenameGet = 3;
dartGetSet._sameNameDifferentRenameSet = 4;
dartGetSet._differentNameSameRename = 3;
expect(jsGetSet.getSet, 3);
expect(jsGetSet.renamedGetSet, 3);
expect(jsGetSet.sameNameDifferentRename, 3);

View file

@ -24,26 +24,29 @@ class StaticInterop {
external factory StaticInterop();
}
class Dart {}
@JSExport()
class Dart {
int _unused = 0;
}
void main() {
createStaticInteropMock<StaticInterop, Dart>(Dart());
createStaticInteropMock<Dart, StaticInterop>(StaticInterop());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'StaticInterop' is not a Dart interface type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
// [web] Type argument 'StaticInterop' needs to be a non-JS interop type.
createStaticInteropMock<Dart, Js>(Js());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'Js' is not a Dart interface type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
// [web] Type argument 'Js' needs to be a non-JS interop type.
createStaticInteropMock<Dart, Anonymous>(Anonymous());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'Anonymous' is not a Dart interface type.
// [web] Type argument 'Anonymous' needs to be a non-JS interop type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
createStaticInteropMock<StaticInterop, void Function()>(() {});
//^
// [web] Second type argument 'void Function()' is not a Dart interface type.
// [web] Type argument 'void Function()' needs to be an interface type.
createStaticInteropMock(Dart());
//^
// [web] First type argument 'dynamic' is not a `@staticInterop` type.
// [web] Type argument 'Object' needs to be a `@staticInterop` type.
}

View file

@ -2,9 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Basic inheritance test where @staticInterop class inherits extension methods
// which are then defined in the Dart class' inheritance chain, with some
// overrides.
// Test that @staticInterop extension methods are collected from all extensions,
// including inheritance.
import 'package:expect/minitest.dart';
import 'package:js/js.dart';
@ -18,8 +17,8 @@ extension on Extends {
external int extendsMethod(int val);
external int extendsField;
external final int extendsFinalField;
external int get getSet;
external set getSet(int val);
external int get extendsGetSet;
external set extendsGetSet(int val);
}
@JS()
@ -27,15 +26,12 @@ extension on Extends {
class Implements {}
extension on Implements {
@JS('_implementsMethod')
external int implementsMethod(int val);
@JS('_implementsField')
external int implementsField;
@JS('_implementsFinalField')
external final int implementsFinalField;
@JS('_implementsGetter')
@JS('implementsGetSet')
external int get implementsGetter;
@JS('_implementsSetter')
@JS('implementsGetSet')
external set implementsSetter(int val);
}
@ -47,43 +43,59 @@ extension on Inheritance {
external int method(int val);
external int field;
external final int finalField;
// Overrides
external int get getSet;
external set getSet(int val);
}
extension on Inheritance {
external int method2(int val);
external int field2;
external final int finalField2;
external int get getSet2;
external set getSet2(int val);
}
@JSExport()
class ExtendsDart {
int extendsMethod(int val) => val;
int extendsField = 0;
final int extendsFinalField = 0;
int getSet = 0;
int extendsGetSet = 0;
}
@JSExport()
class ImplementsMixin {
int implementsMethod(int val) => val;
int implementsField = 1;
final int implementsFinalField = 1;
int _implementsGetSet = 1;
int get implementsGetter => _implementsGetSet;
set implementsSetter(int val) => _implementsGetSet = val;
int implementsGetSet = 1;
}
@JSExport()
class InheritanceDart extends ExtendsDart with ImplementsMixin {
int method(int val) => val;
int field = 2;
final int finalField = 2;
@override
int getSet = 2;
int method2(int val) => val;
int field2 = 2;
final int finalField2 = 2;
int getSet2 = 2;
}
void main() {
var dartMock = InheritanceDart();
var jsMock = createStaticInteropMock<Inheritance, InheritanceDart>(dartMock);
expect(jsMock.extendsMethod(0), 0);
expect(jsMock.extendsField, 0);
jsMock.extendsField = 1;
expect(jsMock.extendsField, 1);
expect(jsMock.extendsFinalField, 0);
expect(jsMock.extendsGetSet, 0);
// Dart mock uses a field for this getter and setter, so it should change.
jsMock.extendsGetSet = 1;
expect(jsMock.extendsGetSet, 1);
expect(jsMock.implementsMethod(1), 1);
expect(jsMock.implementsField, 1);
@ -92,7 +104,6 @@ void main() {
expect(jsMock.implementsFinalField, 1);
expect(jsMock.implementsGetter, 1);
jsMock.implementsSetter = 2;
// Dart mock uses a field for this getter and setter, so it should change.
expect(jsMock.implementsGetter, 2);
expect(jsMock.method(2), 2);
@ -103,4 +114,13 @@ void main() {
expect(jsMock.getSet, 2);
jsMock.getSet = 3;
expect(jsMock.getSet, 3);
expect(jsMock.method2(2), 2);
expect(jsMock.field2, 2);
jsMock.field2 = 3;
expect(jsMock.field2, 3);
expect(jsMock.finalField2, 2);
expect(jsMock.getSet2, 2);
jsMock.getSet2 = 3;
expect(jsMock.getSet2, 3);
}

View file

@ -1,183 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks that there aren't any missing
// overrides.
import 'package:js/js.dart';
import 'package:js/js_util.dart';
@JS()
@staticInterop
class StaticInterop {}
extension on StaticInterop {
external int field;
external final int finalField;
external int get getSet;
external set getSet(int val);
external void method();
// We should ignore the non-external members for determining overrides.
int get nonExternalGetSet => throw '';
set nonExternalGetSet(int val) => throw '';
void nonExternalMethod() => throw '';
}
class CorrectDart {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartStatic {
static int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartUsingExtensions {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
}
extension on DartUsingExtensions {
void method() => throw '';
}
class DartFactory {
DartFactory();
factory DartFactory.finalField() => DartFactory();
int field = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartFinal {
final int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartNoGet {
int field = throw '';
final int finalField = throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartNoSet {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
void method() => throw '';
}
class DartNoMembers {}
void main() {
createStaticInteropMock<StaticInterop, CorrectDart>(CorrectDart());
// Static members do not qualify as an override.
createStaticInteropMock<StaticInterop, DartStatic>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field', but Dart class 'DartStatic' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartStatic' does not have an overriding instance member.
DartStatic());
// Extension members do not qualify as an override.
createStaticInteropMock<StaticInterop, DartUsingExtensions>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'method', but Dart class 'DartUsingExtensions' does not have an overriding instance member.
DartUsingExtensions());
// Factory members with the same name do not qualify as an override.
createStaticInteropMock<StaticInterop, DartFactory>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'finalField', but Dart class 'DartFactory' does not have an overriding instance member.
DartFactory());
// Final fields can not override a setter.
createStaticInteropMock<StaticInterop, DartFinal>(DartFinal());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartFinal' does not have an overriding instance member.
createStaticInteropMock<StaticInterop, DartNoGet>(DartNoGet());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet', but Dart class 'DartNoGet' does not have an overriding instance member.
// Test that getters are treated differently from setters even though they
// share the same name.
createStaticInteropMock<StaticInterop, DartNoSet>(DartNoSet());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet=', but Dart class 'DartNoSet' does not have an overriding instance member.
// Test multiple missing members.
createStaticInteropMock<StaticInterop, DartNoMembers>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'finalField', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet=', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'method', but Dart class 'DartNoMembers' does not have an overriding instance member.
DartNoMembers());
testUsingInheritanceAndMixins();
}
// The following should classes should not contain any override errors, as they
// have all the necessary members.
class DartWithInheritance extends DartNoSet {
set getSet(int val) => throw '';
}
class DartWithMixins with CorrectDart {}
mixin MixinSet {
set getSet(int val) => throw '';
}
class DartWithMixinsAndInheritance extends DartNoSet with MixinSet {}
@JS()
@staticInterop
class BaseStaticInterop {}
extension on BaseStaticInterop {
external void baseMethod();
}
@JS()
@staticInterop
class StaticInteropWithInheritance extends BaseStaticInterop
implements StaticInterop {}
class DartImplementingInteropInheritance extends DartWithMixinsAndInheritance {
void baseMethod() => throw '';
}
void testUsingInheritanceAndMixins() {
// Test where Dart class implements using inherited members.
createStaticInteropMock<StaticInterop, DartWithInheritance>(
DartWithInheritance());
// Test where Dart class implements using mixed-in members.
createStaticInteropMock<StaticInterop, DartWithMixins>(DartWithMixins());
// Test where Dart class implements using inherited and mixed-in members.
createStaticInteropMock<StaticInterop, DartWithMixinsAndInheritance>(
DartWithMixinsAndInheritance());
// Missing inherited method, expect an error.
createStaticInteropMock<
//^
// [web] `@staticInterop` class 'StaticInteropWithInheritance' has external extension member 'baseMethod', but Dart class 'DartWithMixinsAndInheritance' does not have an overriding instance member.
StaticInteropWithInheritance,
DartWithMixinsAndInheritance>(DartWithMixinsAndInheritance());
// Added missing method, should pass.
createStaticInteropMock<StaticInteropWithInheritance,
DartImplementingInteropInheritance>(DartImplementingInteropInheritance());
}

View file

@ -24,6 +24,7 @@ extension on StaticInterop {
external set getSet(int? val);
}
@JSExport()
class Dart {
int? method(int? val) => throw '';
int? field = throw '';
@ -34,6 +35,7 @@ class Dart {
// Have the mock class implement the class interface you defined to mock the
// @staticInterop interface.
@JSExport()
class DartMock extends Mock implements Dart {}
void main() {

View file

@ -26,7 +26,10 @@ external Object get windowType;
@staticInterop
class JSWindow {}
class DartWindow {}
@JSExport()
class DartWindow {
int _unused = 0;
}
void main() {
// Test that everything still works the same.

View file

@ -2,11 +2,67 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks that overrides are subtypes.
// Test that `createStaticInteropMock` checks that overrides exist and are
// subtypes.
import 'package:js/js.dart';
import 'package:js/js_util.dart';
@JS()
@staticInterop
class StaticInterop {}
extension on StaticInterop {
external int field;
external final int finalField;
external int get getSet1;
external set getSet1(int val);
external int get getSet2;
external set getSet2(int val);
external void method();
}
@JSExport()
class CorrectDart {
int field = throw '';
final int finalField = throw '';
int get getSet1 => throw '';
set getSet1(int val) => throw '';
int get getSet2 => throw '';
set getSet2(int val) => throw '';
void method() => throw '';
}
@JSExport()
class IncorrectDart {
IncorrectDart();
// Factories do not count.
factory IncorrectDart.method() => IncorrectDart();
// Setter is not implemented.
final int field = throw '';
// Static members do not count.
static final int finalField = throw '';
// Getter is not implemented.
set getSet1(int val) => throw '';
int get getSet2 => throw '';
}
extension on IncorrectDart {
// Extension members do not count.
set getSet2(int val) => throw '';
}
void testMissingOverrides() {
createStaticInteropMock<StaticInterop, CorrectDart>(CorrectDart());
createStaticInteropMock<StaticInterop, IncorrectDart>(IncorrectDart());
//^
// [web] Dart class 'IncorrectDart' does not have any members that implement any of the following extension member(s) with export name 'finalField': <unnamed>.finalField (FunctionType(int Function())).
// [web] Dart class 'IncorrectDart' does not have any members that implement any of the following extension member(s) with export name 'method': <unnamed>.method (FunctionType(void Function())).
// [web] Dart class 'IncorrectDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'field': <unnamed>.field= (FunctionType(void Function(int))).
// [web] Dart class 'IncorrectDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet2': <unnamed>.getSet2= (FunctionType(void Function(int))).
// [web] Dart class 'IncorrectDart' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'getSet1': <unnamed>.getSet1 (FunctionType(int Function())).
}
// Set up a simple type hierarchy.
class A {
const A();
@ -27,38 +83,61 @@ class SimpleInterop {}
extension SimpleInteropExtension on SimpleInterop {
external B field;
external final B finalField;
external B get getSetNum;
external set getSetInt(B val);
external B get getSet;
external set getSet(B val);
external B method(B b);
}
// Implement using the exact same types.
@JSExport()
class SimpleDart {
B field = throw '';
final B finalField = throw '';
B get getSetNum => throw '';
set getSetInt(B val) => throw '';
B get getSet => throw '';
set getSet(B val) => throw '';
B method(B b) => throw '';
}
void testExactTypes() {
createStaticInteropMock<SimpleInterop, SimpleDart>(SimpleDart());
}
// Implement using subtypes.
@JSExport()
class SubtypeSimpleDart {
B field = throw '';
final C finalField = throw '';
C get getSetNum => throw '';
set getSetInt(A val) => throw '';
C get getSet => throw '';
set getSet(A val) => throw '';
C method(A a) => throw '';
}
void testSimpleSubtyping() {
createStaticInteropMock<SimpleInterop, SubtypeSimpleDart>(
SubtypeSimpleDart());
}
// Implement using supertypes (which shouldn't work).
@JSExport()
class SupertypeSimpleDart {
A field = throw '';
final A finalField = throw '';
A get getSetNum => throw '';
set getSetInt(C val) => throw '';
// Getter must be subtype of setter, so only the setter should be an error.
C get getSet => throw '';
set getSet(C val) => throw '';
A method(C c) => throw '';
}
void testIncorrectSimpleSubtyping() {
createStaticInteropMock<SimpleInterop, SupertypeSimpleDart>(
//^
// [web] Dart class 'SupertypeSimpleDart' does not have any members that implement any of the following extension member(s) with export name 'finalField': SimpleInteropExtension.finalField (FunctionType(B Function())).
// [web] Dart class 'SupertypeSimpleDart' does not have any members that implement any of the following extension member(s) with export name 'method': SimpleInteropExtension.method (FunctionType(B Function(B))).
// [web] Dart class 'SupertypeSimpleDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet': SimpleInteropExtension.getSet= (FunctionType(void Function(B))).
// [web] Dart class 'SupertypeSimpleDart' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'field': SimpleInteropExtension.field (FunctionType(B Function())).
SupertypeSimpleDart());
}
@JS()
@staticInterop
class ComplexAndOptionalInteropMethods {}
@ -70,12 +149,19 @@ extension ComplexAndOptionalInteropMethodsExtension
external B optionalSubtype(B b, [B b2 = const B()]);
}
@JSExport()
class ComplexAndOptionalDart {
C Function(A _) nestedTypes(List<B> arg1, Map<Set<B>, B> arg2) => throw '';
B optional(B b, [B? b2]) => throw '';
C optionalSubtype(A a, [A? a2]) => throw '';
}
void testComplexSubtyping() {
createStaticInteropMock<ComplexAndOptionalInteropMethods,
ComplexAndOptionalDart>(ComplexAndOptionalDart());
}
@JSExport()
class IncorrectComplexAndOptionalDart {
// List type is wrong.
B Function(B _) nestedTypes(List<List<B>> arg1, Map<Set<B>, B> arg2) =>
@ -86,25 +172,25 @@ class IncorrectComplexAndOptionalDart {
B optionalSubtype(B b, [C c = const C()]) => throw '';
}
void main() {
createStaticInteropMock<SimpleInterop, SimpleDart>(SimpleDart());
createStaticInteropMock<SimpleInterop, SubtypeSimpleDart>(
SubtypeSimpleDart());
createStaticInteropMock<SimpleInterop, SupertypeSimpleDart>(
//^
// [web] Dart class member 'SupertypeSimpleDart.field' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.field' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.finalField' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.finalField' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.getSetInt=' with type 'void Function(C)' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.getSetInt=' with type 'void Function(B)'.
// [web] Dart class member 'SupertypeSimpleDart.getSetNum' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.getSetNum' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.method' with type 'A Function(C)' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.method' with type 'B Function(B)'.
SupertypeSimpleDart());
createStaticInteropMock<ComplexAndOptionalInteropMethods,
ComplexAndOptionalDart>(ComplexAndOptionalDart());
void testIncorrectComplexSubtyping() {
createStaticInteropMock<
//^
// [web] Dart class member 'IncorrectComplexAndOptionalDart.nestedTypes' with type 'B Function(B) Function(List<List<B>>, Map<Set<B>, B>)' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.nestedTypes' with type 'B Function(B) Function(List<B>, Map<Set<B>, B>)'.
// [web] Dart class member 'IncorrectComplexAndOptionalDart.optional' with type 'B Function(B, B?)' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.optional' with type 'B Function(B, [B?])'.
// [web] Dart class member 'IncorrectComplexAndOptionalDart.optionalSubtype' with type 'B Function(B, [C])' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.optionalSubtype' with type 'B Function(B, [B])'.
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'nestedTypes': ComplexAndOptionalInteropMethodsExtension.nestedTypes (FunctionType(B Function(B) Function(List<B>, Map<Set<B>, B>))).
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'optional': ComplexAndOptionalInteropMethodsExtension.optional (FunctionType(B Function(B, [B?]))).
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'optionalSubtype': ComplexAndOptionalInteropMethodsExtension.optionalSubtype (FunctionType(B Function(B, [B]))).
ComplexAndOptionalInteropMethods,
IncorrectComplexAndOptionalDart>(IncorrectComplexAndOptionalDart());
}
void testSubtyping() {
testExactTypes();
testSimpleSubtyping();
testIncorrectSimpleSubtyping();
testComplexSubtyping();
testIncorrectComplexSubtyping();
}
void main() {
testMissingOverrides();
testSubtyping();
}

View file

@ -3,176 +3,102 @@
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks for extension member conflicts.
// We should only require users to implement one of these conflicts (or a
// getter/setter pair).
import 'package:js/js.dart';
import 'package:js/js_util.dart';
class EmptyDart {}
@JS()
@staticInterop
class Method {}
class SameKindConflict {}
extension on Method {
external void member();
extension E1 on SameKindConflict {
external int get getter;
external set setter(int val);
external int method();
}
@JS()
@staticInterop
class Getter {}
extension NamedExtension on Getter {
external int get member;
extension E2 on SameKindConflict {
external String get getter;
external set setter(int val);
external String method();
}
@JS()
@staticInterop
class Field {}
extension on Field {
external final String member;
@JSExport()
class DartSameKindConflict {
String getter = '';
set setter(int val) => throw '';
String method() => throw '';
}
@JS()
@staticInterop
class ExtendsImplementsConflict extends Method implements Getter {}
@JS()
@staticInterop
class ImplementsConflict implements Method, Getter {}
@JS()
@staticInterop
class ManyConflicts extends Method implements Getter, Field {}
@JS()
@staticInterop
class Override implements Method {}
extension on Override {
external int member();
@JSExport()
class IncorrectDartSameKindConflict {
bool getter = true;
set setter(bool val) => throw '';
bool method() => throw '';
}
@JS()
@staticInterop
class OverrideOneConflictButNotAll implements Override, Getter {}
@JS()
@staticInterop
class ConflictThroughInheritance implements OverrideOneConflictButNotAll {}
@JS()
@staticInterop
class ResolveThroughOverride implements ConflictThroughInheritance {}
extension on ResolveThroughOverride {
external int member;
}
class ResolveThroughOverrideDart {
int member = throw '';
}
@JS()
@staticInterop
class Setter {}
extension on Setter {
external set member(int val);
}
@JS()
@staticInterop
class NoConflictDueToSubtype implements Override, Method {}
class NoConflictDueToSubtypeDart {
int member() => throw '';
}
@JS()
@staticInterop
class GetterSetterConflict implements Setter, Getter {}
@JS()
@staticInterop
class GetterSetterSameExtension {}
extension on GetterSetterSameExtension {
external int get member;
external set member(int val);
}
class GetterSetterSameExtensionDart extends ResolveThroughOverrideDart {}
@JS()
@staticInterop
class GetterSetterMethodConflict implements GetterSetterSameExtension, Method {}
@JS()
@staticInterop
class NonExternal {}
extension on NonExternal {
int get member => throw '';
}
@JS()
@staticInterop
class ExternalNonExternal implements NonExternal, GetterSetterSameExtension {}
class ExternalNonExternalDart extends ResolveThroughOverrideDart {}
void main() {
// Test name conflicts between extended and implemented members.
createStaticInteropMock<ExtendsImplementsConflict, EmptyDart>(
void testSameKindConflict() {
// No error as one of the extension members are implemented for each export
// name.
createStaticInteropMock<SameKindConflict, DartSameKindConflict>(
DartSameKindConflict());
// Error as none of them are implemented for each export name.
createStaticInteropMock<SameKindConflict, IncorrectDartSameKindConflict>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Method.unnamed'.
EmptyDart());
// Test name conflicts between implemented members.
createStaticInteropMock<ImplementsConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Method.unnamed'.
// Test multiple name conflicts.
createStaticInteropMock<ManyConflicts, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Field.unnamed', 'Getter.NamedExtension', 'Method.unnamed'.
// Test name conflicts where one definition is overridden, but there is still
// a name conflict between the other two.
createStaticInteropMock<OverrideOneConflictButNotAll, EmptyDart>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Override.unnamed'.
EmptyDart());
// Test case where if we inherit a class with a conflict, the conflict still
// exists.
createStaticInteropMock<ConflictThroughInheritance, EmptyDart>(
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Override.unnamed'.
EmptyDart());
// Test case where name conflicts are resolved using derived class.
createStaticInteropMock<ResolveThroughOverride, ResolveThroughOverrideDart>(
ResolveThroughOverrideDart());
// Test case where you inherit two classes with the same member name but they
// have a subtype relation, so there is no conflict.
createStaticInteropMock<NoConflictDueToSubtype, NoConflictDueToSubtypeDart>(
NoConflictDueToSubtypeDart());
// Test conflict where getter and setter collide when they are in different
// extensions.
createStaticInteropMock<GetterSetterConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'Getter.NamedExtension', 'Setter.unnamed'.
// Test no conflict where getter and setter are on the same extension.
createStaticInteropMock<GetterSetterSameExtension,
GetterSetterSameExtensionDart>(GetterSetterSameExtensionDart());
// Test conflict where getter and setter are in one extension, but there is
// a conflict with another extension.
createStaticInteropMock<GetterSetterMethodConflict, EmptyDart>(EmptyDart());
//^
// [web] External extension member with name 'member' is defined in the following extensions and none are more specific: 'GetterSetterSameExtension.unnamed', 'Method.unnamed'.
// Test no conflict between external and non-external members.
createStaticInteropMock<ExternalNonExternal, ExternalNonExternalDart>(
ExternalNonExternalDart());
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'getter': E1.getter (FunctionType(int Function())), E2.getter (FunctionType(String Function())).
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'method': E1.method (FunctionType(int Function())), E2.method (FunctionType(String Function())).
// [web] Dart class 'IncorrectDartSameKindConflict' does not have any members that implement any of the following extension member(s) with export name 'setter': E1.setter= (FunctionType(void Function(int))), E2.setter= (FunctionType(void Function(int))).
IncorrectDartSameKindConflict());
}
@JS()
@staticInterop
class DifferentKindConflict {}
extension E3 on DifferentKindConflict {
external int getSet;
@JS('getSet')
external void method();
}
@JSExport()
class ImplementGetter {
int get getSet => throw '';
}
@JSExport()
class ImplementSetter {
set getSet(int val) => throw '';
}
@JSExport()
class ImplementBoth {
int getSet = 0;
}
@JSExport()
class ImplementMethod {
void getSet() {}
}
void testDifferentKindConflict() {
// Missing setter error.
createStaticInteropMock<DifferentKindConflict, ImplementGetter>(
//^
// [web] Dart class 'ImplementGetter' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet': E3.getSet= (FunctionType(void Function(int))).
ImplementGetter());
// Missing getter error.
createStaticInteropMock<DifferentKindConflict, ImplementSetter>(
//^
// [web] Dart class 'ImplementSetter' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'getSet': E3.getSet (FunctionType(int Function())).
ImplementSetter());
// No error as both getter and setter are there, and we've satisfied an export
// for `getSet`.
createStaticInteropMock<DifferentKindConflict, ImplementBoth>(
ImplementBoth());
// No error as we've satisfied an export for `getSet`.
createStaticInteropMock<DifferentKindConflict, ImplementMethod>(
ImplementMethod());
}

View file

@ -23,10 +23,11 @@ extension on Methods {
external int optionalAdd(int a, int b, [int c = 0, int? d]);
}
@JSExport()
class MethodsDart {
int add(int a, int b) => a + b;
int nonExternal() => 1;
int rename() => 1;
int _rename() => 1;
int optionalAdd(int a, int b, [int? c, int? d]) =>
a + b + (c ?? 0) + (d ?? 0);
}
@ -44,11 +45,12 @@ extension on Fields {
external final int renamedFinalField;
}
@JSExport()
class FieldsDart {
int field = 1;
int finalField = 1;
int renamedField = 1;
final int renamedFinalField = 1;
int _renamedField = 1;
final int _renamedFinalField = 1;
}
@JS()
@ -72,12 +74,13 @@ extension on GetSet {
external set differentNameSameRenameSet(int val);
}
@JSExport()
class GetSetDart {
int getSet = 1;
int renamedGetSet = 1;
int sameNameDifferentRename = 1;
int differentNameSameRenameGet = 1;
int differentNameSameRenameSet = 1;
int _renamedGetSet = 1;
int _sameNameDifferentRenameGet = 1;
int _sameNameDifferentRenameSet = 1;
int _differentNameSameRename = 1;
}
void test([Object? proto]) {
@ -99,11 +102,11 @@ void test([Object? proto]) {
jsFields.field = 2;
jsFields.renamedField = 2;
expect(dartFields.field, 2);
expect(dartFields.renamedField, 2);
expect(dartFields._renamedField, 2);
// Modify the Dart mock and check for updates in the JS mock.
dartFields.field = 3;
dartFields.finalField = 3;
dartFields.renamedField = 3;
dartFields._renamedField = 3;
expect(jsFields.field, 3);
expect(jsFields.finalField, 3);
expect(jsFields.renamedField, 3);
@ -119,17 +122,17 @@ void test([Object? proto]) {
jsGetSet.sameNameDifferentRename = 2;
jsGetSet.differentNameSameRenameSet = 2;
expect(dartGetSet.getSet, 2);
expect(dartGetSet.renamedGetSet, 2);
expect(dartGetSet.sameNameDifferentRename, 2);
expect(dartGetSet.differentNameSameRenameGet, 1);
expect(dartGetSet.differentNameSameRenameSet, 2);
expect(dartGetSet._renamedGetSet, 2);
expect(dartGetSet._sameNameDifferentRenameGet, 1);
expect(dartGetSet._sameNameDifferentRenameSet, 2);
expect(dartGetSet._differentNameSameRename, 2);
// Modify the Dart mock and check for updates in the JS mock.
dartGetSet.getSet = 3;
dartGetSet.renamedGetSet = 3;
dartGetSet.sameNameDifferentRename = 3;
dartGetSet._renamedGetSet = 3;
// Use different values to disambiguate.
dartGetSet.differentNameSameRenameGet = 3;
dartGetSet.differentNameSameRenameSet = 4;
dartGetSet._sameNameDifferentRenameGet = 3;
dartGetSet._sameNameDifferentRenameSet = 4;
dartGetSet._differentNameSameRename = 3;
expect(jsGetSet.getSet, 3);
expect(jsGetSet.renamedGetSet, 3);
expect(jsGetSet.sameNameDifferentRename, 3);

View file

@ -24,26 +24,29 @@ class StaticInterop {
external factory StaticInterop();
}
class Dart {}
@JSExport()
class Dart {
int _unused = 0;
}
void main() {
createStaticInteropMock<StaticInterop, Dart>(Dart());
createStaticInteropMock<Dart, StaticInterop>(StaticInterop());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'StaticInterop' is not a Dart interface type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
// [web] Type argument 'StaticInterop' needs to be a non-JS interop type.
createStaticInteropMock<Dart, Js>(Js());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'Js' is not a Dart interface type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
// [web] Type argument 'Js' needs to be a non-JS interop type.
createStaticInteropMock<Dart, Anonymous>(Anonymous());
//^
// [web] First type argument 'Dart' is not a `@staticInterop` type.
// [web] Second type argument 'Anonymous' is not a Dart interface type.
// [web] Type argument 'Anonymous' needs to be a non-JS interop type.
// [web] Type argument 'Dart' needs to be a `@staticInterop` type.
createStaticInteropMock<StaticInterop, void Function()>(() {});
//^
// [web] Second type argument 'void Function()' is not a Dart interface type.
// [web] Type argument 'void Function()' needs to be an interface type.
createStaticInteropMock(Dart());
//^
// [web] First type argument 'dynamic' is not a `@staticInterop` type.
// [web] Type argument 'Object' needs to be a `@staticInterop` type.
}

View file

@ -2,9 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Basic inheritance test where @staticInterop class inherits extension methods
// which are then defined in the Dart class' inheritance chain, with some
// overrides.
// Test that @staticInterop extension methods are collected from all extensions,
// including inheritance.
import 'package:expect/minitest.dart';
import 'package:js/js.dart';
@ -18,8 +17,8 @@ extension on Extends {
external int extendsMethod(int val);
external int extendsField;
external final int extendsFinalField;
external int get getSet;
external set getSet(int val);
external int get extendsGetSet;
external set extendsGetSet(int val);
}
@JS()
@ -27,15 +26,12 @@ extension on Extends {
class Implements {}
extension on Implements {
@JS('_implementsMethod')
external int implementsMethod(int val);
@JS('_implementsField')
external int implementsField;
@JS('_implementsFinalField')
external final int implementsFinalField;
@JS('_implementsGetter')
@JS('implementsGetSet')
external int get implementsGetter;
@JS('_implementsSetter')
@JS('implementsGetSet')
external set implementsSetter(int val);
}
@ -47,43 +43,59 @@ extension on Inheritance {
external int method(int val);
external int field;
external final int finalField;
// Overrides
external int get getSet;
external set getSet(int val);
}
extension on Inheritance {
external int method2(int val);
external int field2;
external final int finalField2;
external int get getSet2;
external set getSet2(int val);
}
@JSExport()
class ExtendsDart {
int extendsMethod(int val) => val;
int extendsField = 0;
final int extendsFinalField = 0;
int getSet = 0;
int extendsGetSet = 0;
}
@JSExport()
class ImplementsMixin {
int implementsMethod(int val) => val;
int implementsField = 1;
final int implementsFinalField = 1;
int _implementsGetSet = 1;
int get implementsGetter => _implementsGetSet;
set implementsSetter(int val) => _implementsGetSet = val;
int implementsGetSet = 1;
}
@JSExport()
class InheritanceDart extends ExtendsDart with ImplementsMixin {
int method(int val) => val;
int field = 2;
final int finalField = 2;
@override
int getSet = 2;
int method2(int val) => val;
int field2 = 2;
final int finalField2 = 2;
int getSet2 = 2;
}
void main() {
var dartMock = InheritanceDart();
var jsMock = createStaticInteropMock<Inheritance, InheritanceDart>(dartMock);
expect(jsMock.extendsMethod(0), 0);
expect(jsMock.extendsField, 0);
jsMock.extendsField = 1;
expect(jsMock.extendsField, 1);
expect(jsMock.extendsFinalField, 0);
expect(jsMock.extendsGetSet, 0);
// Dart mock uses a field for this getter and setter, so it should change.
jsMock.extendsGetSet = 1;
expect(jsMock.extendsGetSet, 1);
expect(jsMock.implementsMethod(1), 1);
expect(jsMock.implementsField, 1);
@ -92,7 +104,6 @@ void main() {
expect(jsMock.implementsFinalField, 1);
expect(jsMock.implementsGetter, 1);
jsMock.implementsSetter = 2;
// Dart mock uses a field for this getter and setter, so it should change.
expect(jsMock.implementsGetter, 2);
expect(jsMock.method(2), 2);
@ -103,4 +114,13 @@ void main() {
expect(jsMock.getSet, 2);
jsMock.getSet = 3;
expect(jsMock.getSet, 3);
expect(jsMock.method2(2), 2);
expect(jsMock.field2, 2);
jsMock.field2 = 3;
expect(jsMock.field2, 3);
expect(jsMock.finalField2, 2);
expect(jsMock.getSet2, 2);
jsMock.getSet2 = 3;
expect(jsMock.getSet2, 3);
}

View file

@ -1,183 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks that there aren't any missing
// overrides.
import 'package:js/js.dart';
import 'package:js/js_util.dart';
@JS()
@staticInterop
class StaticInterop {}
extension on StaticInterop {
external int field;
external final int finalField;
external int get getSet;
external set getSet(int val);
external void method();
// We should ignore the non-external members for determining overrides.
int get nonExternalGetSet => throw '';
set nonExternalGetSet(int val) => throw '';
void nonExternalMethod() => throw '';
}
class CorrectDart {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartStatic {
static int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartUsingExtensions {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
}
extension on DartUsingExtensions {
void method() => throw '';
}
class DartFactory {
DartFactory();
factory DartFactory.finalField() => DartFactory();
int field = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartFinal {
final int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartNoGet {
int field = throw '';
final int finalField = throw '';
set getSet(int val) => throw '';
void method() => throw '';
}
class DartNoSet {
int field = throw '';
final int finalField = throw '';
int get getSet => throw '';
void method() => throw '';
}
class DartNoMembers {}
void main() {
createStaticInteropMock<StaticInterop, CorrectDart>(CorrectDart());
// Static members do not qualify as an override.
createStaticInteropMock<StaticInterop, DartStatic>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field', but Dart class 'DartStatic' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartStatic' does not have an overriding instance member.
DartStatic());
// Extension members do not qualify as an override.
createStaticInteropMock<StaticInterop, DartUsingExtensions>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'method', but Dart class 'DartUsingExtensions' does not have an overriding instance member.
DartUsingExtensions());
// Factory members with the same name do not qualify as an override.
createStaticInteropMock<StaticInterop, DartFactory>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'finalField', but Dart class 'DartFactory' does not have an overriding instance member.
DartFactory());
// Final fields can not override a setter.
createStaticInteropMock<StaticInterop, DartFinal>(DartFinal());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartFinal' does not have an overriding instance member.
createStaticInteropMock<StaticInterop, DartNoGet>(DartNoGet());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet', but Dart class 'DartNoGet' does not have an overriding instance member.
// Test that getters are treated differently from setters even though they
// share the same name.
createStaticInteropMock<StaticInterop, DartNoSet>(DartNoSet());
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet=', but Dart class 'DartNoSet' does not have an overriding instance member.
// Test multiple missing members.
createStaticInteropMock<StaticInterop, DartNoMembers>(
//^
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'field=', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'finalField', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'getSet=', but Dart class 'DartNoMembers' does not have an overriding instance member.
// [web] `@staticInterop` class 'StaticInterop' has external extension member 'method', but Dart class 'DartNoMembers' does not have an overriding instance member.
DartNoMembers());
testUsingInheritanceAndMixins();
}
// The following should classes should not contain any override errors, as they
// have all the necessary members.
class DartWithInheritance extends DartNoSet {
set getSet(int val) => throw '';
}
class DartWithMixins with CorrectDart {}
mixin MixinSet {
set getSet(int val) => throw '';
}
class DartWithMixinsAndInheritance extends DartNoSet with MixinSet {}
@JS()
@staticInterop
class BaseStaticInterop {}
extension on BaseStaticInterop {
external void baseMethod();
}
@JS()
@staticInterop
class StaticInteropWithInheritance extends BaseStaticInterop
implements StaticInterop {}
class DartImplementingInteropInheritance extends DartWithMixinsAndInheritance {
void baseMethod() => throw '';
}
void testUsingInheritanceAndMixins() {
// Test where Dart class implements using inherited members.
createStaticInteropMock<StaticInterop, DartWithInheritance>(
DartWithInheritance());
// Test where Dart class implements using mixed-in members.
createStaticInteropMock<StaticInterop, DartWithMixins>(DartWithMixins());
// Test where Dart class implements using inherited and mixed-in members.
createStaticInteropMock<StaticInterop, DartWithMixinsAndInheritance>(
DartWithMixinsAndInheritance());
// Missing inherited method, expect an error.
createStaticInteropMock<
//^
// [web] `@staticInterop` class 'StaticInteropWithInheritance' has external extension member 'baseMethod', but Dart class 'DartWithMixinsAndInheritance' does not have an overriding instance member.
StaticInteropWithInheritance,
DartWithMixinsAndInheritance>(DartWithMixinsAndInheritance());
// Added missing method, should pass.
createStaticInteropMock<StaticInteropWithInheritance,
DartImplementingInteropInheritance>(DartImplementingInteropInheritance());
}

View file

@ -24,6 +24,7 @@ extension on StaticInterop {
external set getSet(int? val);
}
@JSExport()
class Dart {
int? method(int? val) => throw '';
int? field = throw '';
@ -34,6 +35,7 @@ class Dart {
// Have the mock class implement the class interface you defined to mock the
// @staticInterop interface.
@JSExport()
class DartMock extends Mock implements Dart {}
void main() {

View file

@ -26,7 +26,10 @@ external Object get windowType;
@staticInterop
class JSWindow {}
class DartWindow {}
@JSExport()
class DartWindow {
int _unused = 0;
}
void main() {
// Test that everything still works the same.

View file

@ -2,11 +2,67 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that `createStaticInteropMock` checks that overrides are subtypes.
// Test that `createStaticInteropMock` checks that overrides exist and are
// subtypes.
import 'package:js/js.dart';
import 'package:js/js_util.dart';
@JS()
@staticInterop
class StaticInterop {}
extension on StaticInterop {
external int field;
external final int finalField;
external int get getSet1;
external set getSet1(int val);
external int get getSet2;
external set getSet2(int val);
external void method();
}
@JSExport()
class CorrectDart {
int field = throw '';
final int finalField = throw '';
int get getSet1 => throw '';
set getSet1(int val) => throw '';
int get getSet2 => throw '';
set getSet2(int val) => throw '';
void method() => throw '';
}
@JSExport()
class IncorrectDart {
IncorrectDart();
// Factories do not count.
factory IncorrectDart.method() => IncorrectDart();
// Setter is not implemented.
final int field = throw '';
// Static members do not count.
static final int finalField = throw '';
// Getter is not implemented.
set getSet1(int val) => throw '';
int get getSet2 => throw '';
}
extension on IncorrectDart {
// Extension members do not count.
set getSet2(int val) => throw '';
}
void testMissingOverrides() {
createStaticInteropMock<StaticInterop, CorrectDart>(CorrectDart());
createStaticInteropMock<StaticInterop, IncorrectDart>(IncorrectDart());
//^
// [web] Dart class 'IncorrectDart' does not have any members that implement any of the following extension member(s) with export name 'finalField': <unnamed>.finalField (FunctionType(int Function())).
// [web] Dart class 'IncorrectDart' does not have any members that implement any of the following extension member(s) with export name 'method': <unnamed>.method (FunctionType(void Function())).
// [web] Dart class 'IncorrectDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'field': <unnamed>.field= (FunctionType(void Function(int))).
// [web] Dart class 'IncorrectDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet2': <unnamed>.getSet2= (FunctionType(void Function(int))).
// [web] Dart class 'IncorrectDart' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'getSet1': <unnamed>.getSet1 (FunctionType(int Function())).
}
// Set up a simple type hierarchy.
class A {
const A();
@ -27,38 +83,61 @@ class SimpleInterop {}
extension SimpleInteropExtension on SimpleInterop {
external B field;
external final B finalField;
external B get getSetNum;
external set getSetInt(B val);
external B get getSet;
external set getSet(B val);
external B method(B b);
}
// Implement using the exact same types.
@JSExport()
class SimpleDart {
B field = throw '';
final B finalField = throw '';
B get getSetNum => throw '';
set getSetInt(B val) => throw '';
B get getSet => throw '';
set getSet(B val) => throw '';
B method(B b) => throw '';
}
void testExactTypes() {
createStaticInteropMock<SimpleInterop, SimpleDart>(SimpleDart());
}
// Implement using subtypes.
@JSExport()
class SubtypeSimpleDart {
B field = throw '';
final C finalField = throw '';
C get getSetNum => throw '';
set getSetInt(A val) => throw '';
C get getSet => throw '';
set getSet(A val) => throw '';
C method(A a) => throw '';
}
void testSimpleSubtyping() {
createStaticInteropMock<SimpleInterop, SubtypeSimpleDart>(
SubtypeSimpleDart());
}
// Implement using supertypes (which shouldn't work).
@JSExport()
class SupertypeSimpleDart {
A field = throw '';
final A finalField = throw '';
A get getSetNum => throw '';
set getSetInt(C val) => throw '';
// Getter must be subtype of setter, so only the setter should be an error.
C get getSet => throw '';
set getSet(C val) => throw '';
A method(C c) => throw '';
}
void testIncorrectSimpleSubtyping() {
createStaticInteropMock<SimpleInterop, SupertypeSimpleDart>(
//^
// [web] Dart class 'SupertypeSimpleDart' does not have any members that implement any of the following extension member(s) with export name 'finalField': SimpleInteropExtension.finalField (FunctionType(B Function())).
// [web] Dart class 'SupertypeSimpleDart' does not have any members that implement any of the following extension member(s) with export name 'method': SimpleInteropExtension.method (FunctionType(B Function(B))).
// [web] Dart class 'SupertypeSimpleDart' has a getter, but does not have a setter to implement any of the following extension member(s) with export name 'getSet': SimpleInteropExtension.getSet= (FunctionType(void Function(B))).
// [web] Dart class 'SupertypeSimpleDart' has a setter, but does not have a getter to implement any of the following extension member(s) with export name 'field': SimpleInteropExtension.field (FunctionType(B Function())).
SupertypeSimpleDart());
}
@JS()
@staticInterop
class ComplexAndOptionalInteropMethods {}
@ -70,12 +149,19 @@ extension ComplexAndOptionalInteropMethodsExtension
external B optionalSubtype(B b, [B b2 = const B()]);
}
@JSExport()
class ComplexAndOptionalDart {
C Function(A _) nestedTypes(List<B> arg1, Map<Set<B>, B> arg2) => throw '';
B optional(B b, [B? b2]) => throw '';
C optionalSubtype(A a, [A? a2]) => throw '';
}
void testComplexSubtyping() {
createStaticInteropMock<ComplexAndOptionalInteropMethods,
ComplexAndOptionalDart>(ComplexAndOptionalDart());
}
@JSExport()
class IncorrectComplexAndOptionalDart {
// List type is wrong.
B Function(B _) nestedTypes(List<List<B>> arg1, Map<Set<B>, B> arg2) =>
@ -86,25 +172,25 @@ class IncorrectComplexAndOptionalDart {
B optionalSubtype(B b, [C c = const C()]) => throw '';
}
void main() {
createStaticInteropMock<SimpleInterop, SimpleDart>(SimpleDart());
createStaticInteropMock<SimpleInterop, SubtypeSimpleDart>(
SubtypeSimpleDart());
createStaticInteropMock<SimpleInterop, SupertypeSimpleDart>(
//^
// [web] Dart class member 'SupertypeSimpleDart.field' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.field' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.finalField' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.finalField' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.getSetInt=' with type 'void Function(C)' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.getSetInt=' with type 'void Function(B)'.
// [web] Dart class member 'SupertypeSimpleDart.getSetNum' with type 'A Function()' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.getSetNum' with type 'B Function()'.
// [web] Dart class member 'SupertypeSimpleDart.method' with type 'A Function(C)' is not a subtype of `@staticInterop` external extension member 'SimpleInterop.method' with type 'B Function(B)'.
SupertypeSimpleDart());
createStaticInteropMock<ComplexAndOptionalInteropMethods,
ComplexAndOptionalDart>(ComplexAndOptionalDart());
void testIncorrectComplexSubtyping() {
createStaticInteropMock<
//^
// [web] Dart class member 'IncorrectComplexAndOptionalDart.nestedTypes' with type 'B Function(B) Function(List<List<B>>, Map<Set<B>, B>)' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.nestedTypes' with type 'B Function(B) Function(List<B>, Map<Set<B>, B>)'.
// [web] Dart class member 'IncorrectComplexAndOptionalDart.optional' with type 'B Function(B, B?)' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.optional' with type 'B Function(B, [B?])'.
// [web] Dart class member 'IncorrectComplexAndOptionalDart.optionalSubtype' with type 'B Function(B, [C])' is not a subtype of `@staticInterop` external extension member 'ComplexAndOptionalInteropMethods.optionalSubtype' with type 'B Function(B, [B])'.
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'nestedTypes': ComplexAndOptionalInteropMethodsExtension.nestedTypes (FunctionType(B Function(B) Function(List<B>, Map<Set<B>, B>))).
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'optional': ComplexAndOptionalInteropMethodsExtension.optional (FunctionType(B Function(B, [B?]))).
// [web] Dart class 'IncorrectComplexAndOptionalDart' does not have any members that implement any of the following extension member(s) with export name 'optionalSubtype': ComplexAndOptionalInteropMethodsExtension.optionalSubtype (FunctionType(B Function(B, [B]))).
ComplexAndOptionalInteropMethods,
IncorrectComplexAndOptionalDart>(IncorrectComplexAndOptionalDart());
}
void testSubtyping() {
testExactTypes();
testSimpleSubtyping();
testIncorrectSimpleSubtyping();
testComplexSubtyping();
testIncorrectComplexSubtyping();
}
void main() {
testMissingOverrides();
testSubtyping();
}