| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 return 'dynamic'; | 154 return 'dynamic'; |
| 155 } else if (isJsArray(type)) { | 155 } else if (isJsArray(type)) { |
| 156 // A list representing a type with arguments. | 156 // A list representing a type with arguments. |
| 157 return getRuntimeTypeAsString(type); | 157 return getRuntimeTypeAsString(type); |
| 158 } else if (isJsFunction(type)) { | 158 } else if (isJsFunction(type)) { |
| 159 // A reference to the constructor. | 159 // A reference to the constructor. |
| 160 return getConstructorName(type); | 160 return getConstructorName(type); |
| 161 } else if (type is int) { | 161 } else if (type is int) { |
| 162 return type.toString(); | 162 return type.toString(); |
| 163 } else { | 163 } else { |
| 164 // TODO(ahe): Handle function types, and be sure to always return a string. |
| 164 return null; | 165 return null; |
| 165 } | 166 } |
| 166 } | 167 } |
| 167 | 168 |
| 168 /** | 169 /** |
| 169 * Creates a comma-separated string of human-readable representations of the | 170 * Creates a comma-separated string of human-readable representations of the |
| 170 * type representations in the JavaScript array [types] starting at index | 171 * type representations in the JavaScript array [types] starting at index |
| 171 * [startIndex]. | 172 * [startIndex]. |
| 172 */ | 173 */ |
| 173 String joinArguments(var types, int startIndex) { | 174 String joinArguments(var types, int startIndex) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 | 320 |
| 320 int len = getLength(s); | 321 int len = getLength(s); |
| 321 for (int i = 0; i < len; i++) { | 322 for (int i = 0; i < len; i++) { |
| 322 if (!isSubtype(getIndex(s, i), getIndex(t, i))) { | 323 if (!isSubtype(getIndex(s, i), getIndex(t, i))) { |
| 323 return false; | 324 return false; |
| 324 } | 325 } |
| 325 } | 326 } |
| 326 return true; | 327 return true; |
| 327 } | 328 } |
| 328 | 329 |
| 330 // TODO(ahe): Remove this. |
| 329 Object functionSubtypeCast(Object object, String signatureName, | 331 Object functionSubtypeCast(Object object, String signatureName, |
| 330 String contextName, var context, | 332 String contextName, var context, |
| 331 var typeArguments) { | 333 var typeArguments) { |
| 332 if (!checkFunctionSubtype(object, signatureName, | 334 if (!checkFunctionSubtype(object, signatureName, |
| 333 contextName, context, typeArguments)) { | 335 contextName, context, typeArguments)) { |
| 334 String actualType = Primitives.objectTypeName(object); | 336 String actualType = Primitives.objectTypeName(object); |
| 335 // TODO(johnniwinther): Provide better function type naming. | 337 // TODO(johnniwinther): Provide better function type naming. |
| 336 String typeName = signatureName; | 338 String typeName = signatureName; |
| 337 throw new CastErrorImplementation(actualType, typeName); | 339 throw new CastErrorImplementation(actualType, typeName); |
| 338 } | 340 } |
| 339 return object; | 341 return object; |
| 340 } | 342 } |
| 341 | 343 |
| 344 // TODO(ahe): Remove this. |
| 342 Object assertFunctionSubtype(Object object, String signatureName, | 345 Object assertFunctionSubtype(Object object, String signatureName, |
| 343 String contextName, var context, | 346 String contextName, var context, |
| 344 var typeArguments) { | 347 var typeArguments) { |
| 345 if (!checkFunctionSubtype(object, signatureName, | 348 if (!checkFunctionSubtype(object, signatureName, |
| 346 contextName, context, typeArguments)) { | 349 contextName, context, typeArguments)) { |
| 347 // TODO(johnniwinther): Provide better function type naming. | 350 // TODO(johnniwinther): Provide better function type naming. |
| 348 String typeName = signatureName; | 351 String typeName = signatureName; |
| 349 throw new TypeErrorImplementation(object, typeName); | 352 throw new TypeErrorImplementation(object, typeName); |
| 350 } | 353 } |
| 351 return object; | 354 return object; |
| 352 } | 355 } |
| 353 | 356 |
| 354 /** | 357 /** |
| 355 * Checks that the type of [target] is a subtype of the function type denoted by | 358 * Checks that the type of [target] is a subtype of the function type denoted by |
| 356 * [signatureName]. If the type contains type variables, [contextName] holds the | 359 * [signatureName]. If the type contains type variables, [contextName] holds the |
| 357 * name of the class where these were declared and either [context] holds the | 360 * name of the class where these were declared and either [context] holds the |
| 358 * object in which the runtime values of these can be found or [typeArguments] | 361 * object in which the runtime values of these can be found or [typeArguments] |
| 359 * contains these values as a list of runtime type information. | 362 * contains these values as a list of runtime type information. |
| 360 */ | 363 */ |
| 364 // TODO(ahe): Remove this. |
| 361 bool checkFunctionSubtype(var target, String signatureName, | 365 bool checkFunctionSubtype(var target, String signatureName, |
| 362 String contextName, var context, | 366 String contextName, var context, |
| 363 var typeArguments) { | 367 var typeArguments) { |
| 364 if (isNull(target)) return true; | 368 if (isNull(target)) return true; |
| 365 var interceptor = getInterceptor(target); | 369 var interceptor = getInterceptor(target); |
| 366 if (hasField(interceptor, '${JS_OPERATOR_IS_PREFIX()}_$signatureName')) { | 370 if (hasField(interceptor, '${JS_OPERATOR_IS_PREFIX()}_$signatureName')) { |
| 367 return true; | 371 return true; |
| 368 } | 372 } |
| 369 var signatureLocation = JS_CURRENT_ISOLATE(); | 373 var signatureLocation = JS_CURRENT_ISOLATE(); |
| 370 if (isNotNull(contextName)) { | 374 if (isNotNull(contextName)) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 if (getConstructorName(t) == JS_FUNCTION_CLASS_NAME() && | 497 if (getConstructorName(t) == JS_FUNCTION_CLASS_NAME() && |
| 494 hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { | 498 hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { |
| 495 return true; | 499 return true; |
| 496 } | 500 } |
| 497 // Get the object describing the class and check for the subtyping flag | 501 // Get the object describing the class and check for the subtyping flag |
| 498 // constructed from the type of [t]. | 502 // constructed from the type of [t]. |
| 499 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; | 503 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; |
| 500 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; | 504 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; |
| 501 // Check for a subtyping flag. | 505 // Check for a subtyping flag. |
| 502 var name = runtimeTypeToString(typeOfT); | 506 var name = runtimeTypeToString(typeOfT); |
| 503 var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; | |
| 504 if (hasNoField(typeOfS, test)) return false; | |
| 505 // Get the necessary substitution of the type arguments, if there is one. | 507 // Get the necessary substitution of the type arguments, if there is one. |
| 506 var substitution; | 508 var substitution; |
| 507 if (isNotIdentical(typeOfT, typeOfS)) { | 509 if (isNotIdentical(typeOfT, typeOfS)) { |
| 510 var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; |
| 511 if (hasNoField(typeOfS, test)) return false; |
| 508 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; | 512 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; |
| 509 substitution = getField(typeOfS, field); | 513 substitution = getField(typeOfS, field); |
| 510 } | 514 } |
| 511 // The class of [s] is a subclass of the class of [t]. If [s] has no type | 515 // The class of [s] is a subclass of the class of [t]. If [s] has no type |
| 512 // arguments and no substitution, it is used as raw type. If [t] has no | 516 // arguments and no substitution, it is used as raw type. If [t] has no |
| 513 // type arguments, it used as a raw type. In both cases, [s] is a subtype | 517 // type arguments, it used as a raw type. In both cases, [s] is a subtype |
| 514 // of [t]. | 518 // of [t]. |
| 515 if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) { | 519 if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) { |
| 516 return true; | 520 return true; |
| 517 } | 521 } |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 * and [t] are Dart values. | 737 * and [t] are Dart values. |
| 734 */ | 738 */ |
| 735 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); | 739 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); |
| 736 | 740 |
| 737 /** | 741 /** |
| 738 * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We | 742 * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We |
| 739 * use this helper to avoid generating code under the invalid assumption that | 743 * use this helper to avoid generating code under the invalid assumption that |
| 740 * [s] and [t] are Dart values. | 744 * [s] and [t] are Dart values. |
| 741 */ | 745 */ |
| 742 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); | 746 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); |
| OLD | NEW |