[JS IR BE] Fix object instance reference

* set it in primary constructor prior to constructor body
This commit is contained in:
Roman Artemev
2018-08-23 19:26:04 +03:00
committed by romanart
parent 85a8af13cf
commit 2e5940e46d
3 changed files with 18 additions and 6 deletions
@@ -6,19 +6,22 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.isObject
import org.jetbrains.kotlin.js.backend.ast.JsFunction
open class IrFunctionToJsTransformer : BaseIrElementToJsNodeTransformer<JsFunction, JsGenerationContext> {
override fun visitSimpleFunction(declaration: IrSimpleFunction, context: JsGenerationContext): JsFunction {
val funcName = context.getNameForSymbol(declaration.symbol)
return translateFunction(declaration, funcName, context)
return translateFunction(declaration, funcName, false, context)
}
override fun visitConstructor(declaration: IrConstructor, context: JsGenerationContext): JsFunction {
assert(declaration.isPrimary)
val funcName = context.getNameForSymbol(declaration.symbol)
return translateFunction(declaration, funcName, context)
val constructedClass = declaration.parent as IrClass
return translateFunction(declaration, funcName, constructedClass.isObject, context)
}
}
@@ -100,7 +100,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
}
private fun maybeGenerateObjectInstance(): List<JsStatement> {
val instanceVarName = "${className.ident}_instance"
val instanceVarName = className.objectInstanceName()
val getInstanceFunName = "${className.ident}_getInstance"
val jsVarNode = context.currentScope.declareName(instanceVarName)
val varStmt = JsVars(JsVars.JsVar(jsVarNode))
@@ -35,12 +35,19 @@ fun jsAssignment(left: JsExpression, right: JsExpression) = JsBinaryOperation(Js
fun prototypeOf(classNameRef: JsExpression) = JsNameRef(Namer.PROTOTYPE_NAME, classNameRef)
fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerationContext): JsFunction {
fun translateFunction(declaration: IrFunction, name: JsName?, isObjectConstructor: Boolean, context: JsGenerationContext): JsFunction {
val functionScope = JsFunctionScope(context.currentScope, "scope for ${name ?: "annon"}")
val functionContext = context.newDeclaration(functionScope, declaration)
val functionParams = declaration.valueParameters.map { functionContext.getNameForSymbol(it.symbol) }
val body = declaration.body?.accept(IrElementToJsStatementTransformer(), functionContext) as? JsBlock ?: JsBlock()
val function = JsFunction(functionScope, body, "member function ${name ?: "annon"}")
val functionBody = if (isObjectConstructor) {
val instanceName = context.currentScope.declareName(name!!.objectInstanceName())
val assignObject = jsAssignment(JsNameRef(instanceName), JsThisRef())
JsBlock(assignObject.makeStmt(), body)
} else body
val function = JsFunction(functionScope, functionBody, "member function ${name ?: "annon"}")
function.name = name
@@ -74,4 +81,6 @@ fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGene
val IrFunction.isStatic: Boolean get() = this.dispatchReceiverParameter == null
fun JsStatement.asBlock() = this as? JsBlock ?: JsBlock(this)
fun JsStatement.asBlock() = this as? JsBlock ?: JsBlock(this)
fun JsName.objectInstanceName() = "${ident}_instance"