| 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
|
|
|