Index: sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
index 7113389e597380d4f76f9d82e59430ff10ccef80..3888d0917ab32ba3ff9a9c792f292f9001cdc207 100644 |
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart |
@@ -55,6 +55,8 @@ class CodeEmitterTask extends CompilerTask { |
// TODO(ngeoffray): remove this field. |
Set<ClassElement> instantiatedClasses; |
+ List<TypedefElement> typedefsNeededForReflection; |
+ |
JavaScriptBackend get backend => compiler.backend; |
TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler; |
@@ -63,9 +65,12 @@ class CodeEmitterTask extends CompilerTask { |
String get n => compiler.enableMinification ? "" : "\n"; |
String get N => compiler.enableMinification ? "\n" : ";\n"; |
+ CodeBuffer getBuffer(OutputUnit outputUnit) { |
+ return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer()); |
+ } |
+ |
CodeBuffer get mainBuffer { |
- return outputBuffers.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit, |
- () => new CodeBuffer()); |
+ return getBuffer(compiler.deferredLoadTask.mainOutputUnit); |
} |
/** |
@@ -750,6 +755,8 @@ class CodeEmitterTask extends CompilerTask { |
ClassElement cls = element; |
if (cls.isUnnamedMixinApplication) return null; |
return cls.name; |
+ } else if (element.isTypedef) { |
+ return element.name; |
} |
throw compiler.internalError(element, |
'Do not know how to reflect on this $element.'); |
@@ -859,7 +866,7 @@ class CodeEmitterTask extends CompilerTask { |
for (Element element in Elements.sortedByPosition(elements)) { |
ClassBuilder builder = new ClassBuilder(namer); |
containerBuilder.addMember(element, builder); |
- getElementDecriptor(element).properties.addAll(builder.properties); |
+ getElementDescriptor(element).properties.addAll(builder.properties); |
} |
} |
@@ -1145,10 +1152,15 @@ class CodeEmitterTask extends CompilerTask { |
} |
} |
- /** |
- * Compute all the classes that must be emitted. |
- */ |
- void computeNeededClasses() { |
+ /// Compute all the classes and typedefs that must be emitted. |
+ void computeNeededDeclarations() { |
+ // Compute needed typedefs. |
+ typedefsNeededForReflection = Elements.sortedByPosition( |
+ compiler.world.allTypedefs |
+ .where(backend.isAccessibleByReflection) |
+ .toList()); |
+ |
+ // Compute needed classes. |
instantiatedClasses = |
compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) |
.toSet(); |
@@ -1303,21 +1315,17 @@ class CodeEmitterTask extends CompilerTask { |
if (uri.scheme == 'file' && compiler.outputUri != null) { |
uri = relativize(compiler.outputUri, library.canonicalUri, false); |
} |
- Map<OutputUnit, ClassBuilder> descriptors = |
- elementDescriptors[library]; |
+ Map<OutputUnit, ClassBuilder> descriptors = elementDescriptors[library]; |
for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { |
- ClassBuilder descriptor = |
- descriptors.putIfAbsent(outputUnit, () => new ClassBuilder(namer)); |
- if (descriptor.properties.isEmpty) continue; |
- bool isDeferred = |
- outputUnit != compiler.deferredLoadTask.mainOutputUnit; |
+ if (!descriptors.containsKey(outputUnit)) continue; |
+ |
+ ClassBuilder descriptor = descriptors[outputUnit]; |
jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); |
- jsAst.ObjectInitializer initializers = |
- descriptor.toObjectInitializer(); |
- CodeBuffer outputBuffer = |
- outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer()); |
+ jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); |
+ CodeBuffer outputBuffer = getBuffer(outputUnit); |
+ |
int sizeBefore = outputBuffer.length; |
outputBuffers[outputUnit] |
..write('["${library.getLibraryName()}",$_') |
@@ -1343,7 +1351,7 @@ class CodeEmitterTask extends CompilerTask { |
// 'is$' method. |
typeTestEmitter.computeRequiredTypeChecks(); |
- computeNeededClasses(); |
+ computeNeededDeclarations(); |
mainBuffer.add(buildGeneratedBy()); |
addComment(HOOKS_API_USAGE, mainBuffer); |
@@ -1378,7 +1386,8 @@ class CodeEmitterTask extends CompilerTask { |
// Only output the classesCollector if we actually have any classes. |
if (!(nativeClasses.isEmpty && |
compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && |
- outputClassLists.values.every((classList) => classList.isEmpty))) { |
+ outputClassLists.values.every((classList) => classList.isEmpty) && |
+ typedefsNeededForReflection.isEmpty)) { |
// Shorten the code by using "$$" as temporary. |
classesCollector = r"$$"; |
mainBuffer.add('var $classesCollector$_=$_{}$N$n'); |
@@ -1402,7 +1411,7 @@ class CodeEmitterTask extends CompilerTask { |
// Might create methodClosures. |
for (List<ClassElement> outputClassList in outputClassLists.values) { |
for (ClassElement element in outputClassList) { |
- generateClass(element, getElementDecriptor(element)); |
+ generateClass(element, getElementDescriptor(element)); |
} |
} |
@@ -1422,6 +1431,8 @@ class CodeEmitterTask extends CompilerTask { |
mainBuffer.write(';'); |
} |
+ // TODO(karlklose): document what kinds of fields this loop adds to the |
+ // library class builder. |
for (Element element in elementDescriptors.keys) { |
// TODO(ahe): Should iterate over all libraries. Otherwise, we will |
// not see libraries that only have fields. |
@@ -1437,6 +1448,28 @@ class CodeEmitterTask extends CompilerTask { |
} |
} |
+ // Emit all required typedef declarations into the main output unit. |
+ // TODO(karlklose): unify required classes and typedefs to declarations |
+ // and have builders for each kind. |
+ for (TypedefElement typedef in typedefsNeededForReflection) { |
+ OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit; |
+ LibraryElement library = typedef.library; |
+ // TODO(karlklose): add a TypedefBuilder and move this code there. |
+ DartType type = typedef.alias; |
+ int typeIndex = metadataEmitter.reifyType(type); |
+ String typeReference = |
+ encoding.encodeTypedefFieldDescriptor(typeIndex); |
+ jsAst.Property descriptor = new jsAst.Property( |
+ js.string(namer.classDescriptorProperty), |
+ js.string(typeReference)); |
+ jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); |
+ String mangledName = namer.getNameX(typedef); |
+ String reflectionName = getReflectionName(typedef, mangledName); |
+ getElementDescriptorForOutputUnit(library, mainUnit) |
+ ..addProperty(mangledName, declaration) |
+ ..addProperty("+$reflectionName", js.string('')); |
+ } |
+ |
if (!mangledFieldNames.isEmpty) { |
var keys = mangledFieldNames.keys.toList(); |
keys.sort(); |
@@ -1689,7 +1722,7 @@ class CodeEmitterTask extends CompilerTask { |
() => new ClassBuilder(namer)); |
} |
- ClassBuilder getElementDecriptor(Element element) { |
+ ClassBuilder getElementDescriptor(Element element) { |
Element owner = element.library; |
if (!element.isTopLevel && !element.isNative) { |
// For static (not top level) elements, record their code in a buffer |