Skip to content

Commit adf6831

Browse files
tihonovcoreromanart
authored andcommitted
[JS BE] implement es6-classes's codegen
1 parent 90bcf8b commit adf6831

File tree

5 files changed

+67
-14
lines changed

5 files changed

+67
-14
lines changed

compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ import org.jetbrains.kotlin.ir.backend.js.utils.isAssociatedObjectAnnotatedAnnot
1515
import org.jetbrains.kotlin.ir.declarations.*
1616
import org.jetbrains.kotlin.ir.expressions.*
1717
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
18-
import org.jetbrains.kotlin.ir.types.classOrNull
19-
import org.jetbrains.kotlin.ir.types.classifierOrFail
20-
import org.jetbrains.kotlin.ir.types.classifierOrNull
18+
import org.jetbrains.kotlin.ir.types.*
2119
import org.jetbrains.kotlin.ir.util.*
2220
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
2321
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
2422
import org.jetbrains.kotlin.ir.visitors.acceptVoid
2523
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
24+
import org.jetbrains.kotlin.utils.addIfNotNull
2625
import java.util.*
2726

2827
fun eliminateDeadDeclarations(
@@ -320,6 +319,22 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
320319
toStringMethod.enqueue("intrinsic: jsPlus")
321320
}
322321
}
322+
context.intrinsics.jsConstruct -> {
323+
val callType = expression.getTypeArgument(0)!!
324+
val constructor = callType.getClass()!!.primaryConstructor
325+
constructor!!.enqueue("ctor call from jsConstruct-intrinsic")
326+
}
327+
context.intrinsics.es6DefaultType -> {
328+
//same as jsClass
329+
val ref = expression.getTypeArgument(0)!!.classifierOrFail.owner as IrDeclaration
330+
ref.enqueue("intrinsic: jsClass")
331+
referencedJsClasses += ref
332+
333+
//Generate klass in `val currResultType = resultType || klass`
334+
val arg = expression.getTypeArgument(0)!!
335+
val klass = arg.getClass()
336+
constructedClasses.addIfNotNull(klass)
337+
}
323338
}
324339
}
325340

compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.descriptors.ClassKind
1212
import org.jetbrains.kotlin.descriptors.Modality
1313
import org.jetbrains.kotlin.descriptors.Visibilities
1414
import org.jetbrains.kotlin.ir.backend.js.*
15+
import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase
16+
import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.*
1517
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
1618
import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport
1719
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
@@ -79,7 +81,8 @@ class ExportModelGenerator(val context: JsIrBackendContext) {
7981

8082
private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? {
8183
if (!constructor.isPrimary) return null
82-
val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + constructor.valueParameters
84+
val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) +
85+
constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER }
8386
return ExportedConstructor(allValueParameters.map { exportParameter(it) })
8487
}
8588

compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
135135
return JsBinaryOperation(JsBinaryOperator.ASG, thisRef, arguments.single())
136136
}
137137

138-
return JsInvocation(callFuncRef, listOf(thisRef) + arguments)
138+
return if (context.staticContext.backendContext.es6mode) {
139+
JsInvocation(JsNameRef("super"), arguments)
140+
} else {
141+
JsInvocation(callFuncRef, listOf(thisRef) + arguments)
142+
}
139143
}
140144

