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..a7322c040cef705ad3cbc17f44015ad8389e5061 100644 |
--- a/lib/compiler/implementation/lib/js_helper.dart |
+++ b/lib/compiler/implementation/lib/js_helper.dart |
@@ -978,8 +978,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 +987,78 @@ stringTypeCheck(value) { |
throw new TypeError('$value does not implement String'); |
} |
+stringTypeCast(value) { |
+ if (value is String || value === null) return value; |
+ throw new CastException(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(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(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(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(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(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 name = property.substring(3, property.length); |
+ throw new CastException(value, name); |
+} |
+ |
/** |
* For types that are not supertypes of native (eg DOM) types, |
* we emit a simple property check to check that an object implements |
@@ -1034,6 +1070,11 @@ propertyTypeCheck(value, property) { |
propertyTypeError(value, property); |
} |
+propertyTypeCast(Object value, Object property) { |
ahe
2012/06/25 10:36:56
Remove types from signature.
Lasse Reichstein Nielsen
2012/06/25 11:20:06
Why?
ahe
2012/06/25 11:57:03
Why are they there?
Lasse Reichstein Nielsen
2012/06/25 12:51:10
For the same reasons we use them everywhere else (
ahe
2012/06/25 12:56:32
Generally, you shouldn't use Object unless you're
Lasse Reichstein Nielsen
2012/06/25 15:16:07
Ack, I agree.
There is no good type to use here.
|
+ 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 |
@@ -1048,6 +1089,15 @@ callTypeCheck(value, property) { |
propertyTypeError(value, property); |
} |
+callTypeCast(value, property) { |
ahe
2012/06/25 10:36:56
A comment would be nice here.
Lasse Reichstein Nielsen
2012/06/25 11:20:06
Will do.
|
+ 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 +1109,12 @@ stringSuperTypeCheck(value, property) { |
propertyTypeError(value, property); |
} |
+stringSuperTypeCast(value, property) { |
+ if (value is String || value === null) return value; |
+ if (JS('bool', '!!#[#]', value, property)) return value; |
ahe
2012/06/25 10:36:56
This could be: return propertyTypeCast(value, prop
Lasse Reichstein Nielsen
2012/06/25 11:20:06
Well spotted.
|
+ propertyTypeCastError(value, property); |
+} |
+ |
stringSuperNativeTypeCheck(value, property) { |
if (value === null) return value; |
if (value is String) return value; |
@@ -1066,6 +1122,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; |
ahe
2012/06/25 10:36:56
Should this call callTypeCast?
ahe
2012/06/25 10:36:56
Don't you need to check for typeof value === 'obje
Lasse Reichstein Nielsen
2012/06/25 11:20:06
I think it should follow the tringSuperNativeTypeC
|
+ propertyTypeCastError(value, property); |
+} |
+ |
/** |
* Specialization of the type check for List and its supertypes, |
* since [value] can be a JS array. |
@@ -1076,6 +1138,11 @@ listTypeCheck(value) { |
throw new TypeError('$value does not implement List'); |
} |
+listTypeCast(value) { |
+ if (value is List || value === null) return value; |
+ throw new CastException(value, 'List'); |
+} |
+ |
listSuperTypeCheck(value, property) { |
if (value === null) return value; |
if (value is List) return value; |
@@ -1083,6 +1150,12 @@ listSuperTypeCheck(value, property) { |
propertyTypeError(value, property); |
} |
+listSuperTypeCast(value, property) { |
+ if (value is List || value === null) return value; |
+ if (JS('bool', '!!#[#]', value, property)) return value; |
ahe
2012/06/25 10:36:56
Call propertyTypeCast?
Lasse Reichstein Nielsen
2012/06/25 11:20:06
Will do.
|
+ propertyTypeCastError(value, property); |
+} |
+ |
listSuperNativeTypeCheck(value, property) { |
if (value === null) return value; |
if (value is List) return value; |
@@ -1090,6 +1163,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; |
ahe
2012/06/25 10:36:56
Call callTypeCast?
Lasse Reichstein Nielsen
2012/06/25 11:20:06
That should work. And ditto for the check.
Lasse Reichstein Nielsen
2012/06/25 15:16:07
Actually, the "callTypeCast" does more tests than
|
+ propertyTypeCastError(value, property); |
+} |
+ |
/** |
* Special interface recognized by the compiler and implemented by DOM |
* objects that support integer indexing. This interface is not |