Chromium Code Reviews| Index: sdk/lib/_internal/js_runtime/lib/js_helper.dart |
| diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart |
| index 663121a605f99407676a7468c2bd6fe0ce0044ee..e5dfcac88de7d54c3e0b2b0ece5f29bca54d1232 100644 |
| --- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart |
| +++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart |
| @@ -49,6 +49,7 @@ import 'dart:_foreign_helper' show |
| JS_EMBEDDED_GLOBAL, |
| JS_GET_FLAG, |
| JS_GET_NAME, |
| + JS_INTERCEPTOR_CONSTANT, |
| JS_STRING_CONCAT, |
| RAW_DART_FUNCTION_REF; |
| @@ -845,24 +846,68 @@ class Primitives { |
| /// |
| /// In minified mode, uses the unminified names if available. |
| static String objectTypeName(Object object) { |
| - String name = constructorNameFallback(getInterceptor(object)); |
| - if (name == 'Object') { |
| - // Try to decompile the constructor by turning it into a string and get |
| - // the name out of that. If the decompiled name is a string containing an |
| - // identifier, we use that instead of the very generic 'Object'. |
| - var decompiled = |
| - JS('var', r'#.match(/^\s*function\s*([\w$]*)\s*\(/)[1]', |
| - JS('var', r'String(#.constructor)', object)); |
| - if (decompiled is String) |
| - if (JS('bool', r'/^\w+$/.test(#)', decompiled)) |
| - name = decompiled; |
| + return formatType(_objectRawTypeName(object), getRuntimeTypeInfo(object)); |
| + } |
| + |
| + static String _objectRawTypeName(Object object) { |
| + var interceptor = getInterceptor(object); |
| + // The interceptor is either an object (self-intercepting plain Dart class), |
| + // the prototype of the constructor for an Interceptor class (like |
| + // `JSString.prototype`, `JSNull.prototype`), or an Interceptor object |
| + // instance (`const JSString()`, should use `JSString.prototype`). |
| + // |
| + // These all should have a `constructor` property with a `name` property. |
| + String name; |
| + var interceptorConstructor = JS('', '#.constructor', interceptor); |
| + if (JS('bool', 'typeof # == "function"', interceptorConstructor)) { |
| + var interceptorConstructorName = JS('', '#.name', interceptorConstructor); |
| + if (interceptorConstructorName is String) { |
| + name = interceptorConstructorName; |
| + } |
| } |
| + |
| + if (name == null || |
| + identical(interceptor, |
| + JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject)) || |
| + identical(interceptor, JS_INTERCEPTOR_CONSTANT(Interceptor))) { |
| + // Try to do better. If we do not find something better, leave the name |
| + // as 'UnknownJavaScriptObject' or 'Interceptor' (or the minified name). |
| + // |
| + // We get here via the UnknownJavaScriptObject test for JavaScript objects |
|
Siggi Cherem (dart-lang)
2015/09/22 16:51:23
We get here ... The object's
=>
If we get here
sra1
2015/09/23 03:58:21
Acknowledged.
|
| + // from outside the program. The object's constructor has a better name. |
| + // |
| + // We get here the Interceptor test for Native classes that are declared |
|
Siggi Cherem (dart-lang)
2015/09/22 16:51:23
We get here the ... The native
=>
If we get here
sra1
2015/09/23 03:58:21
Acknowledged.
|
| + // in the Dart program but have been 'folded' into Interceptor. The |
| + // native class's constructor name is better than the generic |
| + // 'Interceptor' (an abstract class). |
| + |
| + // Try the [constructorNameFallback]. This gets the constructor name for |
| + // any browser (used by [getNativeInterceptor]). |
| + String dispatchName = constructorNameFallback(object); |
| + if (name == null) name = dispatchName; |
| + if (dispatchName == 'Object') { |
| + // Try to decompile the constructor by turning it into a string and get |
| + // the name out of that. If the decompiled name is a string containing |
| + // an identifier, we use that instead of the very generic 'Object'. |
| + var objectConstructor = JS('', '#.constructor', object); |
| + if (JS('bool', 'typeof # == "function"', objectConstructor)) { |
| + var decompiledName = |
| + JS('var', r'#.match(/^\s*function\s*([\w$]*)\s*\(/)[1]', |
| + JS('var', r'String(#)', objectConstructor)); |
| + if (decompiledName is String && |
| + JS('bool', r'/^\w+$/.test(#)', decompiledName)) { |
| + name = decompiledName; |
| + } |
| + } |
| + } |
| + } |
| + |
| // TODO(kasperl): If the namer gave us a fresh global name, we may |
| // want to remove the numeric suffix that makes it unique too. |
| if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { |
| name = name.substring(1); |
| } |
| - return formatType(name, getRuntimeTypeInfo(object)); |
| + return name; |
| } |
| /// In minified mode, uses the unminified names if available. |