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 /** | 5 /** |
6 * This part contains helpers for supporting runtime type information. | 6 * This part contains helpers for supporting runtime type information. |
7 * | 7 * |
8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is | 8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is |
9 * used where we adopt the scheme of using explicit type annotation for Dart | 9 * used where we adopt the scheme of using explicit type annotation for Dart |
10 * objects and 'var' or omitted return type for JavaScript objects. | 10 * objects and 'var' or omitted return type for JavaScript objects. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 Type createRuntimeType(String name) => new TypeImpl(name); | 44 Type createRuntimeType(String name) => new TypeImpl(name); |
45 | 45 |
46 class TypeImpl implements Type { | 46 class TypeImpl implements Type { |
47 final String _typeName; | 47 final String _typeName; |
48 String _unmangledName; | 48 String _unmangledName; |
49 | 49 |
50 TypeImpl(this._typeName); | 50 TypeImpl(this._typeName); |
51 | 51 |
52 String toString() { | 52 String toString() { |
53 if (_unmangledName != null) return _unmangledName; | 53 if (_unmangledName != null) return _unmangledName; |
54 String unmangledName = unmangleAllIdentifiersIfPreservedAnyways(_typeName); | 54 String unmangledName = |
| 55 unmangleAllIdentifiersIfPreservedAnyways(_typeName); |
55 return _unmangledName = unmangledName; | 56 return _unmangledName = unmangledName; |
56 } | 57 } |
57 | 58 |
58 // TODO(ahe): This is a poor hashCode as it collides with its name. | 59 // TODO(ahe): This is a poor hashCode as it collides with its name. |
59 int get hashCode => _typeName.hashCode; | 60 int get hashCode => _typeName.hashCode; |
60 | 61 |
61 bool operator ==(other) { | 62 bool operator ==(other) { |
62 return (other is TypeImpl) && _typeName == other._typeName; | 63 return (other is TypeImpl) && _typeName == other._typeName; |
63 } | 64 } |
64 } | 65 } |
65 | 66 |
66 /** | 67 /** |
67 * Represents a type variable. | 68 * Represents a type variable. |
68 * | 69 * |
69 * This class holds the information needed when reflecting on generic classes | 70 * This class holds the information needed when reflecting on generic classes |
70 * and their members. | 71 * and their members. |
71 */ | 72 */ |
72 class TypeVariable { | 73 class TypeVariable { |
73 final Type owner; | 74 final Type owner; |
74 final String name; | 75 final String name; |
75 final int bound; | 76 final int bound; |
76 | 77 |
77 const TypeVariable(this.owner, this.name, this.bound); | 78 const TypeVariable(this.owner, this.name, this.bound); |
78 } | 79 } |
79 | 80 |
80 getMangledTypeName(TypeImpl type) => type._typeName; | 81 getMangledTypeName(TypeImpl type) => type._typeName; |
81 | 82 |
82 /** | 83 /** |
83 * Sets the runtime type information on [target]. [typeInfo] is a type | 84 * Sets the runtime type information on [target]. [rti] is a type |
84 * representation of type 4 or 5, that is, either a JavaScript array or | 85 * representation of type 4 or 5, that is, either a JavaScript array or |
85 * `null`. | 86 * `null`. |
86 */ | 87 */ |
87 Object setRuntimeTypeInfo(Object target, var typeInfo) { | 88 Object setRuntimeTypeInfo(Object target, var rti) { |
88 assert(typeInfo == null || isJsArray(typeInfo)); | 89 assert(rti == null || isJsArray(rti)); |
89 // We have to check for null because factories may return null. | 90 // We have to check for null because factories may return null. |
90 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo); | 91 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, rti); |
91 return target; | 92 return target; |
92 } | 93 } |
93 | 94 |
94 /** | 95 /** |
95 * Returns the runtime type information of [target]. The returned value is a | 96 * Returns the runtime type information of [target]. The returned value is a |
96 * list of type representations for the type arguments. | 97 * list of type representations for the type arguments. |
97 */ | 98 */ |
98 getRuntimeTypeInfo(Object target) { | 99 getRuntimeTypeInfo(Object target) { |
99 if (target == null) return null; | 100 if (target == null) return null; |
100 return JS('var', r'#.$builtinTypeInfo', target); | 101 return JS('var', r'#.$builtinTypeInfo', target); |
(...skipping 26 matching lines...) Expand all Loading... |
127 | 128 |
128 void copyTypeArguments(Object source, Object target) { | 129 void copyTypeArguments(Object source, Object target) { |
129 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source); | 130 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source); |
130 } | 131 } |
131 | 132 |
132 /** | 133 /** |
133 * Retrieves the class name from type information stored on the constructor | 134 * Retrieves the class name from type information stored on the constructor |
134 * of [object]. | 135 * of [object]. |
135 */ | 136 */ |
136 String getClassName(var object) { | 137 String getClassName(var object) { |
137 return getDartTypeName(getRawRuntimeType(getInterceptor(object))); | 138 return rawRtiToJsConstructorName(getRawRuntimeType(getInterceptor(object))); |
138 } | 139 } |
139 | 140 |
140 /** | 141 /** |
141 * Creates the string representation for the type representation [runtimeType] | 142 * Creates the string representation for the type representation [rti] |
142 * of type 4, the JavaScript array, where the first element represents the class | 143 * of type 4, the JavaScript array, where the first element represents the class |
143 * and the remaining elements represent the type arguments. | 144 * and the remaining elements represent the type arguments. |
144 */ | 145 */ |
145 String getRuntimeTypeAsString(var runtimeType, {String onTypeVariable(int i)}) { | 146 String getRuntimeTypeAsString(var rti, {String onTypeVariable(int i)}) { |
146 assert(isJsArray(runtimeType)); | 147 assert(isJsArray(rti)); |
147 String className = getDartTypeName(getIndex(runtimeType, 0)); | 148 String className = rawRtiToJsConstructorName(getIndex(rti, 0)); |
148 return '$className' | 149 return '$className${joinArguments(rti, 1, onTypeVariable: onTypeVariable)}'; |
149 '${joinArguments(runtimeType, 1, onTypeVariable: onTypeVariable)}'; | |
150 } | 150 } |
151 | 151 |
152 /** | 152 /** |
153 * Returns a human-readable representation of the type representation [type]. | 153 * Returns a human-readable representation of the type representation [rti]. |
154 */ | 154 */ |
155 String runtimeTypeToString(var type, {String onTypeVariable(int i)}) { | 155 String runtimeTypeToString(var rti, {String onTypeVariable(int i)}) { |
156 if (type == null) { | 156 if (rti == null) { |
157 return 'dynamic'; | 157 return 'dynamic'; |
158 } else if (isJsArray(type)) { | 158 } else if (isJsArray(rti)) { |
159 // A list representing a type with arguments. | 159 // A list representing a type with arguments. |
160 return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable); | 160 return getRuntimeTypeAsString(rti, onTypeVariable: onTypeVariable); |
161 } else if (isJsFunction(type)) { | 161 } else if (isJsFunction(rti)) { |
162 // A reference to the constructor. | 162 // A reference to the constructor. |
163 return getDartTypeName(type); | 163 return rawRtiToJsConstructorName(rti); |
164 } else if (type is int) { | 164 } else if (rti is int) { |
165 if (onTypeVariable == null) { | 165 if (onTypeVariable == null) { |
166 return type.toString(); | 166 return rti.toString(); |
167 } else { | 167 } else { |
168 return onTypeVariable(type); | 168 return onTypeVariable(rti); |
169 } | 169 } |
170 } else { | 170 } else { |
171 // TODO(ahe): Handle function types, and be sure to always return a string. | 171 // TODO(ahe): Handle function types, and be sure to always return a string. |
172 return null; | 172 return null; |
173 } | 173 } |
174 } | 174 } |
175 | 175 |
176 /** | 176 /** |
177 * Creates a comma-separated string of human-readable representations of the | 177 * Creates a comma-separated string of human-readable representations of the |
178 * type representations in the JavaScript array [types] starting at index | 178 * type representations in the JavaScript array [types] starting at index |
(...skipping 22 matching lines...) Expand all Loading... |
201 } | 201 } |
202 | 202 |
203 /** | 203 /** |
204 * Returns a human-readable representation of the type of [object]. | 204 * Returns a human-readable representation of the type of [object]. |
205 * | 205 * |
206 * In minified mode does *not* use unminified identifiers (even when present). | 206 * In minified mode does *not* use unminified identifiers (even when present). |
207 */ | 207 */ |
208 String getRuntimeTypeString(var object) { | 208 String getRuntimeTypeString(var object) { |
209 String className = getClassName(object); | 209 String className = getClassName(object); |
210 if (object == null) return className; | 210 if (object == null) return className; |
211 var typeInfo = JS('var', r'#.$builtinTypeInfo', object); | 211 var rti = JS('var', r'#.$builtinTypeInfo', object); |
212 return "$className${joinArguments(typeInfo, 0)}"; | 212 return "$className${joinArguments(rti, 0)}"; |
213 } | 213 } |
214 | 214 |
215 Type getRuntimeType(var object) { | 215 Type getRuntimeType(var object) { |
216 String type = getRuntimeTypeString(object); | 216 String type = getRuntimeTypeString(object); |
217 return new TypeImpl(type); | 217 return new TypeImpl(type); |
218 } | 218 } |
219 | 219 |
220 /** | 220 /** |
221 * Applies the [substitution] on the [arguments]. | 221 * Applies the [substitution] on the [arguments]. |
222 * | 222 * |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 var substitution = getField(interceptor, asField); | 266 var substitution = getField(interceptor, asField); |
267 return checkArguments(substitution, arguments, checks); | 267 return checkArguments(substitution, arguments, checks); |
268 } | 268 } |
269 | 269 |
270 /// Returns the field's type name. | 270 /// Returns the field's type name. |
271 /// | 271 /// |
272 /// In minified mode, uses the unminified names if available. | 272 /// In minified mode, uses the unminified names if available. |
273 String computeTypeName(String isField, List arguments) { | 273 String computeTypeName(String isField, List arguments) { |
274 // Extract the class name from the is field and append the textual | 274 // Extract the class name from the is field and append the textual |
275 // representation of the type arguments. | 275 // representation of the type arguments. |
276 return Primitives.formatType(classNameFromIsCheckProperty(isField), | 276 return Primitives.formatType(isCheckPropertyToJsConstructorName(isField), |
277 arguments); | 277 arguments); |
278 } | 278 } |
279 | 279 |
280 Object subtypeCast(Object object, String isField, List checks, String asField) { | 280 Object subtypeCast(Object object, String isField, List checks, String asField) { |
281 if (object != null && !checkSubtype(object, isField, checks, asField)) { | 281 if (object != null && !checkSubtype(object, isField, checks, asField)) { |
282 String actualType = Primitives.objectTypeName(object); | 282 String actualType = Primitives.objectTypeName(object); |
283 String typeName = computeTypeName(isField, checks); | 283 String typeName = computeTypeName(isField, checks); |
284 // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to | 284 // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to |
285 // align with [TypeErrorImplementation]. | 285 // align with [TypeErrorImplementation]. |
286 throw new CastErrorImplementation(actualType, typeName); | 286 throw new CastErrorImplementation(actualType, typeName); |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 * `null` and `undefined` (which we can avoid). | 668 * `null` and `undefined` (which we can avoid). |
669 */ | 669 */ |
670 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); | 670 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); |
671 | 671 |
672 /** | 672 /** |
673 * Returns `true` if the JavaScript values [s] and [t] are not identical. We use | 673 * Returns `true` if the JavaScript values [s] and [t] are not identical. We use |
674 * this helper instead of [identical] because `identical` needs to merge | 674 * this helper instead of [identical] because `identical` needs to merge |
675 * `null` and `undefined` (which we can avoid). | 675 * `null` and `undefined` (which we can avoid). |
676 */ | 676 */ |
677 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); | 677 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); |
OLD | NEW |