OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library _js_helper; | 5 library _js_helper; |
6 | 6 |
7 import 'dart:_js_embedded_names' show | 7 import 'dart:_js_embedded_names' show |
8 DEFERRED_LIBRARY_URIS, | 8 DEFERRED_LIBRARY_URIS, |
9 DEFERRED_LIBRARY_HASHES, | 9 DEFERRED_LIBRARY_HASHES, |
10 GET_TYPE_FROM_NAME, | 10 GET_TYPE_FROM_NAME, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 DART_CLOSURE_TO_JS, | 42 DART_CLOSURE_TO_JS, |
43 JS, | 43 JS, |
44 JS_BUILTIN, | 44 JS_BUILTIN, |
45 JS_CALL_IN_ISOLATE, | 45 JS_CALL_IN_ISOLATE, |
46 JS_CONST, | 46 JS_CONST, |
47 JS_CURRENT_ISOLATE_CONTEXT, | 47 JS_CURRENT_ISOLATE_CONTEXT, |
48 JS_EFFECT, | 48 JS_EFFECT, |
49 JS_EMBEDDED_GLOBAL, | 49 JS_EMBEDDED_GLOBAL, |
50 JS_GET_FLAG, | 50 JS_GET_FLAG, |
51 JS_GET_NAME, | 51 JS_GET_NAME, |
| 52 JS_INTERCEPTOR_CONSTANT, |
52 JS_STRING_CONCAT, | 53 JS_STRING_CONCAT, |
53 RAW_DART_FUNCTION_REF; | 54 RAW_DART_FUNCTION_REF; |
54 | 55 |
55 import 'dart:_interceptors'; | 56 import 'dart:_interceptors'; |
56 import 'dart:_internal' as _symbol_dev; | 57 import 'dart:_internal' as _symbol_dev; |
57 import 'dart:_internal' show | 58 import 'dart:_internal' show |
58 EfficientLength, | 59 EfficientLength, |
59 MappedIterable, | 60 MappedIterable, |
60 IterableElementError; | 61 IterableElementError; |
61 | 62 |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 /// constructor of the given class. | 839 /// constructor of the given class. |
839 static String formatType(String className, List typeArguments) { | 840 static String formatType(String className, List typeArguments) { |
840 return unmangleAllIdentifiersIfPreservedAnyways | 841 return unmangleAllIdentifiersIfPreservedAnyways |
841 ('$className${joinArguments(typeArguments, 0)}'); | 842 ('$className${joinArguments(typeArguments, 0)}'); |
842 } | 843 } |
843 | 844 |
844 /// Returns the type of [object] as a string (including type arguments). | 845 /// Returns the type of [object] as a string (including type arguments). |
845 /// | 846 /// |
846 /// In minified mode, uses the unminified names if available. | 847 /// In minified mode, uses the unminified names if available. |
847 static String objectTypeName(Object object) { | 848 static String objectTypeName(Object object) { |
848 String name = constructorNameFallback(getInterceptor(object)); | 849 return formatType(_objectRawTypeName(object), getRuntimeTypeInfo(object)); |
849 if (name == 'Object') { | 850 } |
850 // Try to decompile the constructor by turning it into a string and get | 851 |
851 // the name out of that. If the decompiled name is a string containing an | 852 static String _objectRawTypeName(Object object) { |
852 // identifier, we use that instead of the very generic 'Object'. | 853 var interceptor = getInterceptor(object); |
853 var decompiled = | 854 // The interceptor is either an object (self-intercepting plain Dart class), |
854 JS('var', r'#.match(/^\s*function\s*([\w$]*)\s*\(/)[1]', | 855 // the prototype of the constructor for an Interceptor class (like |
855 JS('var', r'String(#.constructor)', object)); | 856 // `JSString.prototype`, `JSNull.prototype`), or an Interceptor object |
856 if (decompiled is String) | 857 // instance (`const JSString()`, should use `JSString.prototype`). |
857 if (JS('bool', r'/^\w+$/.test(#)', decompiled)) | 858 // |
858 name = decompiled; | 859 // These all should have a `constructor` property with a `name` property. |
| 860 String name; |
| 861 var interceptorConstructor = JS('', '#.constructor', interceptor); |
| 862 if (JS('bool', 'typeof # == "function"', interceptorConstructor)) { |
| 863 var interceptorConstructorName = JS('', '#.name', interceptorConstructor); |
| 864 if (interceptorConstructorName is String) { |
| 865 name = interceptorConstructorName; |
| 866 } |
859 } | 867 } |
| 868 |
| 869 if (name == null || |
| 870 identical(interceptor, |
| 871 JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject)) || |
| 872 identical(interceptor, JS_INTERCEPTOR_CONSTANT(Interceptor))) { |
| 873 // Try to do better. If we do not find something better, leave the name |
| 874 // as 'UnknownJavaScriptObject' or 'Interceptor' (or the minified name). |
| 875 // |
| 876 // When we get here via the UnknownJavaScriptObject test (for JavaScript |
| 877 // objects from outside the program), the object's constructor has a |
| 878 // better name that 'UnknownJavaScriptObject'. |
| 879 // |
| 880 // When we get here the Interceptor test (for Native classes that are |
| 881 // declared in the Dart program but have been 'folded' into Interceptor), |
| 882 // the native class's constructor name is better than the generic |
| 883 // 'Interceptor' (an abstract class). |
| 884 |
| 885 // Try the [constructorNameFallback]. This gets the constructor name for |
| 886 // any browser (used by [getNativeInterceptor]). |
| 887 String dispatchName = constructorNameFallback(object); |
| 888 if (name == null) name = dispatchName; |
| 889 if (dispatchName == 'Object') { |
| 890 // Try to decompile the constructor by turning it into a string and get |
| 891 // the name out of that. If the decompiled name is a string containing |
| 892 // an identifier, we use that instead of the very generic 'Object'. |
| 893 var objectConstructor = JS('', '#.constructor', object); |
| 894 if (JS('bool', 'typeof # == "function"', objectConstructor)) { |
| 895 var decompiledName = |
| 896 JS('var', r'#.match(/^\s*function\s*([\w$]*)\s*\(/)[1]', |
| 897 JS('var', r'String(#)', objectConstructor)); |
| 898 if (decompiledName is String && |
| 899 JS('bool', r'/^\w+$/.test(#)', decompiledName)) { |
| 900 name = decompiledName; |
| 901 } |
| 902 } |
| 903 } else { |
| 904 name = dispatchName; |
| 905 } |
| 906 } |
| 907 |
860 // TODO(kasperl): If the namer gave us a fresh global name, we may | 908 // TODO(kasperl): If the namer gave us a fresh global name, we may |
861 // want to remove the numeric suffix that makes it unique too. | 909 // want to remove the numeric suffix that makes it unique too. |
862 if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { | 910 if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { |
863 name = name.substring(1); | 911 name = name.substring(1); |
864 } | 912 } |
865 return formatType(name, getRuntimeTypeInfo(object)); | 913 return name; |
866 } | 914 } |
867 | 915 |
868 /// In minified mode, uses the unminified names if available. | 916 /// In minified mode, uses the unminified names if available. |
869 static String objectToHumanReadableString(Object object) { | 917 static String objectToHumanReadableString(Object object) { |
870 String name = objectTypeName(object); | 918 String name = objectTypeName(object); |
871 return "Instance of '$name'"; | 919 return "Instance of '$name'"; |
872 } | 920 } |
873 | 921 |
874 static num dateNow() => JS('int', r'Date.now()'); | 922 static num dateNow() => JS('int', r'Date.now()'); |
875 | 923 |
(...skipping 3145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4021 // unneeded code. | 4069 // unneeded code. |
4022 class _UnreachableError extends AssertionError { | 4070 class _UnreachableError extends AssertionError { |
4023 _UnreachableError(); | 4071 _UnreachableError(); |
4024 String toString() => "Assertion failed: Reached dead code"; | 4072 String toString() => "Assertion failed: Reached dead code"; |
4025 } | 4073 } |
4026 | 4074 |
4027 @NoInline() | 4075 @NoInline() |
4028 void assertUnreachable() { | 4076 void assertUnreachable() { |
4029 throw new _UnreachableError(); | 4077 throw new _UnreachableError(); |
4030 } | 4078 } |
OLD | NEW |