Index: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart |
diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart |
index 081270bbf351ae88e7fc01d80dc49a54dc98b8d1..8902af8448a276b3bbfc9e5b51a56b29f560ce78 100644 |
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart |
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart |
@@ -200,6 +200,7 @@ class ModelEmitter { |
backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), |
'outputContainsConstantList': program.outputContainsConstantList, |
'embeddedGlobals': emitEmbeddedGlobals(program), |
+ 'readMetadataTypeFunction': readMetadataTypeFunction, |
'staticNonFinals': |
emitStaticNonFinalFields(fragment.staticNonFinalFields), |
'operatorIsPrefix': js.string(namer.operatorIsPrefix), |
@@ -420,6 +421,31 @@ class ModelEmitter { |
return new js.Property(js.string(GET_TYPE_FROM_NAME), function); |
} |
+ static final metadataTypeComment = |
+ "Types are non-evaluated and must be compiled at first use. " |
+ "Compiled strings are guaranteed not to be strings, and it's thus safe " |
+ "to use a type-test to determine if a type has already been compiled."; |
+ |
+ static final String readMetadataTypeName = "readMetadataType"; |
+ |
+ js.Statement get readMetadataTypeFunction { |
+ return js.js.statement('''function $readMetadataTypeName(index) { |
+ // $metadataTypeComment. |
sra1
2015/05/07 03:39:30
Just put the comment here.
floitsch
2015/05/07 04:08:59
Done.
|
+ var type = #typesAccess[index]; |
+ if (typeof type == 'string') { |
+ type = expressionCompile(type); |
+ #typesAccess[index] = type; |
+ } |
+ return type; |
+ }''', {"typesAccess": generateEmbeddedGlobalAccess(TYPES)}); |
+ } |
+ |
+ js.Template get templateForReadType { |
+ // TODO(floitsch): make sure that no local variable shadows the access to |
+ // the readMetadataType function. |
+ return js.js.expressionTemplateFor('$readMetadataTypeName(#)'); |
+ } |
+ |
List<js.Property> emitMetadata(Program program) { |
List<js.Property> metadataGlobals = <js.Property>[]; |
@@ -435,7 +461,9 @@ class ModelEmitter { |
List<String> types = |
program.metadataTypes[program.fragments.first.outputUnit]; |
if (types == null) types = <String>[]; |
- metadataGlobals.add(createGlobal(types, TYPES)); |
+ // The strings in the array are already pretty-printed JS expressions. |
+ js.Expression unparsedTypes = js.stringArray(types); |
+ metadataGlobals.add(new js.Property(js.string(TYPES), unparsedTypes)); |
return metadataGlobals; |
} |
@@ -464,7 +492,7 @@ class ModelEmitter { |
js.LiteralString immediateString = unparse(compiler, immediateCode); |
- js.Expression deferredTypes = types == null |
+ js.Expression deferredTypes = (types == null) |
? js.string("[]") |
: js.string("[${types.join(",")}]"); |
@@ -1162,6 +1190,13 @@ function parseFunctionDescriptor(proto, name, descriptor, typesOffset) { |
// Initialize globals. |
#embeddedGlobals; |
+ function expressionCompile(__s__) { |
+ 'use strict'; |
+ return eval('(' + __s__ + ')'); |
+ } |
+ |
+ #readMetadataTypeFunction; |
+ |
// TODO(floitsch): this order means that native classes may not be |
// referenced from constants. I'm mostly afraid of things like using them as |
// generic arguments (which should be fine, but maybe there are other |