141145
override fun visitConstructorCall(expression: IrConstructorCall, context: JsGenerationContext): JsExpression {

compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
1414
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
1515
import org.jetbrains.kotlin.ir.types.IrType
1616
import org.jetbrains.kotlin.ir.types.classifierOrFail
17+
import org.jetbrains.kotlin.ir.types.classifierOrNull
1718
import org.jetbrains.kotlin.ir.types.isAny
1819
import org.jetbrains.kotlin.ir.util.*
1920
import org.jetbrains.kotlin.js.backend.ast.*
@@ -31,25 +32,55 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
3132
private val classBlock = JsGlobalBlock()
3233
private val classModel = JsIrClassModel(irClass)
3334

35+
private val es6mode = context.staticContext.backendContext.es6mode
36+
3437
fun generate(): JsStatement {
3538
assert(!irClass.descriptor.isExpect)
3639

37-
maybeGeneratePrimaryConstructor()
40+
if (!es6mode) maybeGeneratePrimaryConstructor()
3841
val transformer = IrDeclarationToJsTransformer()
3942

4043
// Properties might be lowered out of classes
4144
// We'll use IrSimpleFunction::correspondingProperty to collect them into set
4245
val properties = mutableSetOf<IrProperty>()
4346

47+
val jsClass = JsClass(name = className)
48+
49+
if (baseClass != null && !baseClass.isAny()) {
50+
jsClass.baseClass = baseClassName?.makeRef()
51+
}
52+
53+
if (es6mode) classModel.preDeclarationBlock.statements += jsClass.makeStmt()
54+
4455
for (declaration in irClass.declarations) {
4556
when (declaration) {
4657
is IrConstructor -> {
47-
classBlock.statements += declaration.accept(transformer, context)
48-
classModel.preDeclarationBlock.statements += generateInheritanceCode()
58+
if (es6mode) {
59+
declaration.accept(IrFunctionToJsTransformer(), context).let {
60+
//HACK: add superCall to Error
61+
if ((baseClass?.classifierOrNull?.owner as? IrClass)?.symbol === context.staticContext.backendContext.throwableClass) {
62+
it.body.statements.add(0, JsInvocation(JsNameRef("super")).makeStmt())
63+
}
64+
65+
if (it.body.statements.any { it !is JsEmpty }) {
66+
jsClass.constructor = it
67+
}
68+
}
69+
} else {
70+
classBlock.statements += declaration.accept(transformer, context)
71+
classModel.preDeclarationBlock.statements += generateInheritanceCode()
72+
}
4973
}
5074
is IrSimpleFunction -> {
5175
properties.addIfNotNull(declaration.correspondingPropertySymbol?.owner)
52-
generateMemberFunction(declaration)?.let { classBlock.statements += it }
76+
77+
if (es6mode) {
78+
val (_, function) = generateMemberFunction(declaration)
79+
function?.let { jsClass.members += it }
80+
} else {
81+
val (memberRef, function) = generateMemberFunction(declaration)
82+
function?.let { classBlock.statements += jsAssignment(memberRef, it.apply { name = null }).makeStmt() }
83+
}
5384
}
5485
is IrClass -> {
5586
classBlock.statements += JsClassGenerator(declaration, context).generate()
@@ -111,17 +142,15 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
111142
return this.overriddenSymbols.any { it.owner.overridesExternal() }
112143
}
113144

114-
private fun generateMemberFunction(declaration: IrSimpleFunction): JsStatement? {
115-
145+
private fun generateMemberFunction(declaration: IrSimpleFunction): Pair<JsNameRef, JsFunction?> {
116146
val memberName = context.getNameForMemberFunction(declaration.realOverrideTarget)
117147
val memberRef = JsNameRef(memberName, classPrototypeRef)
118148

119149
if (declaration.isReal && declaration.body != null) {
120150
val translatedFunction = declaration.accept(IrFunctionToJsTransformer(), context)
121-
122151
assert(!declaration.isStaticMethodOfClass)
123152

124-
return jsAssignment(memberRef, translatedFunction.apply { name = null }).makeStmt()
153+
return Pair(memberRef, translatedFunction)
125154
}
126155

127156
// do not generate code like
@@ -144,7 +173,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
144173
}
145174
}
146175

147-
return null
176+
return Pair(memberRef, null)
148177
}
149178

150179
private fun maybeGeneratePrimaryConstructor() {

compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGene
208208
val argument = expression.getValueArgument(index)
209209
val result = argument?.accept(transformer, context)
210210
if (result == null) {
211+
if (context.staticContext.backendContext.es6mode) return@mapTo JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(2))
212+
211213
assert(expression is IrFunctionAccessExpression && expression.symbol.owner.isExternalOrInheritedFromExternal())
212214
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
213215
} else

0 commit comments

Comments
 (0)