Index: lib/src/compiler/code_generator.dart |
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
index 1276c85eaeaeed3e9b6f4a7bbe8d4cff67e002fc..a4508bf05eb26b4532d44b760189cbbd2599fa38 100644 |
--- a/lib/src/compiler/code_generator.dart |
+++ b/lib/src/compiler/code_generator.dart |
@@ -116,6 +116,9 @@ class CodeGenerator extends GeneralizingAstVisitor |
String _buildRoot; |
+ /// Whether we are currently generating code for the body of a `JS()` call. |
+ bool _isInForeignJS = false; |
+ |
CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
: context = c, |
types = c.typeProvider, |
@@ -219,7 +222,6 @@ class CodeGenerator extends GeneralizingAstVisitor |
// Add implicit dart:core dependency so it is first. |
emitLibraryName(dartCoreLibrary); |
- // |
// Visit each compilation unit and emit its code. |
// |
// NOTE: declarations are not necessarily emitted in this order. |
@@ -2009,7 +2011,18 @@ class CodeGenerator extends GeneralizingAstVisitor |
// type literal |
if (element is TypeDefiningElement) { |
- return _emitTypeName(fillDynamicTypeArgs(element.type)); |
+ var typeName = _emitTypeName(fillDynamicTypeArgs(element.type)); |
+ |
+ // If the type is a type literal expression in Dart code, wrap the raw |
+ // runtime type in a "Type" instance. |
+ if (!_isInForeignJS && |
+ node.parent is! MethodInvocation && |
+ node.parent is! PrefixedIdentifier && |
+ node.parent is! PropertyAccess) { |
+ typeName = js.call('dart.wrapType(#)', typeName); |
+ } |
+ |
+ return typeName; |
} |
// library member |
@@ -2477,8 +2490,20 @@ class CodeGenerator extends GeneralizingAstVisitor |
source = (code as StringLiteral).stringValue; |
} |
+ // TODO(rnystrom): The JS() calls are almost never nested, and probably |
+ // really shouldn't be, but there are at least a couple of calls in the |
+ // HTML library where an argument to JS() is itself a JS() call. If those |
+ // go away, this can just assert(!_isInForeignJS). |
+ // Inside JS(), type names evaluate to the raw runtime type, not the |
+ // wrapped Type object. |
+ var wasInForeignJS = _isInForeignJS; |
+ _isInForeignJS = true; |
+ |
var template = js.parseForeignJS(source); |
var result = template.instantiate(_visitList(templateArgs)); |
+ |
+ _isInForeignJS = wasInForeignJS; |
+ |
// `throw` is emitted as a statement by `parseForeignJS`. |
assert(result is JS.Expression || node.parent is ExpressionStatement); |
return result; |