Skip to content

Commit 7be0e41

Browse files
authored
#3180. Add isA tests. Part 1. (#3263)
Add `isA` tests. Part 1.
1 parent 292ccda commit 7be0e41

File tree

9 files changed

+456
-0
lines changed

9 files changed

+456
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
///
9+
/// Since the type-check this function emits is determined at compile-time, `T`
10+
/// needs to be an interop extension type that can also be determined at
11+
/// compile-time. In particular, `isA` can't be provided a generic type variable
12+
/// as a type argument.
13+
///
14+
/// @description Checks that it is a compile-time error id `T` is a type
15+
/// variable.
16+
/// @author [email protected]
17+
18+
import 'dart:js_interop';
19+
20+
test<T extends JSAny?>(JSAny? v) {
21+
v.isA<T>();
22+
// ^
23+
// [analyzer] unspecified
24+
// [web] unspecified
25+
}
26+
27+
main() {
28+
test<JSObject>(JSObject());
29+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If `T` is a primitive JS type like [JSString], this uses a `typeof` check
10+
/// that corresponds to that primitive type like `typeofEquals('string')`.
11+
///
12+
/// @description Checks that `isA` works as expected for JS non-nullable
13+
/// primitive types.
14+
/// @author [email protected]
15+
16+
import 'dart:js_interop';
17+
import 'dart:js_interop_unsafe';
18+
import '../../../Utils/expect.dart';
19+
import '../js_utils.dart';
20+
21+
main() {
22+
eval(r'''
23+
globalThis.s = "JS string";
24+
globalThis.b = false;
25+
globalThis.n1 = 42;
26+
globalThis.n2 = 3.14;
27+
globalThis.bi = 123456789n;
28+
globalThis.smb = Symbol();
29+
''');
30+
Expect.isTrue(globalContext["s"].isA<JSString>());
31+
Expect.isTrue(globalContext["s"].isA<JSAny>());
32+
Expect.isFalse(globalContext["s"].isA<JSObject>());
33+
Expect.isFalse(globalContext["s"].isA<JSNumber>());
34+
Expect.isFalse(globalContext["s"].isA<JSBoolean>());
35+
Expect.isFalse(globalContext["s"].isA<JSSymbol>());
36+
Expect.isFalse(globalContext["s"].isA<JSBigInt>());
37+
38+
Expect.isTrue(globalContext["b"].isA<JSBoolean>());
39+
Expect.isTrue(globalContext["b"].isA<JSAny>());
40+
Expect.isFalse(globalContext["b"].isA<JSObject>());
41+
Expect.isFalse(globalContext["b"].isA<JSNumber>());
42+
Expect.isFalse(globalContext["b"].isA<JSString>());
43+
Expect.isFalse(globalContext["b"].isA<JSSymbol>());
44+
Expect.isFalse(globalContext["b"].isA<JSBigInt>());
45+
46+
Expect.isTrue(globalContext["n1"].isA<JSNumber>());
47+
Expect.isTrue(globalContext["n1"].isA<JSAny>());
48+
Expect.isFalse(globalContext["n1"].isA<JSObject>());
49+
Expect.isFalse(globalContext["n1"].isA<JSBoolean>());
50+
Expect.isFalse(globalContext["n1"].isA<JSString>());
51+
Expect.isFalse(globalContext["n1"].isA<JSSymbol>());
52+
Expect.isFalse(globalContext["n1"].isA<JSBigInt>());
53+
54+
Expect.isTrue(globalContext["n2"].isA<JSNumber>());
55+
Expect.isTrue(globalContext["n2"].isA<JSAny>());
56+
Expect.isFalse(globalContext["n2"].isA<JSObject>());
57+
Expect.isFalse(globalContext["n2"].isA<JSBoolean>());
58+
Expect.isFalse(globalContext["n2"].isA<JSString>());
59+
Expect.isFalse(globalContext["n2"].isA<JSSymbol>());
60+
Expect.isFalse(globalContext["n2"].isA<JSBigInt>());
61+
62+
Expect.isTrue(globalContext["bi"].isA<JSBigInt>());
63+
Expect.isTrue(globalContext["bi"].isA<JSAny>());
64+
Expect.isFalse(globalContext["bi"].isA<JSObject>());
65+
Expect.isFalse(globalContext["bi"].isA<JSNumber>());
66+
Expect.isFalse(globalContext["bi"].isA<JSBoolean>());
67+
Expect.isFalse(globalContext["bi"].isA<JSSymbol>());
68+
Expect.isFalse(globalContext["bi"].isA<JSString>());
69+
70+
Expect.isTrue(globalContext["smb"].isA<JSSymbol>());
71+
Expect.isTrue(globalContext["smb"].isA<JSAny>());
72+
Expect.isFalse(globalContext["smb"].isA<JSObject>());
73+
Expect.isFalse(globalContext["smb"].isA<JSNumber>());
74+
Expect.isFalse(globalContext["smb"].isA<JSBoolean>());
75+
Expect.isFalse(globalContext["smb"].isA<JSBigInt>());
76+
Expect.isFalse(globalContext["smb"].isA<JSString>());
77+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If `T` is a primitive JS type like [JSString], this uses a `typeof` check
10+
/// that corresponds to that primitive type like `typeofEquals('string')`.
11+
///
12+
/// @description Checks that `isA` works as expected for JS `null` and
13+
/// `undefined` values.
14+
/// @author [email protected]
15+
16+
import 'dart:js_interop';
17+
import 'dart:js_interop_unsafe';
18+
import '../../../Utils/expect.dart';
19+
import '../js_utils.dart';
20+
21+
main() {
22+
eval(r'''
23+
globalThis.n = null;
24+
globalThis.u = undefined;
25+
''');
26+
Expect.isFalse(globalContext["n"].isA<JSString>());
27+
Expect.isFalse(globalContext["n"].isA<JSObject>());
28+
Expect.isFalse(globalContext["n"].isA<JSAny>());
29+
Expect.isFalse(globalContext["n"].isA<JSNumber>());
30+
Expect.isFalse(globalContext["n"].isA<JSBoolean>());
31+
Expect.isFalse(globalContext["n"].isA<JSSymbol>());
32+
Expect.isFalse(globalContext["n"].isA<JSBigInt>());
33+
Expect.isTrue(globalContext["n"].isA<JSAny?>());
34+
35+
Expect.isFalse(globalContext["u"].isA<JSString>());
36+
Expect.isFalse(globalContext["u"].isA<JSObject>());
37+
Expect.isFalse(globalContext["u"].isA<JSAny>());
38+
Expect.isFalse(globalContext["u"].isA<JSNumber>());
39+
Expect.isFalse(globalContext["u"].isA<JSBoolean>());
40+
Expect.isFalse(globalContext["u"].isA<JSSymbol>());
41+
Expect.isFalse(globalContext["u"].isA<JSBigInt>());
42+
Expect.isTrue(globalContext["u"].isA<JSAny?>());
43+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If `T` is a primitive JS type like [JSString], this uses a `typeof` check
10+
/// that corresponds to that primitive type like `typeofEquals('string')`.
11+
///
12+
/// @description Checks that `isA` works as expected for JS nullable primitive
13+
/// types.
14+
/// @author [email protected]
15+
16+
import 'dart:js_interop';
17+
import 'dart:js_interop_unsafe';
18+
import '../../../Utils/expect.dart';
19+
import '../js_utils.dart';
20+
21+
main() {
22+
eval(r'''
23+
globalThis.s = "JS string";
24+
globalThis.b = false;
25+
globalThis.n1 = 42;
26+
globalThis.n2 = 3.14;
27+
globalThis.bi = 123456789n;
28+
globalThis.smb = Symbol();
29+
globalThis.n = null;
30+
''');
31+
Expect.isTrue(globalContext["s"].isA<JSString?>());
32+
Expect.isTrue(globalContext["s"].isA<JSAny?>());
33+
Expect.isFalse(globalContext["s"].isA<JSObject?>());
34+
Expect.isFalse(globalContext["s"].isA<JSNumber?>());
35+
Expect.isFalse(globalContext["s"].isA<JSBoolean?>());
36+
Expect.isFalse(globalContext["s"].isA<JSSymbol?>());
37+
Expect.isFalse(globalContext["s"].isA<JSBigInt?>());
38+
39+
Expect.isTrue(globalContext["b"].isA<JSBoolean?>());
40+
Expect.isTrue(globalContext["b"].isA<JSAny?>());
41+
Expect.isFalse(globalContext["b"].isA<JSObject?>());
42+
Expect.isFalse(globalContext["b"].isA<JSNumber?>());
43+
Expect.isFalse(globalContext["b"].isA<JSString?>());
44+
Expect.isFalse(globalContext["b"].isA<JSSymbol?>());
45+
Expect.isFalse(globalContext["b"].isA<JSBigInt?>());
46+
47+
Expect.isTrue(globalContext["n1"].isA<JSNumber?>());
48+
Expect.isTrue(globalContext["n1"].isA<JSAny?>());
49+
Expect.isFalse(globalContext["n1"].isA<JSObject?>());
50+
Expect.isFalse(globalContext["n1"].isA<JSBoolean?>());
51+
Expect.isFalse(globalContext["n1"].isA<JSString?>());
52+
Expect.isFalse(globalContext["n1"].isA<JSSymbol?>());
53+
Expect.isFalse(globalContext["n1"].isA<JSBigInt?>());
54+
55+
Expect.isTrue(globalContext["n2"].isA<JSNumber?>());
56+
Expect.isTrue(globalContext["n2"].isA<JSAny?>());
57+
Expect.isFalse(globalContext["n2"].isA<JSObject?>());
58+
Expect.isFalse(globalContext["n2"].isA<JSBoolean?>());
59+
Expect.isFalse(globalContext["n2"].isA<JSString?>());
60+
Expect.isFalse(globalContext["n2"].isA<JSSymbol?>());
61+
Expect.isFalse(globalContext["n2"].isA<JSBigInt?>());
62+
63+
Expect.isTrue(globalContext["bi"].isA<JSBigInt?>());
64+
Expect.isTrue(globalContext["bi"].isA<JSAny?>());
65+
Expect.isFalse(globalContext["bi"].isA<JSObject?>());
66+
Expect.isFalse(globalContext["bi"].isA<JSNumber?>());
67+
Expect.isFalse(globalContext["bi"].isA<JSBoolean?>());
68+
Expect.isFalse(globalContext["bi"].isA<JSSymbol?>());
69+
Expect.isFalse(globalContext["bi"].isA<JSString?>());
70+
71+
Expect.isTrue(globalContext["smb"].isA<JSSymbol?>());
72+
Expect.isTrue(globalContext["smb"].isA<JSAny?>());
73+
Expect.isFalse(globalContext["smb"].isA<JSObject?>());
74+
Expect.isFalse(globalContext["smb"].isA<JSNumber?>());
75+
Expect.isFalse(globalContext["smb"].isA<JSBoolean?>());
76+
Expect.isFalse(globalContext["smb"].isA<JSBigInt?>());
77+
Expect.isFalse(globalContext["smb"].isA<JSString?>());
78+
79+
Expect.isTrue(globalContext["n"].isA<JSSymbol?>());
80+
Expect.isTrue(globalContext["n"].isA<JSAny?>());
81+
Expect.isTrue(globalContext["n"].isA<JSObject?>());
82+
Expect.isTrue(globalContext["n"].isA<JSNumber?>());
83+
Expect.isTrue(globalContext["n"].isA<JSBoolean?>());
84+
Expect.isTrue(globalContext["n"].isA<JSBigInt?>());
85+
Expect.isTrue(globalContext["n"].isA<JSString?>());
86+
87+
Expect.isTrue(globalContext["u"].isA<JSSymbol?>());
88+
Expect.isTrue(globalContext["u"].isA<JSAny?>());
89+
Expect.isTrue(globalContext["u"].isA<JSObject?>());
90+
Expect.isTrue(globalContext["u"].isA<JSNumber?>());
91+
Expect.isTrue(globalContext["u"].isA<JSBoolean?>());
92+
Expect.isTrue(globalContext["u"].isA<JSBigInt?>());
93+
Expect.isTrue(globalContext["u"].isA<JSString?>());
94+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If T is a non-primitive JS type like [JSArray] or an interop extension type
10+
/// on one, this uses an instanceof check using the name or the `@JS` rename of
11+
/// the given type like `instanceOfString('Array')`. Note that if you rename the
12+
/// library using the `@JS` annotation, this uses the rename in the instanceof
13+
/// check like `instanceOfString('library1.JSClass')`.
14+
///
15+
/// @description Checks that `isA<JSArray>` returns `true` for `JSArray` type.
16+
/// @author [email protected]
17+
18+
import 'dart:js_interop';
19+
import 'dart:js_interop_unsafe';
20+
import '../../../Utils/expect.dart';
21+
import '../js_utils.dart';
22+
23+
main() {
24+
eval(r'''
25+
globalThis.ar1 = Array();
26+
globalThis.ar2 = [];
27+
globalThis.ar3 = [1, 2, 3];
28+
''');
29+
test(globalContext["ar1"]);
30+
test(globalContext["ar2"]);
31+
test(globalContext["ar3"]);
32+
}
33+
34+
test(JSAny? value) {
35+
Expect.isTrue(value.isA<JSArray>());
36+
Expect.isTrue(value.isA<JSAny>());
37+
Expect.isTrue(value.isA<JSObject>());
38+
Expect.isFalse(value.isA<JSNumber>());
39+
Expect.isFalse(value.isA<JSBoolean>());
40+
Expect.isFalse(value.isA<JSBigInt>());
41+
Expect.isFalse(value.isA<JSString>());
42+
Expect.isFalse(value.isA<JSSymbol>());
43+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If T is a non-primitive JS type like [JSArray] or an interop extension type
10+
/// on one, this uses an instanceof check using the name or the `@JS` rename of
11+
/// the given type like `instanceOfString('Array')`. Note that if you rename the
12+
/// library using the `@JS` annotation, this uses the rename in the instanceof
13+
/// check like `instanceOfString('library1.JSClass')`.
14+
///
15+
/// @description Checks that `isA<JSArray>` returns `true` for `JSArray` type.
16+
/// @author [email protected]
17+
18+
import 'dart:js_interop';
19+
import 'dart:js_interop_unsafe';
20+
import '../../../Utils/expect.dart';
21+
import '../js_utils.dart';
22+
23+
main() {
24+
eval(r'''
25+
globalThis.ar1 = Array("");
26+
globalThis.ar2 = ["one", "two", "three"];
27+
globalThis.ar3 = [1, 2, 3];
28+
''');
29+
Expect.isTrue(globalContext["ar1"].isA<JSArray<JSString>>());
30+
Expect.isTrue(globalContext["ar1"].isA<JSArray<JSObject>>());
31+
32+
Expect.isTrue(globalContext["ar2"].isA<JSArray<JSString>>());
33+
Expect.isTrue(globalContext["ar2"].isA<JSArray<JSNumber>>());
34+
35+
Expect.isTrue(globalContext["ar3"].isA<JSArray<JSNumber>>());
36+
Expect.isTrue(globalContext["ar3"].isA<JSArray<JSString>>());
37+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion bool isA<T extends JSAny?>()
6+
/// Whether this [JSAny?] is an instance of the JavaScript type that is declared
7+
/// by `T`.
8+
/// ...
9+
/// If T is a non-primitive JS type like [JSArray] or an interop extension type
10+
/// on one, this uses an instanceof check using the name or the `@JS` rename of
11+
/// the given type like `instanceOfString('Array')`. Note that if you rename the
12+
/// library using the `@JS` annotation, this uses the rename in the instanceof
13+
/// check like `instanceOfString('library1.JSClass')`.
14+
///
15+
/// @description Checks that `isA<JSArray>` returns `true` for an extension type
16+
/// on `JSArray`.
17+
/// @author [email protected]
18+
19+
import 'dart:js_interop';
20+
import 'dart:js_interop_unsafe';
21+
import '../../../Utils/expect.dart';
22+
import '../js_utils.dart';
23+
24+
@JS()
25+
extension type MyArray1(JSArray ar) implements JSArray {}
26+
27+
@JS()
28+
extension type MyArray2<T extends JSAny?>(JSArray<T> ar) implements JSArray<T> {
29+
}
30+
31+
main() {
32+
MyArray1 ma1 = MyArray1(JSArray());
33+
globalContext["ma1"] = ma1;
34+
Expect.isTrue(globalContext["ma1"].isA<JSArray>());
35+
Expect.isFalse(globalContext["ma1"].isA<JSNumber>());
36+
Expect.isFalse(globalContext["ma1"].isA<MyArray1>());
37+
38+
eval("globalThis.s = 'JS String';");
39+
JSString jsS = globalContext["s"] as JSString;
40+
JSArray<JSString> jsArr = JSArray<JSString>.withLength(1);
41+
jsArr[0] = jsS;
42+
MyArray2<JSString> ma2 = MyArray2(jsArr);
43+
globalContext["ma2"] = ma2;
44+
Expect.isTrue(globalContext["ma2"].isA<JSArray<JSString>>());
45+
Expect.isTrue(globalContext["ma2"].isA<JSArray<JSNumber>>());
46+
Expect.isFalse(globalContext["ma2"].isA<MyArray2>());
47+
}

0 commit comments

Comments
 (0)