[js_runtime] Test for JavaScriptFunction type tests.

- Add test for JavaScriptFunction type tests
- Make toString() for JavaScriptFunction more explicit.

Change-Id: I60042b909709c822c924336fd4973f35dc7f779a
Reviewed-on: https://dart-review.googlesource.com/58062
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index 7221968..0a2baed 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
@@ -485,6 +485,7 @@
 
   String toString() {
     var dartClosure = JS('', '#.#', this, DART_CLOSURE_PROPERTY_NAME);
-    return dartClosure == null ? super.toString() : dartClosure.toString();
+    if (dartClosure == null) return super.toString();
+    return 'JavaScript function for ${dartClosure.toString()}';
   }
 }
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index e0aedb9..5f39637 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -88,7 +88,11 @@
 
 import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
 import 'dart:_interceptors'
-    show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
+    show
+        JavaScriptFunction,
+        JavaScriptObject,
+        UnknownJavaScriptObject,
+        DART_CLOSURE_PROPERTY_NAME;
 import 'dart:_js_helper'
     show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
 import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
@@ -99,7 +103,7 @@
 
 _convertDartFunction(Function f, {bool captureThis: false}) {
   return JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f, captureThis) {
           return function() {
@@ -652,7 +656,7 @@
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
   if (existing != null) return existing;
   var ret = JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f) {
           return function() {
@@ -671,7 +675,7 @@
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS);
   if (existing != null) return existing;
   var ret = JS(
-      '',
+      'JavaScriptFunction',
       '''
         function(_call, f) {
           return function() {
diff --git a/tests/compiler/dart2js_extra/33296_test.dart b/tests/compiler/dart2js_extra/33296_test.dart
new file mode 100644
index 0000000..7d06619
--- /dev/null
+++ b/tests/compiler/dart2js_extra/33296_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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 'dart:js';
+import 'dart:html'; // TODO(33316): Remove.
+import "package:expect/expect.dart";
+
+main() {
+  var f = () => [];
+  Expect.isTrue(f is List Function());
+  Expect.isFalse(f is int Function(int));
+
+  var g = allowInterop(f);
+  // g is inferred to have the same type as f.
+  Expect.isTrue(g is List Function());
+  // The JavaScriptFunction matches any function type.
+  Expect.isTrue(g is int Function(int));
+
+  if (false) new DivElement(); // TODO(33316): Remove.
+}