Chromium Code Reviews| Index: lib/compiler/implementation/lib/js_helper.dart |
| diff --git a/lib/compiler/implementation/lib/js_helper.dart b/lib/compiler/implementation/lib/js_helper.dart |
| index a7b2f06a280802240ec6c0f0e40707368b3c3077..99a5ac7ca85946a11a3ee89dfdbb79c5771fbfc0 100644 |
| --- a/lib/compiler/implementation/lib/js_helper.dart |
| +++ b/lib/compiler/implementation/lib/js_helper.dart |
| @@ -409,7 +409,7 @@ class Primitives { |
| /** [: @"$".charCodeAt(0) :] */ |
| static final int DOLLAR_CHAR_VALUE = 36; |
| - static String objectToString(Object object) { |
| + static String objectTypeName(Object object) { |
| String name = constructorNameFallback(object); |
| if (name == 'Object') { |
| // Try to decompile the constructor by turning it into a string |
| @@ -422,6 +422,11 @@ class Primitives { |
| // 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.charCodeAt(0) === DOLLAR_CHAR_VALUE) name = name.substring(1); |
| + return name; |
| + } |
| + |
| + static String objectToString(Object object) { |
| + String name = objectTypeName(object); |
| return "Instance of '$name'"; |
| } |
| @@ -978,8 +983,8 @@ getRuntimeTypeInfo(target) { |
| /** |
| * The following methods are called by the runtime to implement |
| - * checked mode. We specialize each primitive type (eg int, bool), and |
| - * use the compiler's convention to do is checks on regular objects. |
| + * checked mode and casts. We specialize each primitive type (eg int, bool), and |
| + * use the compiler's convention to do is-checks on regular objects. |
| */ |
| stringTypeCheck(value) { |
| if (value === null) return value; |
| @@ -987,42 +992,80 @@ stringTypeCheck(value) { |
| throw new TypeError('$value does not implement String'); |
| } |
| +stringTypeCast(value) { |
|
ngeoffray
2012/08/27 14:24:00
These helpers share sooo much with their checked m
|
| + if (value is String || value === null) return value; |
| + // TODO(lrn): When reified types are available, pass value.class and String. |
| + throw new CastException(Primitives.objectTypeName(value), 'String'); |
| +} |
| + |
| doubleTypeCheck(value) { |
| if (value === null) return value; |
| if (value is double) return value; |
| throw new TypeError('$value does not implement double'); |
| } |
| +doubleTypeCast(value) { |
| + if (value is double || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'double'); |
| +} |
| + |
| numTypeCheck(value) { |
| if (value === null) return value; |
| if (value is num) return value; |
| throw new TypeError('$value does not implement num'); |
| } |
| +numTypeCast(value) { |
| + if (value is num || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'num'); |
| +} |
| + |
| boolTypeCheck(value) { |
| if (value === null) return value; |
| if (value is bool) return value; |
| throw new TypeError('$value does not implement bool'); |
| } |
| +boolTypeCast(value) { |
| + if (value is bool || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'bool'); |
| +} |
| + |
| functionTypeCheck(value) { |
| if (value === null) return value; |
| if (value is Function) return value; |
| throw new TypeError('$value does not implement Function'); |
| } |
| +functionTypeCast(value) { |
| + if (value is Function || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'Function'); |
| +} |
| + |
| intTypeCheck(value) { |
| if (value === null) return value; |
| if (value is int) return value; |
| throw new TypeError('$value does not implement int'); |
| } |
| +intTypeCast(value) { |
| + if (value is int || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'int'); |
| +} |
| + |
| void propertyTypeError(value, property) { |
| // Cuts the property name to the class name. |
| String name = property.substring(3, property.length); |
| throw new TypeError('$value does not implement $name'); |
| } |
| +void propertyTypeCastError(value, property) { |
| + // Cuts the property name to the class name. |
| + String actualType = Primitives.objectTypeName(value); |
| + String expectedType = property.substring(3, property.length); |
| + throw new CastException(actualType, expectedType); |
| +} |
| + |
| /** |
| * For types that are not supertypes of native (eg DOM) types, |
| * we emit a simple property check to check that an object implements |
| @@ -1035,6 +1078,16 @@ propertyTypeCheck(value, property) { |
| } |
| /** |
| + * For types that are not supertypes of native (eg DOM) types, |
| + * we emit a simple property check to check that an object implements |
| + * that type. |
| + */ |
| +propertyTypeCast(value, property) { |
| + if (value === null || JS('bool', '!!#[#]', value, property)) return value; |
| + propertyTypeCastError(value, property); |
| +} |
| + |
| +/** |
| * For types that are supertypes of native (eg DOM) types, we emit a |
| * call because we cannot add a JS property to their prototype at load |
| * time. |
| @@ -1049,6 +1102,20 @@ callTypeCheck(value, property) { |
| } |
| /** |
| + * For types that are supertypes of native (eg DOM) types, we emit a |
| + * call because we cannot add a JS property to their prototype at load |
| + * time. |
| + */ |
| +callTypeCast(value, property) { |
| + if (value === null |
| + || ((JS('bool', 'typeof # === "object"', value)) |
| + && JS('bool', '#[#]()', value, property))) { |
| + return value; |
| + } |
| + propertyTypeCastError(value, property); |
| +} |
| + |
| +/** |
| * Specialization of the type check for String and its supertype |
| * since [value] can be a JS primitive. |
| */ |
| @@ -1059,6 +1126,11 @@ stringSuperTypeCheck(value, property) { |
| propertyTypeError(value, property); |
| } |
| +stringSuperTypeCast(value, property) { |
| + if (value is String) return value; |
| + return propertyTypeCast(value, property); |
| +} |
| + |
| stringSuperNativeTypeCheck(value, property) { |
| if (value === null) return value; |
| if (value is String) return value; |
| @@ -1066,6 +1138,12 @@ stringSuperNativeTypeCheck(value, property) { |
| propertyTypeError(value, property); |
| } |
| +stringSuperNativeTypeCast(value, property) { |
| + if (value is String || value === null) return value; |
| + if (JS('bool', '#[#]()', value, property)) return value; |
| + propertyTypeCastError(value, property); |
| +} |
| + |
| /** |
| * Specialization of the type check for List and its supertypes, |
| * since [value] can be a JS array. |
| @@ -1076,6 +1154,11 @@ listTypeCheck(value) { |
| throw new TypeError('$value does not implement List'); |
| } |
| +listTypeCast(value) { |
| + if (value is List || value === null) return value; |
| + throw new CastException(Primitives.objectTypeName(value), 'List'); |
| +} |
| + |
| listSuperTypeCheck(value, property) { |
| if (value === null) return value; |
| if (value is List) return value; |
| @@ -1083,6 +1166,11 @@ listSuperTypeCheck(value, property) { |
| propertyTypeError(value, property); |
| } |
| +listSuperTypeCast(value, property) { |
| + if (value is List) return value; |
| + return propertyTypeCast(value, property); |
| +} |
| + |
| listSuperNativeTypeCheck(value, property) { |
| if (value === null) return value; |
| if (value is List) return value; |
| @@ -1090,6 +1178,12 @@ listSuperNativeTypeCheck(value, property) { |
| propertyTypeError(value, property); |
| } |
| +listSuperNativeTypeCast(value, property) { |
| + if (value is List || value === null) return value; |
| + if (JS('bool', '#[#]()', value, property)) return value; |
| + propertyTypeCastError(value, property); |
| +} |
| + |
| /** |
| * Special interface recognized by the compiler and implemented by DOM |
| * objects that support integer indexing. This interface is not |