[dart2js,ddc] Add package:js `.call()` tests

Some expectations in these tests do not match the language 
specification or are undefined.

These tests should help:
 - avoid regressions in the existing behavior
 - highlight incremental improvements towards implementing the 
   desired behavior (with corresponding changes to the expectations)
 - identify the differences between the JavaScript compilers

Change-Id: Icaa7371b3cf8c4221e4348176f712b3d03196720
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/359245
Commit-Queue: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/tests/lib/js/call_field_test.dart b/tests/lib/js/call_field_test.dart
new file mode 100644
index 0000000..b0cd0ce
--- /dev/null
+++ b/tests/lib/js/call_field_test.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2024, 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.
+
+/// WARNING
+///
+/// Not all of the expectations in this test match the language specification.
+///
+/// This is part of a set of tests covering "callable objects". Please consider
+/// them all together when making changes:
+///
+/// ```
+/// tests/lib/js/call_field_test.dart
+/// tests/lib/js/call_getter_test.dart
+/// tests/lib/js/call_method_test.dart
+/// ```
+///
+/// This test was created with expectations that match the current behavior to
+/// make it more clear when something changes and when the results in the web
+/// compilers differ.
+///
+/// If your change causes an expectation to fail you should decide if the
+/// new result is desireable and update the expectation accordingly.
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+import 'call_utils.dart';
+
+@JS()
+class NamedClass {
+  external int Function(String s) call;
+}
+
+@JS('jsFunction')
+external NamedClass get jsFunctionAsNamedClass;
+
+@JS('jsObject')
+external NamedClass get jsObjectAsNamedClass;
+
+@JS('jsClass')
+external NamedClass get jsClassAsNamedClass;
+
+@JS()
+class NamedClass2 {
+  external Function call;
+}
+
+@JS('jsFunction')
+external NamedClass2 get functionAsNamedClass2;
+
+@JS('jsObject')
+external NamedClass2 get jsObjectAsNamedClass2;
+
+@JS('jsClass')
+external NamedClass2 get jsClassAsNamedClass2;
+
+@JS()
+@anonymous
+class SomeClass {
+  external int Function(String s) call;
+}
+
+@JS('jsFunction')
+external SomeClass get functionAsSomeClass;
+
+@JS('jsObject')
+external SomeClass get jsObjectAsSomeClass;
+
+@JS('jsClass')
+external SomeClass get jsClassAsSomeClass;
+
+@JS()
+@anonymous
+class SomeClass2 {
+  external Function call;
+}
+
+@JS('jsFunction')
+external SomeClass2 get functionAsSomeClass2;
+
+@JS('jsObject')
+external SomeClass2 get jsObjectAsSomeClass2;
+
+@JS('jsClass')
+external SomeClass2 get jsClassAsSomeClass2;
+
+void main() {
+  injectJS();
+  testNamedClass();
+  testNamedClass2();
+  testAnonymous();
+  testAnonymous2();
+  testDynamic();
+}
+
+void testNamedClass() {
+  var obj = jsFunctionAsNamedClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testNamedClass2() {
+  var obj = functionAsNamedClass2;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsNamedClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsNamedClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testAnonymous() {
+  var obj = functionAsSomeClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testAnonymous2() {
+  var obj = functionAsSomeClass2;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsSomeClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsSomeClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testDynamic() {
+  var d = confuse(jsFunctionAsNamedClass);
+  Expect.equals('F', d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.equals('F', d('Fosse'));
+
+  d = confuse(jsObjectAsNamedClass);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+
+  d = confuse(jsClassAsNamedClass);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.throws(() => (d.call)('Fosse'), jsThisIsNullCheck);
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+}
diff --git a/tests/lib/js/call_getter_test.dart b/tests/lib/js/call_getter_test.dart
new file mode 100644
index 0000000..d52853a
--- /dev/null
+++ b/tests/lib/js/call_getter_test.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2024, 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.
+
+/// WARNING
+///
+/// Not all of the expectations in this test match the language specification.
+///
+/// This is part of a set of tests covering "callable objects". Please consider
+/// them all together when making changes:
+///
+/// ```
+/// tests/lib/js/call_field_test.dart
+/// tests/lib/js/call_getter_test.dart
+/// tests/lib/js/call_method_test.dart
+/// ```
+///
+/// This test was created with expectations that match the current behavior to
+/// make it more clear when something changes and when the results in the web
+/// compilers differ.
+///
+/// If your change causes an expectation to fail you should decide if the
+/// new result is desireable and update the expectation accordingly.
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+import 'call_utils.dart';
+
+@JS()
+class NamedClass {
+  external int Function(String s) get call;
+}
+
+@JS('jsFunction')
+external NamedClass get jsFunctionAsNamedClass;
+
+@JS('jsObject')
+external NamedClass get jsObjectAsNamedClass;
+
+@JS('jsClass')
+external NamedClass get jsClassAsNamedClass;
+
+@JS()
+class NamedClass2 {
+  external Function get call;
+}
+
+@JS('jsFunction')
+external NamedClass2 get functionAsNamedClass2;
+
+@JS('jsObject')
+external NamedClass2 get jsObjectAsNamedClass2;
+
+@JS('jsClass')
+external NamedClass2 get jsClassAsNamedClass2;
+
+@JS()
+@anonymous
+class SomeClass {
+  external int Function(String s) get call;
+}
+
+@JS('jsFunction')
+external SomeClass get functionAsSomeClass;
+
+@JS('jsObject')
+external SomeClass get jsObjectAsSomeClass;
+
+@JS('jsClass')
+external SomeClass get jsClassAsSomeClass;
+
+@JS()
+@anonymous
+class SomeClass2 {
+  external Function get call;
+}
+
+@JS('jsFunction')
+external SomeClass2 get functionAsSomeClass2;
+
+@JS('jsObject')
+external SomeClass2 get jsObjectAsSomeClass2;
+
+@JS('jsClass')
+external SomeClass2 get jsClassAsSomeClass2;
+
+void main() {
+  injectJS();
+  testNamedClass();
+  testNamedClass2();
+  testAnonymous();
+  testAnonymous2();
+  testDynamic();
+}
+
+void testNamedClass() {
+  var obj = jsFunctionAsNamedClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testNamedClass2() {
+  var obj = functionAsNamedClass2;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsNamedClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsNamedClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testAnonymous() {
+  var obj = functionAsSomeClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testAnonymous2() {
+  var obj = functionAsSomeClass2;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+
+  obj = jsObjectAsSomeClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+
+  obj = jsClassAsSomeClass2;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+}
+
+void testDynamic() {
+  var d = confuse(jsFunctionAsNamedClass);
+  Expect.equals('F', d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.equals('F', d('Fosse'));
+
+  d = confuse(jsObjectAsNamedClass);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+
+  d = confuse(jsClassAsNamedClass);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.throws(() => (d.call)('Fosse'), jsThisIsNullCheck);
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+}
diff --git a/tests/lib/js/call_method_test.dart b/tests/lib/js/call_method_test.dart
new file mode 100644
index 0000000..cf31eaf
--- /dev/null
+++ b/tests/lib/js/call_method_test.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2024, 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.
+
+/// WARNING
+///
+/// Not all of the expectations in this test match the language specification.
+///
+/// This is part of a set of tests covering "callable objects". Please consider
+/// them all together when making changes:
+///
+/// ```
+/// tests/lib/js/call_field_test.dart
+/// tests/lib/js/call_getter_test.dart
+/// tests/lib/js/call_method_test.dart
+/// ```
+///
+/// This test was created with expectations that match the current behavior to
+/// make it more clear when something changes and when the results in the web
+/// compilers differ.
+///
+/// If your change causes an expectation to fail you should decide if the
+/// new result is desireable and update the expectation accordingly.
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+import 'call_utils.dart';
+
+@JS('jsFunction')
+external int Function(String) jsFunctionAsFunction;
+
+@JS('jsObject')
+external int Function(String) jsObjectAsFunction;
+
+@JS('jsClass')
+external int Function(String) jsClassAsFunction;
+
+@JS('jsFunction')
+external Function jsFunctionAsFunctionInterface;
+
+@JS('jsObject')
+external Function jsObjectAsFunctionInterface;
+
+@JS('jsClass')
+external Function jsClassAsFunctionInterface;
+
+@JS()
+class NamedClass {
+  external int call(String s);
+}
+
+@JS('jsFunction')
+external NamedClass get functionAsNamedClass;
+
+@JS('jsObject')
+external NamedClass get jsObjectAsNamedClass;
+
+@JS('jsClass')
+external NamedClass get jsClassAsNamedClass;
+
+@JS()
+@anonymous
+class SomeClass {
+  external int call(String s);
+}
+
+@JS('jsFunction')
+external SomeClass get functionAsSomeClass;
+
+@JS('jsObject')
+external SomeClass get jsObjectAsSomeClass;
+
+@JS('jsClass')
+external SomeClass get jsClassAsSomeClass;
+
+void main() {
+  injectJS();
+  testFunction();
+  testFunctionInterface();
+  testNamedClass();
+  testAnonymous();
+  testDynamic();
+}
+
+void testFunction() {
+  var obj = jsFunctionAsFunction;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+  Expect.equals('C', obj('Cello'));
+
+  obj = jsObjectAsFunction;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+
+  obj = jsClassAsFunction;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+}
+
+void testFunctionInterface() {
+  var obj = jsFunctionAsFunctionInterface;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+  Expect.equals('C', obj('Cello'));
+
+  obj = jsObjectAsFunctionInterface;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+
+  obj = jsClassAsFunctionInterface;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throws(() => (obj.call)('Cello'), jsThisIsNullCheck);
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+}
+
+void testNamedClass() {
+  var obj = functionAsNamedClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+  Expect.equals('C', obj('Cello'));
+
+  obj = jsObjectAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+
+  obj = jsClassAsNamedClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => (obj.call));
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+}
+
+void testAnonymous() {
+  var obj = functionAsSomeClass;
+  Expect.equals('C', obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.equals('C', (obj.call)('Cello'));
+  }
+  Expect.equals('C', obj('Cello'));
+
+  obj = jsObjectAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+
+  obj = jsClassAsSomeClass;
+  Expect.throwsNoSuchMethodError(() => obj.call('Cello'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => obj.call);
+  } else {
+    Expect.throwsNoSuchMethodError(() => (obj.call)('Cello'));
+  }
+  Expect.throwsNoSuchMethodError(() => obj('Cello'));
+}
+
+void testDynamic() {
+  var d = confuse(jsFunctionAsFunction);
+  Expect.equals('F', d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.equals('F', d('Fosse'));
+
+  d = confuse(jsClassAsFunction);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.throws(() => (d.call)('Fosse'), jsThisIsNullCheck);
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+
+  d = confuse(jsObjectAsFunction);
+  Expect.throwsNoSuchMethodError(() => d.call('Fosse'));
+  if (dart2js) {
+    Expect.throwsNoSuchMethodError(() => d.call);
+  } else {
+    Expect.equals('F', (d.call)('Fosse'));
+  }
+  Expect.throwsNoSuchMethodError(() => d('Fosse'));
+}
diff --git a/tests/lib/js/call_utils.dart b/tests/lib/js/call_utils.dart
new file mode 100644
index 0000000..97454af
--- /dev/null
+++ b/tests/lib/js/call_utils.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2024, 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:js/js.dart';
+
+const dart2js = const bool.fromEnvironment('dart.library._dart2js_only');
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+dynamic confuse(dynamic x) => x;
+
+@JS()
+external dynamic eval(String script);
+
+void injectJS() {
+  eval(
+    '''
+    self.jsFunction = function(s) {
+        if (this == null) {
+          throw "`this` is null or undefined";
+        }
+        if (typeof s != 'string') {
+          throw "`s` is not a string";
+        }
+        return s.at(0);
+      };
+    self.jsObject = { call: function(s) {
+        if (this == null) {
+          throw "`this` is null or undefined";
+        }
+        if (typeof s != 'string') {
+          throw "`s` is not a string";
+        }
+        return s.at(0);
+      } };
+    self.NamedClass = class NamedClass {
+      call(s) {
+        if (this == null) {
+          throw "`this` is null or undefined";
+        }
+        if (typeof s != 'string') {
+          throw "`s` is not a string";
+        }
+        return s.at(0);
+      }
+    }
+    self.jsClass = new NamedClass();
+    ''',
+  );
+}
+
+bool jsThisIsNullCheck(e) =>
+    e.toString().contains('`this` is null or undefined');
+
+bool jsArgIsNotStringCheck(e) => e.toString().contains('`s` is not a string');
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index fc812a2..b54fa9d 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -61,6 +61,9 @@
 [ $csp ]
 html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
 isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+js/call_field_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/call_getter_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/call_method_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/extends_test/extends_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/extends_test/extends_with_es6_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code