JS: support class prototypes in new pipeline

This commit is contained in:
Alexey Andreev
2017-02-10 18:38:19 +03:00
parent 108fcba885
commit 2354adfa22
2 changed files with 35 additions and 38 deletions
@@ -729,7 +729,9 @@ public final class StaticContext {
}
public void addClass(@NotNull ClassDescriptor classDescriptor) {
fragment.getClasses().put(getInnerNameForDescriptor(classDescriptor), classModelGenerator.generateClassModel(classDescriptor));
if (!AnnotationsUtils.isNativeObject(classDescriptor) && !AnnotationsUtils.isLibraryObject(classDescriptor)) {
fragment.getClasses().put(getInnerNameForDescriptor(classDescriptor), classModelGenerator.generateClassModel(classDescriptor));
}
}
public void export(@NotNull MemberDescriptor descriptor, boolean force) {
@@ -754,41 +756,4 @@ public final class StaticContext {
rootFunction.getBody().getStatements().addAll(exporter.getStatements());
rootFunction.getBody().getStatements().addAll(topLevelStatements);
}*/
/*private void addClassPrototypes() {
Set<ClassDescriptor> visited = new HashSet<>();
for (ClassDescriptor cls : classes) {
addClassPrototypes(cls, visited);
}
}*/
/*private void addClassPrototypes(@NotNull ClassDescriptor cls, @NotNull Set<ClassDescriptor> visited) {
if (!visited.add(cls)) return;
if (DescriptorUtilsKt.getModule(cls) != currentModule) return;
if (isNativeObject(cls) || isLibraryObject(cls)) return;
ClassDescriptor superclass = DescriptorUtilsKt.getSuperClassNotAny(cls);
if (superclass != null) {
addClassPrototypes(superclass, visited);
List<JsStatement> statements = rootFunction.getBody().getStatements();
JsNameRef superclassRef;
if (isNativeObject(superclass) || isLibraryObject(superclass)) {
superclassRef = getQualifiedReference(superclass);
}
else {
superclassRef = getInnerNameForDescriptor(superclass).makeRef();
}
JsExpression superPrototype = JsAstUtils.prototypeOf(superclassRef);
JsExpression superPrototypeInstance = new JsInvocation(new JsNameRef("create", "Object"), superPrototype);
JsExpression classRef = new JsNameRef(getInnerNameForDescriptor(cls));
JsExpression prototype = JsAstUtils.prototypeOf(classRef);
statements.add(JsAstUtils.assignment(prototype, superPrototypeInstance).makeStmt());
JsExpression constructorRef = new JsNameRef("constructor", prototype.deepCopy());
statements.add(JsAstUtils.assignment(constructorRef, classRef.deepCopy()).makeStmt());
}
}*/
}
@@ -30,6 +30,7 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
private val initializerBlock = JsGlobalBlock()
private val exportBlock = JsGlobalBlock()
private val declaredImports = mutableSetOf<String>()
private val classes = mutableMapOf<JsName, JsClassModel>()
// Add declaration and initialization statements from program fragment to resulting single program
fun addFragment(fragment: JsProgramFragment) {
@@ -94,9 +95,40 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
fun merge() {
rootFunction.body.statements.apply {
this += importBlock.statements
addClassPrototypes(this)
this += declarationBlock.statements
this += initializerBlock.statements
}
rootFunction.body.resolveTemporaryNames()
}
private fun addClassPrototypes(statements: MutableList<JsStatement>) {
val visited = mutableSetOf<JsName>()
for (cls in classes.keys) {
addClassPrototypes(cls, visited, statements)
}
}
private fun addClassPrototypes(
name: JsName,
visited: MutableSet<JsName>,
statements: MutableList<JsStatement>
) {
if (!visited.add(name)) return
val cls = classes[name] ?: return
val superName = cls.superName ?: return
addClassPrototypes(superName, visited, statements)
val superclassRef = superName.makeRef()
val superPrototype = JsAstUtils.prototypeOf(superclassRef)
val superPrototypeInstance = JsInvocation(JsNameRef("create", "Object"), superPrototype)
val classRef = name.makeRef()
val prototype = JsAstUtils.prototypeOf(classRef)
statements += JsAstUtils.assignment(prototype, superPrototypeInstance).makeStmt()
val constructorRef = JsNameRef("constructor", prototype.deepCopy())
statements += JsAstUtils.assignment(constructorRef, classRef.deepCopy()).makeStmt()
}
}