[js] Add Dart Object API tests for interop objects
Change-Id: I806ef3e5ed2468eecd91427a3e28cc0859aa81fa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317844
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
diff --git a/tests/lib/js/object_apis_interop_values_test.dart b/tests/lib/js/object_apis_interop_values_test.dart
new file mode 100644
index 0000000..7e6ed9c
--- /dev/null
+++ b/tests/lib/js/object_apis_interop_values_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2023, 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.
+
+@JS()
+library js_interop_test;
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+import 'object_apis_utils.dart';
+
+@JS()
+external dynamic eval(String code);
+
+@JS()
+class JavaScriptClass {
+ external factory JavaScriptClass();
+ external int get instanceGetter;
+}
+
+void main() {
+ // Install a class that is accessible through interop.
+ eval('''
+self.JavaScriptClass = class JavaScriptClass {
+ constructor() {}
+ get instanceGetter() { return 42; }
+}
+''');
+ var instanceOfClass = JavaScriptClass();
+ var other = JavaScriptClass();
+ Expect.equals(42, instanceOfClass.instanceGetter);
+ testHashCode(instanceOfClass);
+ testRuntimeType(instanceOfClass);
+ testNoSuchMethod(instanceOfClass);
+ testNoSuchMethodTearoff(instanceOfClass);
+ testToString(instanceOfClass);
+ testToStringTearoff(instanceOfClass);
+ testEquals(instanceOfClass, other);
+
+ var emptyObject = eval('Object.create({})');
+ testHashCode(emptyObject);
+ testRuntimeType(emptyObject);
+ testNoSuchMethod(emptyObject);
+ testNoSuchMethodTearoff(emptyObject);
+ testToString(emptyObject);
+ testToStringTearoff(emptyObject);
+ testEquals(emptyObject, other);
+
+ var jsNull = eval('null');
+ testHashCode(jsNull);
+ testRuntimeType(jsNull);
+ testNoSuchMethod(jsNull);
+ testNoSuchMethodTearoff(jsNull);
+ testToString(jsNull);
+ testToStringTearoff(jsNull);
+ testEquals(jsNull, other);
+}
diff --git a/tests/lib/js/object_apis_utils.dart b/tests/lib/js/object_apis_utils.dart
new file mode 100644
index 0000000..b5041af
--- /dev/null
+++ b/tests/lib/js/object_apis_utils.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2023, 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.
+
+import 'package:expect/expect.dart';
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void testHashCode(x) {
+ var hashCodeResult = confuse(x.hashCode);
+ Expect.type<int>(hashCodeResult);
+ Expect.equals(x.hashCode, hashCodeResult);
+}
+
+void testRuntimeType(x) {
+ var runtimeTypeResult = confuse(x.runtimeType);
+ Expect.type<Type>(runtimeTypeResult);
+ Expect.equals(x.runtimeType, runtimeTypeResult);
+}
+
+void testNoSuchMethod(x) {
+ var noSuchMethodResult = Expect.throws(
+ () => x.noSuchMethod(Invocation.method(Symbol('testMethod'), null)));
+ Expect.type<NoSuchMethodError>(noSuchMethodResult);
+ Expect.contains('testMethod', noSuchMethodResult.toString());
+}
+
+void testNoSuchMethodTearoff(x) {
+ var noSuchMethodTearoff = confuse(x.noSuchMethod);
+ Expect.type<dynamic Function(Invocation)>(noSuchMethodTearoff);
+ Expect.equals(x.noSuchMethod, noSuchMethodTearoff);
+ var noSuchMethodResult = Expect.throws(
+ () => noSuchMethodTearoff(Invocation.method(Symbol('testMethod'), null)));
+ Expect.type<NoSuchMethodError>(noSuchMethodResult);
+ Expect.contains('testMethod', noSuchMethodResult.toString());
+}
+
+void testToString(x) {
+ var toStringResult = confuse(x.toString());
+ Expect.type<String>(toStringResult);
+ Expect.isTrue(toStringResult.isNotEmpty);
+ Expect.equals(x.toString(), toStringResult);
+}
+
+void testToStringTearoff(x) {
+ var toStringTearoff = confuse(x.toString);
+ Expect.type<String Function()>(toStringTearoff);
+ Expect.equals(x.toString, toStringTearoff);
+ var toStringResult = toStringTearoff();
+ Expect.type<String>(toStringResult);
+ Expect.isTrue(toStringResult.isNotEmpty);
+ Expect.equals(x.toString(), toStringResult);
+}
+
+void testEquals(x, other) {
+ var y = confuse(other);
+ var equalityResult = x == y;
+ Expect.type<bool>(equalityResult);
+ Expect.isFalse(equalityResult);
+ Expect.equals(equalityResult, x == y);
+ Expect.isTrue(confuse(x) == x);
+}
diff --git a/tests/lib/js/static_interop_test/object_apis_static_interop_values_test.dart b/tests/lib/js/static_interop_test/object_apis_static_interop_values_test.dart
new file mode 100644
index 0000000..d439fa8
--- /dev/null
+++ b/tests/lib/js/static_interop_test/object_apis_static_interop_values_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2023, 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.
+
+@JS()
+library object_apis_test;
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+import '../object_apis_utils.dart';
+
+@JS()
+external dynamic eval(String code);
+
+@JS()
+@staticInterop
+class JavaScriptClass {
+ external factory JavaScriptClass();
+}
+
+extension on JavaScriptClass {
+ external int get instanceGetter;
+}
+
+void main() {
+ // Install a class that is accessible through interop.
+ eval('''
+self.JavaScriptClass = class JavaScriptClass {
+ constructor() {}
+ get instanceGetter() { return 42; }
+}
+''');
+ var instanceOfClass = JavaScriptClass();
+ var other = JavaScriptClass();
+ Expect.equals(42, instanceOfClass.instanceGetter);
+ testHashCode(instanceOfClass);
+ testRuntimeType(instanceOfClass);
+ testNoSuchMethod(instanceOfClass);
+ testNoSuchMethodTearoff(instanceOfClass);
+ testToString(instanceOfClass);
+ testToStringTearoff(instanceOfClass);
+ testEquals(instanceOfClass, other);
+
+ var emptyObject = eval('Object.create({})');
+ testHashCode(emptyObject);
+ testRuntimeType(emptyObject);
+ testNoSuchMethod(emptyObject);
+ testNoSuchMethodTearoff(emptyObject);
+ testToString(emptyObject);
+ testToStringTearoff(emptyObject);
+ testEquals(emptyObject, other);
+
+ var jsNull = eval('null');
+ testHashCode(jsNull);
+ testRuntimeType(jsNull);
+ testNoSuchMethod(jsNull);
+ testNoSuchMethodTearoff(jsNull);
+ testToString(jsNull);
+ testToStringTearoff(jsNull);
+ testEquals(jsNull, other);
+}