// Copyright (c) 2020, 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. // Tests subtyping relationships between JS and anonymous classes. @JS() library subtyping_test; import 'package:js/js.dart'; import 'package:expect/expect.dart' show hasUnsoundNullSafety; import 'package:expect/minitest.dart'; @JS() class JSClassA {} @JS() class JSClassB {} @JS() @anonymous class AnonymousClassA {} @JS() @anonymous class AnonymousClassB {} class DartClass {} void useJSClassA(JSClassA _) {} void useAnonymousClassA(AnonymousClassA _) {} void useDartClass(DartClass _) {} void useNullableJSClassA(JSClassA? _) {} void useNullableAnonymousClassA(AnonymousClassA? _) {} // Avoid static type optimization by running all tests using this. @pragma('dart2js:noInline') @pragma('dart2js:assumeDynamic') confuse(x) => x; void main() { // Checks subtyping with the same type and nullability subtyping. expect(useJSClassA is void Function(JSClassA), true); expect(useAnonymousClassA is void Function(AnonymousClassA), true); expect(useJSClassA is void Function(JSClassA?), hasUnsoundNullSafety); expect(useAnonymousClassA is void Function(AnonymousClassA?), hasUnsoundNullSafety); expect(useNullableJSClassA is void Function(JSClassA?), true); expect(useNullableAnonymousClassA is void Function(AnonymousClassA?), true); expect(useNullableJSClassA is void Function(JSClassA), true); expect(useNullableAnonymousClassA is void Function(AnonymousClassA), true); expect(confuse(useJSClassA) is void Function(JSClassA), true); expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA), true); expect( confuse(useJSClassA) is void Function(JSClassA?), hasUnsoundNullSafety); expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA?), hasUnsoundNullSafety); expect(confuse(useNullableJSClassA) is void Function(JSClassA?), true); expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA?), true); expect(confuse(useNullableJSClassA) is void Function(JSClassA), true); expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA), true); // No subtyping between JS and anonymous classes. expect(useJSClassA is void Function(AnonymousClassA), false); expect(useAnonymousClassA is void Function(JSClassA), false); expect(confuse(useJSClassA) is void Function(AnonymousClassA), false); expect(confuse(useAnonymousClassA) is void Function(JSClassA), false); // No subtyping between separate classes even if they're both JS classes or // anonymous classes. expect(useJSClassA is void Function(JSClassB), false); expect(useAnonymousClassA is void Function(AnonymousClassB), false); expect(confuse(useJSClassA) is void Function(JSClassB), false); expect(confuse(useAnonymousClassA) is void Function(AnonymousClassB), false); // No subtyping between JS/anonymous classes and Dart classes. expect(useJSClassA is void Function(DartClass), false); expect(useAnonymousClassA is void Function(DartClass), false); expect(confuse(useJSClassA) is void Function(DartClass), false); expect(confuse(useAnonymousClassA) is void Function(DartClass), false); }