blob: 2551fcdb9ec607fed696b84cffd87f878091d134 [file] [log] [blame]
// 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);
}