Index: lib/src/compiler/code_generator.dart |
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
index 95dba1cdabaa92703a3e0c6a11ea8fa81638d0fa..d7a99ba629d8fc93344eb2be4c897b47d924a21c 100644 |
--- a/lib/src/compiler/code_generator.dart |
+++ b/lib/src/compiler/code_generator.dart |
@@ -446,27 +446,49 @@ class CodeGenerator extends GeneralizingAstVisitor |
} |
@override |
- visitAsExpression(AsExpression node) { |
- var from = getStaticType(node.expression); |
- var to = node.type.type; |
+ visitAsExpression(AsExpression node) => |
+ _emitCast(node.expression, to: node.type.type); |
- var fromExpr = _visit(node.expression); |
+ /// Emits a cast and/or a null check (i.e. a cast to a non-null type). |
+ JS.Expression _emitCast(Expression fromExpr, |
+ {DartType to, bool checkNull: false}) { |
+ |
+ var jsFrom = _visit(fromExpr); |
+ var from = getStaticType(fromExpr); |
+ |
+ JS.Expression maybeCheckNull(JS.Expression jsExpr) { |
Jennifer Messerly
2016/05/10 23:42:12
aside: it might be a better architecture to fuse t
|
+ if (checkNull && isNullable(fromExpr)) { |
+ return js.call('dart.notNull(#)', jsExpr); |
+ } |
+ return jsExpr; |
+ } |
// Skip the cast if it's not needed. |
- if (rules.isSubtypeOf(from, to)) return fromExpr; |
+ if (to == null || rules.isSubtypeOf(from, to)) { |
+ return maybeCheckNull(jsFrom); |
+ } |
// All Dart number types map to a JS double. |
if (_isNumberInJS(from) && _isNumberInJS(to)) { |
// Make sure to check when converting to int. |
if (from != types.intType && to == types.intType) { |
- return js.call('dart.asInt(#)', [fromExpr]); |
+ // TODO(jmesserly): fuse this with notNull check. |
+ return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom])); |
} |
// A no-op in JavaScript. |
- return fromExpr; |
+ return maybeCheckNull(jsFrom); |
} |
- return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); |
+ if (to == types.boolType && checkNull) { |
+ return js.call('dart.test(#)', _visit(fromExpr)); |
+ } |
+ |
+ if (checkNull && isNullable(fromExpr)) { |
+ return js.call('dart.asNotNull(#, #)', [jsFrom, _emitType(to)]); |
+ } else { |
+ return js.call('dart.as(#, #)', [jsFrom, _emitType(to)]); |
+ } |
} |
@override |
@@ -3059,9 +3081,10 @@ class CodeGenerator extends GeneralizingAstVisitor |
JS.Expression notNull(Expression expr) { |
if (expr == null) return null; |
- var jsExpr = _visit(expr); |
- if (!isNullable(expr)) return jsExpr; |
- return js.call('dart.notNull(#)', jsExpr); |
+ if (expr is AsExpression) { |
+ return _emitCast(expr.expression, to: expr.type.type, checkNull: true); |
+ } |
+ return _emitCast(expr, checkNull: true); |
} |
@override |