Index: lib/src/compiler/code_generator.dart |
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
index d07bfb06619611d3aa7cb7238e7f19185343f0e9..b5c3047bcc2b7a4b68488e9c39978947db62fb3d 100644 |
--- a/lib/src/compiler/code_generator.dart |
+++ b/lib/src/compiler/code_generator.dart |
@@ -41,7 +41,11 @@ import 'js_metalet.dart' as JS; |
import 'js_names.dart' as JS; |
import 'js_typeref_codegen.dart' show JsTypeRefCodegen; |
import 'module_builder.dart' |
- show LegacyModuleBuilder, NodeModuleBuilder, pathToJSIdentifier; |
+ show |
+ LegacyModuleBuilder, |
+ NodeModuleBuilder, |
+ pathToJSIdentifier, |
+ toJSIdentifier; |
import 'nullable_type_inference.dart' show NullableTypeInference; |
import 'reify_coercions.dart' show CoercionReifier; |
import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; |
@@ -124,6 +128,8 @@ class CodeGenerator extends GeneralizingAstVisitor |
List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; |
List<JS.Method> _superHelpers = <JS.Method>[]; |
+ List<TypeParameterType> _typeParamInConst = null; |
+ |
/// Whether we are currently generating code for the body of a `JS()` call. |
bool _isInForeignJS = false; |
@@ -2299,6 +2305,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
} |
if (type is TypeParameterType) { |
+ _typeParamInConst?.add(type); |
return new JS.Identifier(name); |
} |
@@ -3385,9 +3392,22 @@ class CodeGenerator extends GeneralizingAstVisitor |
} |
JS.Expression _emitConst(JS.Expression expr()) { |
- // TODO(jmesserly): emit the constants at top level if possible. |
- // This wasn't quite working, so disabled for now. |
- return js.call('dart.const(#)', expr()); |
+ var savedTypeParams = _typeParamInConst; |
+ _typeParamInConst = []; |
+ |
+ var jsExpr = js.call('dart.const(#)', expr()); |
+ |
+ bool usesTypeParams = _typeParamInConst.isNotEmpty; |
+ _typeParamInConst = savedTypeParams; |
+ |
+ // TODO(jmesserly): if it uses type params we can still hoist it up as far |
+ // as it will go, e.g. at the level the generic class is defined where type |
+ // params are available. |
+ if (_currentFunction == null || usesTypeParams) return jsExpr; |
+ |
+ var temp = new JS.TemporaryId('const'); |
+ _moduleItems.add(js.statement('let #;', [temp])); |
+ return js.call('# || (# = #)', [temp, temp, jsExpr]); |
} |
/// Returns a new expression, which can be be used safely *once* on the |