Index: lib/src/compiler/code_generator.dart |
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
index 05d603f8de8c428c91f543740d95d541006ad1c7..067c92d076146109c2968c2387076d176f3dfab5 100644 |
--- a/lib/src/compiler/code_generator.dart |
+++ b/lib/src/compiler/code_generator.dart |
@@ -4188,11 +4188,41 @@ class CodeGenerator extends GeneralizingAstVisitor |
_visitListToBinary(node.strings, '+'); |
@override |
- JS.TemplateString visitStringInterpolation(StringInterpolation node) { |
- // Assuming we implement toString() on our objects, we can avoid calling it |
- // in most cases. Builtin types may differ though. We could handle this with |
- // a tagged template. |
- return new JS.TemplateString(_visitList(node.elements)); |
+ JS.Expression visitStringInterpolation(StringInterpolation node) { |
+ var parts = []; |
+ bool needsTag = false; |
+ for (var interpolatePart in node.elements) { |
+ if (!needsTag && interpolatePart is InterpolationExpression) { |
+ // If we have something that could be native or null, we need to use |
+ // dart.str |
+ var expr = interpolatePart.expression; |
+ var type = getStaticType(expr); |
+ |
+ // JS template strings will call .toString() by default. This works for |
+ // Dart types if we know they are not null or native. But if we have |
+ // null, or a native type like List, we need to go through a runtime |
+ // helper that will give the correct Dart behavior. |
+ needsTag = isNullable(expr) || |
+ type.isDynamic || |
+ type.isObject || |
+ (_extensionTypes.hasNativeSubtype(type) && |
+ type != types.stringType); |
+ } |
+ |
+ parts.add(_visit(interpolatePart)); |
+ } |
+ |
+ // Optimization: '$thing' is a common way to call toString. |
sra1
2016/05/17 23:47:58
It is not a synonym.
'$thing' will throw if toStr
Jennifer Messerly
2016/05/18 00:23:42
Doh. If we want to support that then all readabili
|
+ if (parts.length == 3 && parts.first == '' && parts.last == '') { |
+ var code = needsTag ? 'dart.toString(#)' : '#.toString()'; |
+ return js.call(code, parts[1]); |
+ } |
+ |
+ var templateStr = new JS.TemplateString(parts); |
+ if (needsTag) { |
+ return new JS.TaggedTemplate(js.call('dart.str'), templateStr); |
+ } |
+ return templateStr; |
} |
@override |