diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt index 21c742c5e94..159bd191033 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt @@ -15,14 +15,13 @@ import org.jetbrains.kotlin.ir.backend.js.utils.isAssociatedObjectAnnotatedAnnot import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.types.classOrNull -import org.jetbrains.kotlin.ir.types.classifierOrFail -import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* fun eliminateDeadDeclarations( @@ -320,6 +319,22 @@ fun usefulDeclarations(roots: Iterable, context: JsIrBackendConte toStringMethod.enqueue("intrinsic: jsPlus") } } + context.intrinsics.jsConstruct -> { + val callType = expression.getTypeArgument(0)!! + val constructor = callType.getClass()!!.primaryConstructor + constructor!!.enqueue("ctor call from jsConstruct-intrinsic") + } + context.intrinsics.es6DefaultType -> { + //same as jsClass + val ref = expression.getTypeArgument(0)!!.classifierOrFail.owner as IrDeclaration + ref.enqueue("intrinsic: jsClass") + referencedJsClasses += ref + + //Generate klass in `val currResultType = resultType || klass` + val arg = expression.getTypeArgument(0)!! + val klass = arg.getClass() + constructedClasses.addIfNotNull(klass) + } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index 7f3d8a9e262..f46155964bf 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.backend.js.* +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.* import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName @@ -79,7 +81,8 @@ class ExportModelGenerator(val context: JsIrBackendContext) { private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? { if (!constructor.isPrimary) return null - val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + constructor.valueParameters + val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + + constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER } return ExportedConstructor(allValueParameters.map { exportParameter(it) }) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index e6aab7251fe..393189a7421 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -135,7 +135,11 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer() + val jsClass = JsClass(name = className) + + if (baseClass != null && !baseClass.isAny()) { + jsClass.baseClass = baseClassName?.makeRef() + } + + if (es6mode) classModel.preDeclarationBlock.statements += jsClass.makeStmt() + for (declaration in irClass.declarations) { when (declaration) { is IrConstructor -> { - classBlock.statements += declaration.accept(transformer, context) - classModel.preDeclarationBlock.statements += generateInheritanceCode() + if (es6mode) { + declaration.accept(IrFunctionToJsTransformer(), context).let { + //HACK: add superCall to Error + if ((baseClass?.classifierOrNull?.owner as? IrClass)?.symbol === context.staticContext.backendContext.throwableClass) { + it.body.statements.add(0, JsInvocation(JsNameRef("super")).makeStmt()) + } + + if (it.body.statements.any { it !is JsEmpty }) { + jsClass.constructor = it + } + } + } else { + classBlock.statements += declaration.accept(transformer, context) + classModel.preDeclarationBlock.statements += generateInheritanceCode() + } } is IrSimpleFunction -> { properties.addIfNotNull(declaration.correspondingPropertySymbol?.owner) - generateMemberFunction(declaration)?.let { classBlock.statements += it } + + if (es6mode) { + val (_, function) = generateMemberFunction(declaration) + function?.let { jsClass.members += it } + } else { + val (memberRef, function) = generateMemberFunction(declaration) + function?.let { classBlock.statements += jsAssignment(memberRef, it.apply { name = null }).makeStmt() } + } } is IrClass -> { classBlock.statements += JsClassGenerator(declaration, context).generate() @@ -111,17 +142,15 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo return this.overriddenSymbols.any { it.owner.overridesExternal() } } - private fun generateMemberFunction(declaration: IrSimpleFunction): JsStatement? { - + private fun generateMemberFunction(declaration: IrSimpleFunction): Pair { val memberName = context.getNameForMemberFunction(declaration.realOverrideTarget) val memberRef = JsNameRef(memberName, classPrototypeRef) if (declaration.isReal && declaration.body != null) { val translatedFunction = declaration.accept(IrFunctionToJsTransformer(), context) - assert(!declaration.isStaticMethodOfClass) - return jsAssignment(memberRef, translatedFunction.apply { name = null }).makeStmt() + return Pair(memberRef, translatedFunction) } // do not generate code like @@ -144,7 +173,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo } } - return null + return Pair(memberRef, null) } private fun maybeGeneratePrimaryConstructor() { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt index f6ee14d9b0a..9f700d4e6b1 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt @@ -208,6 +208,8 @@ fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGene val argument = expression.getValueArgument(index) val result = argument?.accept(transformer, context) if (result == null) { + if (context.staticContext.backendContext.es6mode) return@mapTo JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(2)) + assert(expression is IrFunctionAccessExpression && expression.symbol.owner.isExternalOrInheritedFromExternal()) JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1)) } else