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:_async_await_error_codes' as async_error_codes; | 7 import 'dart:_async_await_error_codes' as async_error_codes; |
8 | 8 |
9 import 'dart:_js_embedded_names' show | 9 import 'dart:_js_embedded_names' show |
10 DEFERRED_LIBRARY_URIS, | 10 DEFERRED_LIBRARY_URIS, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 part 'regexp_helper.dart'; | 80 part 'regexp_helper.dart'; |
81 part 'string_helper.dart'; | 81 part 'string_helper.dart'; |
82 part 'js_rti.dart'; | 82 part 'js_rti.dart'; |
83 part 'linked_hash_map.dart'; | 83 part 'linked_hash_map.dart'; |
84 | 84 |
85 /// Marks the internal map in dart2js, so that internal libraries can is-check | 85 /// Marks the internal map in dart2js, so that internal libraries can is-check |
86 /// them. | 86 /// them. |
87 abstract class InternalMap { | 87 abstract class InternalMap { |
88 } | 88 } |
89 | 89 |
90 /// Extracts the classname from the isCheckProperty. | 90 /// Extracts the JavaScript-constructor name from the given isCheckProperty. |
91 // TODO(floitsch): move this to foreign_helper.dart or similar. | 91 // TODO(floitsch): move this to foreign_helper.dart or similar. |
92 @ForceInline() | 92 @ForceInline() |
93 String classNameFromIsCheckProperty(String isCheckProperty) { | 93 String isCheckPropertyToJsConstructorName(String isCheckProperty) { |
94 return JS_BUILTIN('returns:String;depends:none;effects:none', | 94 return JS_BUILTIN('returns:String;depends:none;effects:none', |
95 JsBuiltin.classNameFromIsCheckProperty, | 95 JsBuiltin.isCheckPropertyToJsConstructorName, |
96 isCheckProperty); | 96 isCheckProperty); |
97 } | 97 } |
98 | 98 |
99 /// Returns true if the given [type] is a function type object. | 99 /// Returns true if the given [type] is a function type object. |
100 // TODO(floitsch): move this to foreign_helper.dart or similar. | 100 // TODO(floitsch): move this to foreign_helper.dart or similar. |
101 @ForceInline() | 101 @ForceInline() |
102 bool isDartFunctionType(Object type) { | 102 bool isDartFunctionType(Object type) { |
103 return JS_BUILTIN('returns:bool;effects:none;depends:none', | 103 return JS_BUILTIN('returns:bool;effects:none;depends:none', |
104 JsBuiltin.isFunctionType, type); | 104 JsBuiltin.isFunctionType, type); |
105 } | 105 } |
106 | 106 |
107 | 107 |
108 /// Creates a function type object. | 108 /// Creates a function type object. |
109 // TODO(floitsch): move this to foreign_helper.dart or similar. | 109 // TODO(floitsch): move this to foreign_helper.dart or similar. |
110 @ForceInline() | 110 @ForceInline() |
111 createDartFunctionType() { | 111 createDartFunctionTypeRti() { |
112 return JS_BUILTIN('returns:=Object;effects:none;depends:none', | 112 return JS_BUILTIN('returns:=Object;effects:none;depends:none', |
113 JsBuiltin.createFunctionType); | 113 JsBuiltin.createFunctionTypeRti); |
114 } | 114 } |
115 | 115 |
116 /// Retrieves the class name from type information stored on the constructor of | 116 /// Retrieves the class name from type information stored on the constructor of |
117 /// [type]. | 117 /// [type]. |
118 // TODO(floitsch): move this to foreign_helper.dart or similar. | 118 // TODO(floitsch): move this to foreign_helper.dart or similar. |
119 @ForceInline() | 119 @ForceInline() |
120 String getDartTypeName(Object type) { | 120 String rawRtiToJsConstructorName(Object rti) { |
121 return JS_BUILTIN('String', JsBuiltin.typeName, type); | 121 return JS_BUILTIN('String', JsBuiltin.rawRtiToJsConstructorName, rti); |
| 122 } |
| 123 |
| 124 /// Returns the rti from the given [constructorName]. |
| 125 // TODO(floitsch): make this a builtin. |
| 126 jsConstructorNameToRti(String constructorName) { |
| 127 var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME); |
| 128 return JS('', '#(#)', getTypeFromName, constructorName); |
122 } | 129 } |
123 | 130 |
124 /// Returns the raw runtime type of the given object [o]. | 131 /// Returns the raw runtime type of the given object [o]. |
125 /// | 132 /// |
126 /// The argument [o] must be the interceptor for primitive types. If | 133 /// The argument [o] must be the interceptor for primitive types. If |
127 /// necessary run it through [getInterceptor] first. | 134 /// necessary run it through [getInterceptor] first. |
128 // TODO(floitsch): move this to foreign_helper.dart or similar. | 135 // TODO(floitsch): move this to foreign_helper.dart or similar. |
129 // TODO(floitsch): we should call getInterceptor ourselves, but currently | 136 // TODO(floitsch): we should call getInterceptor ourselves, but currently |
130 // getInterceptor is not GVNed. | 137 // getInterceptor is not GVNed. |
131 @ForceInline() | 138 @ForceInline() |
(...skipping 29 matching lines...) Expand all Loading... |
161 | 168 |
162 /// Returns whether the given type is _the_ null type. | 169 /// Returns whether the given type is _the_ null type. |
163 // TODO(floitsch): move this to foreign_helper.dart or similar. | 170 // TODO(floitsch): move this to foreign_helper.dart or similar. |
164 @ForceInline() | 171 @ForceInline() |
165 bool isNullTypeRti(type) { | 172 bool isNullTypeRti(type) { |
166 return JS_BUILTIN('returns:bool;effects:none;depends:none', | 173 return JS_BUILTIN('returns:bool;effects:none;depends:none', |
167 JsBuiltin.isNullTypeRti, type); | 174 JsBuiltin.isNullTypeRti, type); |
168 } | 175 } |
169 | 176 |
170 /// Returns the metadata of the given [index]. | 177 /// Returns the metadata of the given [index]. |
| 178 // TODO(floitsch): move this to foreign_helper.dart or similar. |
171 @ForceInline() | 179 @ForceInline() |
172 getMetadata(int index) { | 180 getMetadata(int index) { |
173 return JS_BUILTIN('returns:var;effects:none;depends:none', | 181 return JS_BUILTIN('returns:var;effects:none;depends:none', |
174 JsBuiltin.getMetadata, index); | 182 JsBuiltin.getMetadata, index); |
175 } | 183 } |
176 | 184 |
177 /// Returns the type of the given [index]. | 185 /// Returns the type of the given [index]. |
| 186 // TODO(floitsch): move this to foreign_helper.dart or similar. |
178 @ForceInline() | 187 @ForceInline() |
179 getType(int index) { | 188 getType(int index) { |
180 return JS_BUILTIN('returns:var;effects:none;depends:none', | 189 return JS_BUILTIN('returns:var;effects:none;depends:none', |
181 JsBuiltin.getType, index); | 190 JsBuiltin.getType, index); |
182 } | 191 } |
183 | 192 |
184 /// No-op method that is called to inform the compiler that preambles might | 193 /// No-op method that is called to inform the compiler that preambles might |
185 /// be needed when executing the resulting JS file in a command-line | 194 /// be needed when executing the resulting JS file in a command-line |
186 /// JS engine. | 195 /// JS engine. |
187 requiresPreamble() {} | 196 requiresPreamble() {} |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 return result; | 793 return result; |
785 } | 794 } |
786 | 795 |
787 /** [: r"$".codeUnitAt(0) :] */ | 796 /** [: r"$".codeUnitAt(0) :] */ |
788 static const int DOLLAR_CHAR_VALUE = 36; | 797 static const int DOLLAR_CHAR_VALUE = 36; |
789 | 798 |
790 /// Creates a string containing the complete type for the class [className] | 799 /// Creates a string containing the complete type for the class [className] |
791 /// with the given type arguments. | 800 /// with the given type arguments. |
792 /// | 801 /// |
793 /// In minified mode, uses the unminified names if available. | 802 /// In minified mode, uses the unminified names if available. |
| 803 /// |
| 804 /// The given [className] string generally contains the name of the JavaScript |
| 805 /// constructor of the given class. |
794 static String formatType(String className, List typeArguments) { | 806 static String formatType(String className, List typeArguments) { |
795 return unmangleAllIdentifiersIfPreservedAnyways | 807 return unmangleAllIdentifiersIfPreservedAnyways |
796 ('$className${joinArguments(typeArguments, 0)}'); | 808 ('$className${joinArguments(typeArguments, 0)}'); |
797 } | 809 } |
798 | 810 |
799 /// Returns the type of [object] as a string (including type arguments). | 811 /// Returns the type of [object] as a string (including type arguments). |
800 /// | 812 /// |
801 /// In minified mode, uses the unminified names if available. | 813 /// In minified mode, uses the unminified names if available. |
802 static String objectTypeName(Object object) { | 814 static String objectTypeName(Object object) { |
803 String name = constructorNameFallback(getInterceptor(object)); | 815 String name = constructorNameFallback(getInterceptor(object)); |
(...skipping 10 matching lines...) Expand all Loading... |
814 } | 826 } |
815 // TODO(kasperl): If the namer gave us a fresh global name, we may | 827 // TODO(kasperl): If the namer gave us a fresh global name, we may |
816 // want to remove the numeric suffix that makes it unique too. | 828 // want to remove the numeric suffix that makes it unique too. |
817 if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { | 829 if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { |
818 name = name.substring(1); | 830 name = name.substring(1); |
819 } | 831 } |
820 return formatType(name, getRuntimeTypeInfo(object)); | 832 return formatType(name, getRuntimeTypeInfo(object)); |
821 } | 833 } |
822 | 834 |
823 /// In minified mode, uses the unminified names if available. | 835 /// In minified mode, uses the unminified names if available. |
824 static String objectToString(Object object) { | 836 static String objectToHumanReadableString(Object object) { |
825 String name = objectTypeName(object); | 837 String name = objectTypeName(object); |
826 return "Instance of '$name'"; | 838 return "Instance of '$name'"; |
827 } | 839 } |
828 | 840 |
829 static num dateNow() => JS('int', r'Date.now()'); | 841 static num dateNow() => JS('int', r'Date.now()'); |
830 | 842 |
831 static void initTicker() { | 843 static void initTicker() { |
832 if (timerFrequency != null) return; | 844 if (timerFrequency != null) return; |
833 // Start with low-resolution. We overwrite the fields if we find better. | 845 // Start with low-resolution. We overwrite the fields if we find better. |
834 timerFrequency = 1000; | 846 timerFrequency = 1000; |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1338 } | 1350 } |
1339 }); | 1351 }); |
1340 if (bad) { | 1352 if (bad) { |
1341 return functionNoSuchMethod( | 1353 return functionNoSuchMethod( |
1342 function, positionalArguments, namedArguments); | 1354 function, positionalArguments, namedArguments); |
1343 } | 1355 } |
1344 positionalArguments.addAll(defaultArguments.values); | 1356 positionalArguments.addAll(defaultArguments.values); |
1345 return JS('', '#.apply(#, #)', jsFunction, function, positionalArguments); | 1357 return JS('', '#.apply(#, #)', jsFunction, function, positionalArguments); |
1346 } | 1358 } |
1347 | 1359 |
1348 static _mangledNameMatchesType(String mangledName, TypeImpl type) { | |
1349 return JS('bool', '# == #', mangledName, type._typeName); | |
1350 } | |
1351 | |
1352 static bool identicalImplementation(a, b) { | 1360 static bool identicalImplementation(a, b) { |
1353 return JS('bool', '# == null', a) | 1361 return JS('bool', '# == null', a) |
1354 ? JS('bool', '# == null', b) | 1362 ? JS('bool', '# == null', b) |
1355 : JS('bool', '# === #', a, b); | 1363 : JS('bool', '# === #', a, b); |
1356 } | 1364 } |
1357 | 1365 |
1358 static StackTrace extractStackTrace(Error error) { | 1366 static StackTrace extractStackTrace(Error error) { |
1359 return getTraceFromException(JS('', r'#.$thrownJsError', error)); | 1367 return getTraceFromException(JS('', r'#.$thrownJsError', error)); |
1360 } | 1368 } |
1361 } | 1369 } |
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 return saveStackTrace( | 1973 return saveStackTrace( |
1966 new NullError('$message (Error $ieErrorCode)', null)); | 1974 new NullError('$message (Error $ieErrorCode)', null)); |
1967 } | 1975 } |
1968 } | 1976 } |
1969 } | 1977 } |
1970 | 1978 |
1971 if (JS('bool', r'# instanceof TypeError', ex)) { | 1979 if (JS('bool', r'# instanceof TypeError', ex)) { |
1972 var match; | 1980 var match; |
1973 // Using JS to give type hints to the compiler to help tree-shaking. | 1981 // Using JS to give type hints to the compiler to help tree-shaking. |
1974 // TODO(ahe): That should be unnecessary due to type inference. | 1982 // TODO(ahe): That should be unnecessary due to type inference. |
1975 var nsme = | 1983 var nsme = TypeErrorDecoder.noSuchMethodPattern; |
1976 JS('TypeErrorDecoder', '#', TypeErrorDecoder.noSuchMethodPattern); | 1984 var notClosure = TypeErrorDecoder.notClosurePattern; |
1977 var notClosure = | 1985 var nullCall = TypeErrorDecoder.nullCallPattern; |
1978 JS('TypeErrorDecoder', '#', TypeErrorDecoder.notClosurePattern); | 1986 var nullLiteralCall = TypeErrorDecoder.nullLiteralCallPattern; |
1979 var nullCall = | 1987 var undefCall = TypeErrorDecoder.undefinedCallPattern; |
1980 JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullCallPattern); | 1988 var undefLiteralCall = TypeErrorDecoder.undefinedLiteralCallPattern; |
1981 var nullLiteralCall = | 1989 var nullProperty = TypeErrorDecoder.nullPropertyPattern; |
1982 JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullLiteralCallPattern); | 1990 var nullLiteralProperty = TypeErrorDecoder.nullLiteralPropertyPattern; |
1983 var undefCall = | 1991 var undefProperty = TypeErrorDecoder.undefinedPropertyPattern; |
1984 JS('TypeErrorDecoder', '#', TypeErrorDecoder.undefinedCallPattern); | |
1985 var undefLiteralCall = | |
1986 JS('TypeErrorDecoder', '#', | |
1987 TypeErrorDecoder.undefinedLiteralCallPattern); | |
1988 var nullProperty = | |
1989 JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullPropertyPattern); | |
1990 var nullLiteralProperty = | |
1991 JS('TypeErrorDecoder', '#', | |
1992 TypeErrorDecoder.nullLiteralPropertyPattern); | |
1993 var undefProperty = | |
1994 JS('TypeErrorDecoder', '#', TypeErrorDecoder.undefinedPropertyPattern); | |
1995 var undefLiteralProperty = | 1992 var undefLiteralProperty = |
1996 JS('TypeErrorDecoder', '#', | 1993 TypeErrorDecoder.undefinedLiteralPropertyPattern; |
1997 TypeErrorDecoder.undefinedLiteralPropertyPattern); | |
1998 if ((match = nsme.matchTypeError(message)) != null) { | 1994 if ((match = nsme.matchTypeError(message)) != null) { |
1999 return saveStackTrace(new JsNoSuchMethodError(message, match)); | 1995 return saveStackTrace(new JsNoSuchMethodError(message, match)); |
2000 } else if ((match = notClosure.matchTypeError(message)) != null) { | 1996 } else if ((match = notClosure.matchTypeError(message)) != null) { |
2001 // notClosure may match "({c:null}).c()" or "({c:1}).c()", so we | 1997 // notClosure may match "({c:null}).c()" or "({c:1}).c()", so we |
2002 // cannot tell if this an attempt to invoke call on null or a | 1998 // cannot tell if this an attempt to invoke call on null or a |
2003 // non-function object. | 1999 // non-function object. |
2004 // But we do know the method name is "call". | 2000 // But we do know the method name is "call". |
2005 JS('', '#.method = "call"', match); | 2001 JS('', '#.method = "call"', match); |
2006 return saveStackTrace(new JsNoSuchMethodError(message, match)); | 2002 return saveStackTrace(new JsNoSuchMethodError(message, match)); |
2007 } else if ((match = nullCall.matchTypeError(message)) != null || | 2003 } else if ((match = nullCall.matchTypeError(message)) != null || |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2209 BoundClosure.receiverOf(JS('BoundClosure', 'void 0')); | 2205 BoundClosure.receiverOf(JS('BoundClosure', 'void 0')); |
2210 BoundClosure.selfOf(JS('BoundClosure', 'void 0')); | 2206 BoundClosure.selfOf(JS('BoundClosure', 'void 0')); |
2211 }); | 2207 }); |
2212 // TODO(ahe): All the place below using \$ should be rewritten to go | 2208 // TODO(ahe): All the place below using \$ should be rewritten to go |
2213 // through the namer. | 2209 // through the namer. |
2214 var function = JS('', '#[#]', functions, 0); | 2210 var function = JS('', '#[#]', functions, 0); |
2215 String name = JS('String|Null', '#.\$stubName', function); | 2211 String name = JS('String|Null', '#.\$stubName', function); |
2216 String callName = JS('String|Null', '#[#]', function, | 2212 String callName = JS('String|Null', '#[#]', function, |
2217 JS_GET_NAME(JsGetName.CALL_NAME_PROPERTY)); | 2213 JS_GET_NAME(JsGetName.CALL_NAME_PROPERTY)); |
2218 | 2214 |
| 2215 // This variable holds either an index into the types-table, or a function |
| 2216 // that can compute a function-rti. (The latter is necessary if the type |
| 2217 // is dependent on generic arguments). |
2219 var functionType; | 2218 var functionType; |
2220 if (reflectionInfo is List) { | 2219 if (reflectionInfo is List) { |
2221 JS('', '#.\$reflectionInfo = #', function, reflectionInfo); | 2220 JS('', '#.\$reflectionInfo = #', function, reflectionInfo); |
2222 ReflectionInfo info = new ReflectionInfo(function); | 2221 ReflectionInfo info = new ReflectionInfo(function); |
2223 functionType = info.functionType; | 2222 functionType = info.functionType; |
2224 } else { | 2223 } else { |
2225 functionType = reflectionInfo; | 2224 functionType = reflectionInfo; |
2226 } | 2225 } |
2227 | 2226 |
2228 | 2227 |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2643 } else { | 2642 } else { |
2644 // A bound closure on an intercepted native class, just use the | 2643 // A bound closure on an intercepted native class, just use the |
2645 // identity hash code. | 2644 // identity hash code. |
2646 receiverHashCode = Primitives.objectHashCode(_receiver); | 2645 receiverHashCode = Primitives.objectHashCode(_receiver); |
2647 } | 2646 } |
2648 return receiverHashCode ^ Primitives.objectHashCode(_target); | 2647 return receiverHashCode ^ Primitives.objectHashCode(_target); |
2649 } | 2648 } |
2650 | 2649 |
2651 toString() { | 2650 toString() { |
2652 var receiver = _receiver == null ? _self : _receiver; | 2651 var receiver = _receiver == null ? _self : _receiver; |
2653 return "Closure '$_name' of ${Primitives.objectToString(receiver)}"; | 2652 return "Closure '$_name' of ${Primitives.objectToHumanReadableString(receive
r)}"; |
2654 } | 2653 } |
2655 | 2654 |
2656 @NoInline() | 2655 @NoInline() |
2657 static selfOf(BoundClosure closure) => closure._self; | 2656 static selfOf(BoundClosure closure) => closure._self; |
2658 | 2657 |
2659 static targetOf(BoundClosure closure) => closure._target; | 2658 static targetOf(BoundClosure closure) => closure._target; |
2660 | 2659 |
2661 @NoInline() | 2660 @NoInline() |
2662 static receiverOf(BoundClosure closure) => closure._receiver; | 2661 static receiverOf(BoundClosure closure) => closure._receiver; |
2663 | 2662 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2861 throw new TypeErrorImplementation(value, 'int'); | 2860 throw new TypeErrorImplementation(value, 'int'); |
2862 } | 2861 } |
2863 | 2862 |
2864 intTypeCast(value) { | 2863 intTypeCast(value) { |
2865 if (value is int || value == null) return value; | 2864 if (value is int || value == null) return value; |
2866 throw new CastErrorImplementation( | 2865 throw new CastErrorImplementation( |
2867 Primitives.objectTypeName(value), 'int'); | 2866 Primitives.objectTypeName(value), 'int'); |
2868 } | 2867 } |
2869 | 2868 |
2870 void propertyTypeError(value, property) { | 2869 void propertyTypeError(value, property) { |
2871 String name = classNameFromIsCheckProperty(property); | 2870 String name = isCheckPropertyToJsConstructorName(property); |
2872 throw new TypeErrorImplementation(value, name); | 2871 throw new TypeErrorImplementation(value, name); |
2873 } | 2872 } |
2874 | 2873 |
2875 void propertyTypeCastError(value, property) { | 2874 void propertyTypeCastError(value, property) { |
2876 // Cuts the property name to the class name. | 2875 // Cuts the property name to the class name. |
2877 String actualType = Primitives.objectTypeName(value); | 2876 String actualType = Primitives.objectTypeName(value); |
2878 String expectedType = property.substring(3, property.length); | 2877 String expectedType = property.substring(3, property.length); |
2879 throw new CastErrorImplementation(actualType, expectedType); | 2878 throw new CastErrorImplementation(actualType, expectedType); |
2880 } | 2879 } |
2881 | 2880 |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3221 } | 3220 } |
3222 | 3221 |
3223 _extractFunctionTypeObjectFrom(o) { | 3222 _extractFunctionTypeObjectFrom(o) { |
3224 var interceptor = getInterceptor(o); | 3223 var interceptor = getInterceptor(o); |
3225 return JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor) | 3224 return JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor) |
3226 ? JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME()) | 3225 ? JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME()) |
3227 : null; | 3226 : null; |
3228 } | 3227 } |
3229 | 3228 |
3230 toRti() { | 3229 toRti() { |
3231 var result = createDartFunctionType(); | 3230 var result = createDartFunctionTypeRti(); |
3232 if (isVoid) { | 3231 if (isVoid) { |
3233 JS('', '#[#] = true', result, JS_FUNCTION_TYPE_VOID_RETURN_TAG()); | 3232 JS('', '#[#] = true', result, JS_FUNCTION_TYPE_VOID_RETURN_TAG()); |
3234 } else { | 3233 } else { |
3235 if (returnType is! DynamicRuntimeType) { | 3234 if (returnType is! DynamicRuntimeType) { |
3236 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), | 3235 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), |
3237 returnType.toRti()); | 3236 returnType.toRti()); |
3238 } | 3237 } |
3239 } | 3238 } |
3240 if (parameterTypes != null && !parameterTypes.isEmpty) { | 3239 if (parameterTypes != null && !parameterTypes.isEmpty) { |
3241 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), | 3240 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3327 parameterTypes, | 3326 parameterTypes, |
3328 namedParameters) { | 3327 namedParameters) { |
3329 return new RuntimeFunctionType( | 3328 return new RuntimeFunctionType( |
3330 returnType, | 3329 returnType, |
3331 parameterTypes, | 3330 parameterTypes, |
3332 null, | 3331 null, |
3333 namedParameters); | 3332 namedParameters); |
3334 } | 3333 } |
3335 | 3334 |
3336 RuntimeType buildInterfaceType(rti, typeArguments) { | 3335 RuntimeType buildInterfaceType(rti, typeArguments) { |
3337 String name = JS('String', r'#.name', rti); | 3336 String jsConstructorName = rawRtiToJsConstructorName(rti); |
3338 if (typeArguments == null || typeArguments.isEmpty) { | 3337 if (typeArguments == null || typeArguments.isEmpty) { |
3339 return new RuntimeTypePlain(name); | 3338 return new RuntimeTypePlain(jsConstructorName); |
3340 } | 3339 } |
3341 return new RuntimeTypeGeneric(name, typeArguments, null); | 3340 return new RuntimeTypeGeneric(jsConstructorName, typeArguments, null); |
3342 } | 3341 } |
3343 | 3342 |
3344 class DynamicRuntimeType extends RuntimeType { | 3343 class DynamicRuntimeType extends RuntimeType { |
3345 const DynamicRuntimeType(); | 3344 const DynamicRuntimeType(); |
3346 | 3345 |
3347 String toString() => 'dynamic'; | 3346 String toString() => 'dynamic'; |
3348 | 3347 |
3349 toRti() => null; | 3348 toRti() => null; |
3350 } | 3349 } |
3351 | 3350 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3403 } else if (JS('bool', '"func" in #', rti)) { | 3402 } else if (JS('bool', '"func" in #', rti)) { |
3404 return new FunctionTypeInfoDecoderRing(rti).toRuntimeType(); | 3403 return new FunctionTypeInfoDecoderRing(rti).toRuntimeType(); |
3405 } else { | 3404 } else { |
3406 throw new RuntimeError( | 3405 throw new RuntimeError( |
3407 "Cannot convert " | 3406 "Cannot convert " |
3408 "'${JS('String', 'JSON.stringify(#)', rti)}' to RuntimeType."); | 3407 "'${JS('String', 'JSON.stringify(#)', rti)}' to RuntimeType."); |
3409 } | 3408 } |
3410 } | 3409 } |
3411 | 3410 |
3412 class RuntimeTypePlain extends RuntimeType { | 3411 class RuntimeTypePlain extends RuntimeType { |
3413 final String name; | 3412 /// The constructor name of this raw type. |
| 3413 final String _jsConstructorName; |
3414 | 3414 |
3415 RuntimeTypePlain(this.name); | 3415 RuntimeTypePlain(this._jsConstructorName); |
3416 | 3416 |
3417 toRti() { | 3417 toRti() { |
3418 var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME); | 3418 var rti = jsConstructorNameToRti(_jsConstructorName); |
3419 var rti = JS('', '#(#)', getTypeFromName, name); | 3419 if (rti == null) throw "no type for '$_jsConstructorName'"; |
3420 if (rti == null) throw "no type for '$name'"; | |
3421 return rti; | 3420 return rti; |
3422 } | 3421 } |
3423 | 3422 |
3424 String toString() => name; | 3423 String toString() => _jsConstructorName; |
3425 } | 3424 } |
3426 | 3425 |
3427 class RuntimeTypeGeneric extends RuntimeType { | 3426 class RuntimeTypeGeneric extends RuntimeType { |
3428 final String name; | 3427 /// The constructor name of the raw type for this generic type. |
| 3428 final String _jsConstructorName; |
3429 final List<RuntimeType> arguments; | 3429 final List<RuntimeType> arguments; |
3430 var rti; | 3430 var rti; |
3431 | 3431 |
3432 RuntimeTypeGeneric(this.name, this.arguments, this.rti); | 3432 RuntimeTypeGeneric(this._jsConstructorName, this.arguments, this.rti); |
3433 | 3433 |
3434 toRti() { | 3434 toRti() { |
3435 if (rti != null) return rti; | 3435 if (rti != null) return rti; |
3436 var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME); | 3436 var result = [jsConstructorNameToRti(_jsConstructorName)]; |
3437 var result = JS('JSExtendableArray', '[#(#)]', getTypeFromName, name); | |
3438 if (result[0] == null) { | 3437 if (result[0] == null) { |
3439 throw "no type for '$name<...>'"; | 3438 throw "no type for '$_jsConstructorName<...>'"; |
3440 } | 3439 } |
3441 for (RuntimeType argument in arguments) { | 3440 for (RuntimeType argument in arguments) { |
3442 JS('', '#.push(#)', result, argument.toRti()); | 3441 result.add(argument.toRti()); |
3443 } | 3442 } |
3444 return rti = result; | 3443 return rti = result; |
3445 } | 3444 } |
3446 | 3445 |
3447 String toString() => '$name<${arguments.join(", ")}>'; | 3446 String toString() => '$_jsConstructorName<${arguments.join(", ")}>'; |
3448 } | 3447 } |
3449 | 3448 |
3450 class FunctionTypeInfoDecoderRing { | 3449 class FunctionTypeInfoDecoderRing { |
3451 final _typeData; | 3450 final _typeData; |
3452 String _cachedToString; | 3451 String _cachedToString; |
3453 | 3452 |
3454 FunctionTypeInfoDecoderRing(this._typeData); | 3453 FunctionTypeInfoDecoderRing(this._typeData); |
3455 | 3454 |
3456 bool get _hasReturnType => JS('bool', '"ret" in #', _typeData); | 3455 bool get _hasReturnType => JS('bool', '"ret" in #', _typeData); |
3457 get _returnType => JS('', '#.ret', _typeData); | 3456 get _returnType => JS('', '#.ret', _typeData); |
(...skipping 10 matching lines...) Expand all Loading... |
3468 get _namedArguments => JS('=Object', '#.named', _typeData); | 3467 get _namedArguments => JS('=Object', '#.named', _typeData); |
3469 | 3468 |
3470 RuntimeType toRuntimeType() { | 3469 RuntimeType toRuntimeType() { |
3471 // TODO(ahe): Implement this (and update return type). | 3470 // TODO(ahe): Implement this (and update return type). |
3472 return const DynamicRuntimeType(); | 3471 return const DynamicRuntimeType(); |
3473 } | 3472 } |
3474 | 3473 |
3475 String _convert(type) { | 3474 String _convert(type) { |
3476 String result = runtimeTypeToString(type); | 3475 String result = runtimeTypeToString(type); |
3477 if (result != null) return result; | 3476 if (result != null) return result; |
| 3477 // Currently the [runtimeTypeToString] method doesn't handle function rtis. |
3478 if (JS('bool', '"func" in #', type)) { | 3478 if (JS('bool', '"func" in #', type)) { |
3479 return new FunctionTypeInfoDecoderRing(type).toString(); | 3479 return new FunctionTypeInfoDecoderRing(type).toString(); |
3480 } else { | 3480 } else { |
3481 throw 'bad type'; | 3481 throw 'bad type'; |
3482 } | 3482 } |
3483 } | 3483 } |
3484 | 3484 |
3485 String toString() { | 3485 String toString() { |
3486 if (_cachedToString != null) return _cachedToString; | 3486 if (_cachedToString != null) return _cachedToString; |
3487 var s = "("; | 3487 var s = "("; |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4089 // This is a function that will return a helper function that does the | 4089 // This is a function that will return a helper function that does the |
4090 // iteration of the sync*. | 4090 // iteration of the sync*. |
4091 // | 4091 // |
4092 // Each invocation should give a body with fresh state. | 4092 // Each invocation should give a body with fresh state. |
4093 final dynamic /* js function */ _outerHelper; | 4093 final dynamic /* js function */ _outerHelper; |
4094 | 4094 |
4095 SyncStarIterable(this._outerHelper); | 4095 SyncStarIterable(this._outerHelper); |
4096 | 4096 |
4097 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); | 4097 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); |
4098 } | 4098 } |
OLD | NEW |