Index: sdk/lib/_internal/js_runtime/lib/interceptors.dart |
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
index 0247af4ab45094c9af83d02c647d4dfd7e6c0c48..f33014076b6750a86588291358277a199b998114 100644 |
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
@@ -22,6 +22,7 @@ import 'dart:_js_helper' show allMatchesInStringUnchecked, |
checkString, |
defineProperty, |
diagnoseIndexError, |
+ getIsolateAffinityTag, |
getRuntimeType, |
initNativeDispatch, |
initNativeDispatchFlag, |
@@ -40,6 +41,8 @@ import 'dart:_js_helper' show allMatchesInStringUnchecked, |
StringMatch, |
firstMatchAfter, |
NoInline; |
+import 'dart:js' show JsNative; |
+ |
import 'dart:_foreign_helper' show |
JS, |
JS_EFFECT, |
@@ -52,6 +55,9 @@ part 'js_array.dart'; |
part 'js_number.dart'; |
part 'js_string.dart'; |
+final String DART_CLOSURE_PROPERTY_NAME = |
+ getIsolateAffinityTag(r'_$dart_dartClosure'); |
+ |
String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); |
_symbolMapToStringMap(Map<Symbol, dynamic> map) { |
@@ -170,6 +176,9 @@ getNativeInterceptor(object) { |
// are 'plain' Objects. This test could be simplified and the dispatch path |
// be faster if Object.prototype was pre-patched with a non-leaf dispatch |
// record. |
+ if (JS('bool', 'typeof # == "function"', object)) { |
+ return JS_INTERCEPTOR_CONSTANT(JavaScriptFunction); |
+ } |
var proto = JS('', 'Object.getPrototypeOf(#)', object); |
if (JS('bool', '# == null || # === Object.prototype', proto, proto)) { |
return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject); |
@@ -394,13 +403,24 @@ abstract class JSObject { |
* Interceptor base class for JavaScript objects not recognized as some more |
* specific native type. |
*/ |
-abstract class JavaScriptObject extends Interceptor implements JSObject { |
+class JavaScriptObject extends Interceptor implements JSObject { |
const JavaScriptObject(); |
// It would be impolite to stash a property on the object. |
int get hashCode => 0; |
Type get runtimeType => JSObject; |
+ |
+ /** |
+ * Returns the result of the JavaScript objects `toString` method. |
+ */ |
+ String toString() { |
+ try { |
+ return JS('String', 'String(#)', this); |
+ } catch(e) { |
+ return super.toString(); |
+ } |
+ } |
} |
@@ -424,3 +444,18 @@ class UnknownJavaScriptObject extends JavaScriptObject { |
String toString() => JS('String', 'String(#)', this); |
} |
+ |
+/** |
+ * Interceptor for JavaScript function objects and Dart functions that have |
+ * been converted to JavaScript functions. |
+ * These interceptor methods are not always used as the JavaScript function |
+ * object has also been mangled to support Dart function calling conventions. |
+ */ |
+class JavaScriptFunction extends JavaScriptObject implements Function { |
+ const JavaScriptFunction(); |
+ |
+ String toString() { |
+ var dartClosure = JsNative.getProperty(this, DART_CLOSURE_PROPERTY_NAME); |
+ return dartClosure == null ? super.toString() : dartClosure.toString(); |
+ } |
+} |