[K/JS] Use only single variant of default arguments function wrapper for exported and not-exported functions
This commit is contained in:
+209
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.common.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendContext) {
|
||||||
|
protected fun IrFunction.generateDefaultArgumentsFunctionName() =
|
||||||
|
Name.identifier("${name}\$default")
|
||||||
|
|
||||||
|
protected abstract fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean)
|
||||||
|
|
||||||
|
protected fun IrFunction.copyAttributesFrom(original: IrFunction) {
|
||||||
|
(this as? IrAttributeContainer)?.copyAttributes(original as? IrAttributeContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun IrFunction.copyReturnTypeFrom(original: IrFunction) {
|
||||||
|
returnType = original.returnType.remapTypeParameters(original.classIfConstructor, classIfConstructor)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun IrFunction.copyReceiversFrom(original: IrFunction) {
|
||||||
|
dispatchReceiverParameter = original.dispatchReceiverParameter?.copyTo(this)
|
||||||
|
extensionReceiverParameter = original.extensionReceiverParameter?.copyTo(this)
|
||||||
|
contextReceiverParametersCount = original.contextReceiverParametersCount
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun IrFunction.copyValueParametersFrom(original: IrFunction, wrapWithNullable: Boolean = true) {
|
||||||
|
valueParameters = original.valueParameters.map {
|
||||||
|
val newType = it.type.remapTypeParameters(original.classIfConstructor, classIfConstructor)
|
||||||
|
val makeNullable = wrapWithNullable && it.defaultValue != null &&
|
||||||
|
(context.ir.unfoldInlineClassType(it.type) ?: it.type) !in context.irBuiltIns.primitiveIrTypes
|
||||||
|
it.copyTo(
|
||||||
|
this,
|
||||||
|
type = if (makeNullable) newType.makeNullable() else newType,
|
||||||
|
defaultValue = if (it.defaultValue != null) {
|
||||||
|
original.factory.createExpressionBody(
|
||||||
|
IrErrorExpressionImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
it.type,
|
||||||
|
"Default Stub"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else null,
|
||||||
|
isAssignable = it.defaultValue != null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findBaseFunctionWithDefaultArgumentsFor(
|
||||||
|
declaration: IrFunction,
|
||||||
|
skipInlineMethods: Boolean,
|
||||||
|
skipExternalMethods: Boolean
|
||||||
|
): IrFunction? {
|
||||||
|
val visited = mutableSetOf<IrFunction>()
|
||||||
|
|
||||||
|
fun IrFunction.dfsImpl(): IrFunction? {
|
||||||
|
visited += this
|
||||||
|
|
||||||
|
if (isInline && skipInlineMethods) return null
|
||||||
|
if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null
|
||||||
|
|
||||||
|
if (this is IrSimpleFunction) {
|
||||||
|
overriddenSymbols.forEach { overridden ->
|
||||||
|
val base = overridden.owner
|
||||||
|
if (base !in visited) base.dfsImpl()?.let { return it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueParameters.any { it.defaultValue != null }) return this
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return declaration.dfsImpl()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun generateDefaultsFunction(
|
||||||
|
declaration: IrFunction,
|
||||||
|
skipInlineMethods: Boolean,
|
||||||
|
skipExternalMethods: Boolean,
|
||||||
|
forceSetOverrideSymbols: Boolean,
|
||||||
|
visibility: DescriptorVisibility,
|
||||||
|
useConstructorMarker: Boolean,
|
||||||
|
copiedAnnotations: List<IrConstructorCall>,
|
||||||
|
): IrFunction? {
|
||||||
|
if (skipInlineMethods && declaration.isInline) return null
|
||||||
|
if (skipExternalMethods && declaration.isExternalOrInheritedFromExternal()) return null
|
||||||
|
if (context.mapping.defaultArgumentsOriginalFunction[declaration] != null) return null
|
||||||
|
context.mapping.defaultArgumentsDispatchFunction[declaration]?.let { return it }
|
||||||
|
if (declaration is IrSimpleFunction) {
|
||||||
|
// If this is an override of a function with default arguments, produce a fake override of a default stub.
|
||||||
|
if (declaration.overriddenSymbols.any {
|
||||||
|
findBaseFunctionWithDefaultArgumentsFor(
|
||||||
|
it.owner,
|
||||||
|
skipInlineMethods,
|
||||||
|
skipExternalMethods
|
||||||
|
) != null
|
||||||
|
})
|
||||||
|
return generateDefaultsFunctionImpl(
|
||||||
|
declaration,
|
||||||
|
IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||||
|
visibility,
|
||||||
|
copiedAnnotations,
|
||||||
|
true,
|
||||||
|
useConstructorMarker,
|
||||||
|
).also { defaultsFunction ->
|
||||||
|
context.mapping.defaultArgumentsDispatchFunction[declaration] = defaultsFunction
|
||||||
|
context.mapping.defaultArgumentsOriginalFunction[defaultsFunction] = declaration
|
||||||
|
|
||||||
|
if (forceSetOverrideSymbols) {
|
||||||
|
(defaultsFunction as IrSimpleFunction).overriddenSymbols += declaration.overriddenSymbols.mapNotNull {
|
||||||
|
generateDefaultsFunction(
|
||||||
|
it.owner,
|
||||||
|
skipInlineMethods,
|
||||||
|
skipExternalMethods,
|
||||||
|
forceSetOverrideSymbols,
|
||||||
|
visibility,
|
||||||
|
useConstructorMarker,
|
||||||
|
it.owner.copyAnnotations(),
|
||||||
|
)?.symbol as IrSimpleFunctionSymbol?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Note: this is intentionally done *after* checking for overrides. While normally `override fun`s
|
||||||
|
// have no default parameters, there is an exception in case of interface delegation:
|
||||||
|
// interface I {
|
||||||
|
// fun f(x: Int = 1)
|
||||||
|
// }
|
||||||
|
// class C(val y: I) : I by y {
|
||||||
|
// // implicit `override fun f(x: Int) = y.f(x)` has a default value for `x`
|
||||||
|
// }
|
||||||
|
// Since this bug causes the metadata serializer to write the "has default value" flag into compiled
|
||||||
|
// binaries, it's way too late to fix it. Hence the workaround.
|
||||||
|
if (declaration.valueParameters.any { it.defaultValue != null }) {
|
||||||
|
return generateDefaultsFunctionImpl(
|
||||||
|
declaration,
|
||||||
|
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
|
visibility,
|
||||||
|
copiedAnnotations,
|
||||||
|
false,
|
||||||
|
useConstructorMarker,
|
||||||
|
).also {
|
||||||
|
context.mapping.defaultArgumentsDispatchFunction[declaration] = it
|
||||||
|
context.mapping.defaultArgumentsOriginalFunction[it] = declaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun generateDefaultsFunctionImpl(
|
||||||
|
declaration: IrFunction,
|
||||||
|
newOrigin: IrDeclarationOrigin,
|
||||||
|
newVisibility: DescriptorVisibility,
|
||||||
|
copiedAnnotations: List<IrConstructorCall>,
|
||||||
|
isFakeOverride: Boolean,
|
||||||
|
useConstructorMarker: Boolean,
|
||||||
|
): IrFunction {
|
||||||
|
val newFunction = when (declaration) {
|
||||||
|
is IrConstructor ->
|
||||||
|
declaration.factory.buildConstructor {
|
||||||
|
updateFrom(declaration)
|
||||||
|
origin = newOrigin
|
||||||
|
isExternal = false
|
||||||
|
isPrimary = false
|
||||||
|
isExpect = false
|
||||||
|
visibility = newVisibility
|
||||||
|
}
|
||||||
|
|
||||||
|
is IrSimpleFunction ->
|
||||||
|
declaration.factory.buildFun {
|
||||||
|
updateFrom(declaration)
|
||||||
|
name = declaration.generateDefaultArgumentsFunctionName()
|
||||||
|
origin = newOrigin
|
||||||
|
this.isFakeOverride = isFakeOverride
|
||||||
|
modality = Modality.FINAL
|
||||||
|
isExternal = false
|
||||||
|
isTailrec = false
|
||||||
|
visibility = newVisibility
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> throw IllegalStateException("Unknown function type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFunction.apply {
|
||||||
|
parent = declaration.parent
|
||||||
|
generateDefaultArgumentStubFrom(declaration, useConstructorMarker)
|
||||||
|
// TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant.
|
||||||
|
annotations += copiedAnnotations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+88
-193
@@ -41,7 +41,8 @@ open class DefaultArgumentStubGenerator(
|
|||||||
open val context: CommonBackendContext,
|
open val context: CommonBackendContext,
|
||||||
private val skipInlineMethods: Boolean = true,
|
private val skipInlineMethods: Boolean = true,
|
||||||
private val skipExternalMethods: Boolean = false,
|
private val skipExternalMethods: Boolean = false,
|
||||||
private val forceSetOverrideSymbols: Boolean = true
|
private val forceSetOverrideSymbols: Boolean = true,
|
||||||
|
private val factory: DefaultArgumentFunctionFactory = MaskedDefaultArgumentFunctionFactory(context)
|
||||||
) : DeclarationTransformer {
|
) : DeclarationTransformer {
|
||||||
override val withLocalDeclarations: Boolean get() = true
|
override val withLocalDeclarations: Boolean get() = true
|
||||||
|
|
||||||
@@ -55,34 +56,21 @@ open class DefaultArgumentStubGenerator(
|
|||||||
|
|
||||||
protected open fun IrFunction.resolveAnnotations(): List<IrConstructorCall> = copyAnnotations()
|
protected open fun IrFunction.resolveAnnotations(): List<IrConstructorCall> = copyAnnotations()
|
||||||
|
|
||||||
private fun lower(irFunction: IrFunction): List<IrFunction>? {
|
protected open fun IrFunction.generateDefaultStubBody(originalDeclaration: IrFunction): IrBody {
|
||||||
val newIrFunction =
|
val newIrFunction = this
|
||||||
irFunction.generateDefaultsFunction(
|
|
||||||
context,
|
|
||||||
skipInlineMethods,
|
|
||||||
skipExternalMethods,
|
|
||||||
forceSetOverrideSymbols,
|
|
||||||
defaultArgumentStubVisibility(irFunction),
|
|
||||||
useConstructorMarker(irFunction),
|
|
||||||
irFunction.resolveAnnotations()
|
|
||||||
) ?: return null
|
|
||||||
if (newIrFunction.isFakeOverride) {
|
|
||||||
return listOf(irFunction, newIrFunction)
|
|
||||||
}
|
|
||||||
|
|
||||||
log { "$irFunction -> $newIrFunction" }
|
|
||||||
val builder = context.createIrBuilder(newIrFunction.symbol)
|
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||||
|
log { "$originalDeclaration -> $newIrFunction" }
|
||||||
|
|
||||||
newIrFunction.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
return context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||||
statements += builder.irBlockBody(newIrFunction) {
|
statements += builder.irBlockBody(newIrFunction) {
|
||||||
val params = mutableListOf<IrValueDeclaration>()
|
val params = mutableListOf<IrValueDeclaration>()
|
||||||
val variables = mutableMapOf<IrValueSymbol, IrValueSymbol>()
|
val variables = mutableMapOf<IrValueSymbol, IrValueSymbol>()
|
||||||
|
|
||||||
irFunction.dispatchReceiverParameter?.let {
|
originalDeclaration.dispatchReceiverParameter?.let {
|
||||||
variables[it.symbol] = newIrFunction.dispatchReceiverParameter?.symbol!!
|
variables[it.symbol] = newIrFunction.dispatchReceiverParameter?.symbol!!
|
||||||
}
|
}
|
||||||
|
|
||||||
irFunction.extensionReceiverParameter?.let {
|
originalDeclaration.extensionReceiverParameter?.let {
|
||||||
variables[it.symbol] = newIrFunction.extensionReceiverParameter?.symbol!!
|
variables[it.symbol] = newIrFunction.extensionReceiverParameter?.symbol!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,23 +84,23 @@ open class DefaultArgumentStubGenerator(
|
|||||||
//
|
//
|
||||||
// works correctly so that `f() { "OK" }` returns "OK" and
|
// works correctly so that `f() { "OK" }` returns "OK" and
|
||||||
// `f()` throws a NullPointerException.
|
// `f()` throws a NullPointerException.
|
||||||
irFunction.valueParameters.forEach {
|
originalDeclaration.valueParameters.forEach {
|
||||||
variables[it.symbol] = newIrFunction.valueParameters[it.index].symbol
|
variables[it.symbol] = newIrFunction.valueParameters[it.index].symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
generateSuperCallHandlerCheckIfNeeded(irFunction, newIrFunction)
|
generateSuperCallHandlerCheckIfNeeded(originalDeclaration, newIrFunction)
|
||||||
|
|
||||||
val intAnd = this@DefaultArgumentStubGenerator.context.ir.symbols.getBinaryOperator(
|
val intAnd = this@DefaultArgumentStubGenerator.context.ir.symbols.getBinaryOperator(
|
||||||
OperatorNameConventions.AND, context.irBuiltIns.intType, context.irBuiltIns.intType
|
OperatorNameConventions.AND, context.irBuiltIns.intType, context.irBuiltIns.intType
|
||||||
)
|
)
|
||||||
var sourceParameterIndex = -1
|
var sourceParameterIndex = -1
|
||||||
for (valueParameter in irFunction.valueParameters) {
|
for (valueParameter in originalDeclaration.valueParameters) {
|
||||||
if (!valueParameter.isMovedReceiver()) {
|
if (!valueParameter.isMovedReceiver()) {
|
||||||
++sourceParameterIndex
|
++sourceParameterIndex
|
||||||
}
|
}
|
||||||
val parameter = newIrFunction.valueParameters[valueParameter.index]
|
val parameter = newIrFunction.valueParameters[valueParameter.index]
|
||||||
val remapped = valueParameter.defaultValue?.let { defaultValue ->
|
val remapped = valueParameter.defaultValue?.let { defaultValue ->
|
||||||
val mask = irGet(newIrFunction.valueParameters[irFunction.valueParameters.size + valueParameter.index / 32])
|
val mask = irGet(newIrFunction.valueParameters[originalDeclaration.valueParameters.size + valueParameter.index / 32])
|
||||||
val bit = irInt(1 shl (sourceParameterIndex % 32))
|
val bit = irInt(1 shl (sourceParameterIndex % 32))
|
||||||
val defaultFlag =
|
val defaultFlag =
|
||||||
irCallOp(intAnd, context.irBuiltIns.intType, mask, bit)
|
irCallOp(intAnd, context.irBuiltIns.intType, mask, bit)
|
||||||
@@ -128,8 +116,8 @@ open class DefaultArgumentStubGenerator(
|
|||||||
variables[valueParameter.symbol] = remapped.symbol
|
variables[valueParameter.symbol] = remapped.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
when (irFunction) {
|
when (originalDeclaration) {
|
||||||
is IrConstructor -> +irDelegatingConstructorCall(irFunction).apply {
|
is IrConstructor -> +irDelegatingConstructorCall(originalDeclaration).apply {
|
||||||
passTypeArgumentsFrom(newIrFunction.parentAsClass)
|
passTypeArgumentsFrom(newIrFunction.parentAsClass)
|
||||||
// This is for Kotlin/Native, which differs from the other backends in that constructors
|
// This is for Kotlin/Native, which differs from the other backends in that constructors
|
||||||
// apparently do have dispatch receivers (though *probably* not type arguments, but copy
|
// apparently do have dispatch receivers (though *probably* not type arguments, but copy
|
||||||
@@ -138,12 +126,30 @@ open class DefaultArgumentStubGenerator(
|
|||||||
dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) }
|
dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) }
|
||||||
params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) }
|
params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) }
|
||||||
}
|
}
|
||||||
is IrSimpleFunction -> +irReturn(dispatchToImplementation(irFunction, newIrFunction, params))
|
is IrSimpleFunction -> +irReturn(dispatchToImplementation(originalDeclaration, newIrFunction, params))
|
||||||
else -> error("Unknown function declaration")
|
else -> error("Unknown function declaration")
|
||||||
}
|
}
|
||||||
}.statements
|
}.statements
|
||||||
}
|
}
|
||||||
return listOf(irFunction, newIrFunction)
|
}
|
||||||
|
|
||||||
|
private fun lower(irFunction: IrFunction): List<IrFunction>? {
|
||||||
|
val newIrFunction =
|
||||||
|
factory.generateDefaultsFunction(
|
||||||
|
irFunction,
|
||||||
|
skipInlineMethods,
|
||||||
|
skipExternalMethods,
|
||||||
|
forceSetOverrideSymbols,
|
||||||
|
defaultArgumentStubVisibility(irFunction),
|
||||||
|
useConstructorMarker(irFunction),
|
||||||
|
irFunction.resolveAnnotations(),
|
||||||
|
) ?: return null
|
||||||
|
|
||||||
|
return listOf(irFunction, newIrFunction).also {
|
||||||
|
if (!newIrFunction.isFakeOverride) {
|
||||||
|
newIrFunction.body = newIrFunction.generateDefaultStubBody(irFunction)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,45 +259,24 @@ open class DefaultArgumentStubGenerator(
|
|||||||
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
|
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.findBaseFunctionWithDefaultArguments(skipInlineMethods: Boolean, skipExternalMethods: Boolean): IrFunction? {
|
|
||||||
|
|
||||||
val visited = mutableSetOf<IrFunction>()
|
|
||||||
|
|
||||||
fun IrFunction.dfsImpl(): IrFunction? {
|
|
||||||
visited += this
|
|
||||||
|
|
||||||
if (isInline && skipInlineMethods) return null
|
|
||||||
if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null
|
|
||||||
|
|
||||||
if (this is IrSimpleFunction) {
|
|
||||||
overriddenSymbols.forEach { overridden ->
|
|
||||||
val base = overridden.owner
|
|
||||||
if (base !in visited) base.dfsImpl()?.let { return it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valueParameters.any { it.defaultValue != null }) return this
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return dfsImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
open class DefaultParameterInjector(
|
open class DefaultParameterInjector(
|
||||||
open val context: CommonBackendContext,
|
open val context: CommonBackendContext,
|
||||||
private val skipInline: Boolean = true,
|
protected val skipInline: Boolean = true,
|
||||||
private val skipExternalMethods: Boolean = false,
|
protected val skipExternalMethods: Boolean = false,
|
||||||
private val forceSetOverrideSymbols: Boolean = true
|
protected val forceSetOverrideSymbols: Boolean = true,
|
||||||
|
protected val factory: DefaultArgumentFunctionFactory = MaskedDefaultArgumentFunctionFactory(context),
|
||||||
) : IrElementTransformerVoid(), BodyLoweringPass {
|
) : IrElementTransformerVoid(), BodyLoweringPass {
|
||||||
|
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
irBody.transformChildrenVoid(this)
|
irBody.transformChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
|
||||||
|
return (0 until functionAccess.valueArgumentsCount).count { functionAccess.getValueArgument(it) != null } != functionAccess.symbol.owner.valueParameters.size
|
||||||
|
}
|
||||||
|
|
||||||
private fun <T : IrFunctionAccessExpression> visitFunctionAccessExpression(expression: T, builder: (IrFunctionSymbol) -> T): T {
|
private fun <T : IrFunctionAccessExpression> visitFunctionAccessExpression(expression: T, builder: (IrFunctionSymbol) -> T): T {
|
||||||
val argumentsCount = (0 until expression.valueArgumentsCount).count { expression.getValueArgument(it) != null }
|
if (!shouldReplaceWithSyntheticFunction(expression))
|
||||||
if (argumentsCount == expression.symbol.owner.valueParameters.size)
|
|
||||||
return expression
|
return expression
|
||||||
|
|
||||||
val (symbol, params) = parametersForCall(expression) ?: return expression
|
val (symbol, params) = parametersForCall(expression) ?: return expression
|
||||||
@@ -346,7 +331,13 @@ open class DefaultParameterInjector(
|
|||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
return visitFunctionAccessExpression(expression) {
|
return visitFunctionAccessExpression(expression) {
|
||||||
with(expression) {
|
with(expression) {
|
||||||
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, it as IrConstructorSymbol, LoweredStatementOrigins.DEFAULT_DISPATCH_CALL)
|
IrConstructorCallImpl.fromSymbolOwner(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
type,
|
||||||
|
it as IrConstructorSymbol,
|
||||||
|
LoweredStatementOrigins.DEFAULT_DISPATCH_CALL
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +370,7 @@ open class DefaultParameterInjector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
|
open protected fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
|
||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
val declaration = expression.symbol.owner
|
val declaration = expression.symbol.owner
|
||||||
@@ -388,21 +379,24 @@ open class DefaultParameterInjector(
|
|||||||
// in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering).
|
// in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering).
|
||||||
// Calling the fake override on an implementation of that interface would then result in a call to a method
|
// Calling the fake override on an implementation of that interface would then result in a call to a method
|
||||||
// that does not actually exist as DefaultImpls is not part of the inheritance hierarchy.
|
// that does not actually exist as DefaultImpls is not part of the inheritance hierarchy.
|
||||||
val baseFunction = declaration.findBaseFunctionWithDefaultArguments(skipInline, skipExternalMethods)
|
val baseFunction = factory.findBaseFunctionWithDefaultArgumentsFor(declaration, skipInline, skipExternalMethods)
|
||||||
val stubFunction = baseFunction?.generateDefaultsFunction(
|
val stubFunction = baseFunction?.let {
|
||||||
context,
|
factory.generateDefaultsFunction(
|
||||||
skipInline,
|
it,
|
||||||
skipExternalMethods,
|
skipInline,
|
||||||
forceSetOverrideSymbols,
|
skipExternalMethods,
|
||||||
defaultArgumentStubVisibility(declaration),
|
forceSetOverrideSymbols,
|
||||||
useConstructorMarker(declaration),
|
defaultArgumentStubVisibility(declaration),
|
||||||
baseFunction.copyAnnotations()
|
useConstructorMarker(declaration),
|
||||||
) ?: return null
|
baseFunction.copyAnnotations(),
|
||||||
|
)
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
log { "$declaration -> $stubFunction" }
|
log { "$declaration -> $stubFunction" }
|
||||||
|
|
||||||
val realArgumentsNumber = declaration.valueParameters.size
|
val realArgumentsNumber = declaration.valueParameters.size
|
||||||
val maskValues = IntArray((declaration.valueParameters.size + 31) / 32)
|
val maskValues = IntArray((declaration.valueParameters.size + 31) / 32)
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
((if (isStatic(expression.symbol.owner) && stubFunction.extensionReceiverParameter != null) 1 else 0) +
|
((if (isStatic(expression.symbol.owner) && stubFunction.extensionReceiverParameter != null) 1 else 0) +
|
||||||
stubFunction.valueParameters.size - realArgumentsNumber - maskValues.size) in listOf(0, 1)
|
stubFunction.valueParameters.size - realArgumentsNumber - maskValues.size) in listOf(0, 1)
|
||||||
@@ -410,6 +404,7 @@ open class DefaultParameterInjector(
|
|||||||
"argument count mismatch: expected $realArgumentsNumber arguments + ${maskValues.size} masks + optional handler/marker, " +
|
"argument count mismatch: expected $realArgumentsNumber arguments + ${maskValues.size} masks + optional handler/marker, " +
|
||||||
"got ${stubFunction.valueParameters.size} total in ${stubFunction.render()}"
|
"got ${stubFunction.valueParameters.size} total in ${stubFunction.render()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceParameterIndex = -1
|
var sourceParameterIndex = -1
|
||||||
val valueParametersPrefix =
|
val valueParametersPrefix =
|
||||||
if (isStatic(expression.symbol.owner))
|
if (isStatic(expression.symbol.owner))
|
||||||
@@ -500,134 +495,34 @@ class DefaultParameterPatchOverridenSymbolsLowering(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.generateDefaultsFunction(
|
private class MaskedDefaultArgumentFunctionFactory(context: CommonBackendContext) : DefaultArgumentFunctionFactory(context) {
|
||||||
context: CommonBackendContext,
|
override fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean) {
|
||||||
skipInlineMethods: Boolean,
|
copyAttributesFrom(original)
|
||||||
skipExternalMethods: Boolean,
|
copyTypeParametersFrom(original)
|
||||||
forceSetOverrideSymbols: Boolean,
|
copyReturnTypeFrom(original)
|
||||||
visibility: DescriptorVisibility,
|
copyReceiversFrom(original)
|
||||||
useConstructorMarker: Boolean,
|
copyValueParametersFrom(original)
|
||||||
copiedAnnotations: List<IrConstructorCall>
|
|
||||||
): IrFunction? {
|
|
||||||
if (skipInlineMethods && isInline) return null
|
|
||||||
if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null
|
|
||||||
if (context.mapping.defaultArgumentsOriginalFunction[this] != null) return null
|
|
||||||
context.mapping.defaultArgumentsDispatchFunction[this]?.let { return it }
|
|
||||||
if (this is IrSimpleFunction) {
|
|
||||||
// If this is an override of a function with default arguments, produce a fake override of a default stub.
|
|
||||||
if (overriddenSymbols.any { it.owner.findBaseFunctionWithDefaultArguments(skipInlineMethods, skipExternalMethods) != null })
|
|
||||||
return generateDefaultsFunctionImpl(
|
|
||||||
context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility, copiedAnnotations, true, useConstructorMarker
|
|
||||||
).also { defaultsFunction ->
|
|
||||||
context.mapping.defaultArgumentsDispatchFunction[this] = defaultsFunction
|
|
||||||
context.mapping.defaultArgumentsOriginalFunction[defaultsFunction] = this
|
|
||||||
|
|
||||||
if (forceSetOverrideSymbols) {
|
for (i in 0 until (original.valueParameters.size + 31) / 32) {
|
||||||
(defaultsFunction as IrSimpleFunction).overriddenSymbols += overriddenSymbols.mapNotNull {
|
addValueParameter(
|
||||||
it.owner.generateDefaultsFunction(
|
"mask$i".synthesizedString,
|
||||||
context,
|
context.irBuiltIns.intType,
|
||||||
skipInlineMethods,
|
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION
|
||||||
skipExternalMethods,
|
)
|
||||||
forceSetOverrideSymbols,
|
|
||||||
visibility,
|
|
||||||
useConstructorMarker,
|
|
||||||
it.owner.copyAnnotations()
|
|
||||||
)?.symbol as IrSimpleFunctionSymbol?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Note: this is intentionally done *after* checking for overrides. While normally `override fun`s
|
|
||||||
// have no default parameters, there is an exception in case of interface delegation:
|
|
||||||
// interface I {
|
|
||||||
// fun f(x: Int = 1)
|
|
||||||
// }
|
|
||||||
// class C(val y: I) : I by y {
|
|
||||||
// // implicit `override fun f(x: Int) = y.f(x)` has a default value for `x`
|
|
||||||
// }
|
|
||||||
// Since this bug causes the metadata serializer to write the "has default value" flag into compiled
|
|
||||||
// binaries, it's way too late to fix it. Hence the workaround.
|
|
||||||
if (valueParameters.any { it.defaultValue != null }) {
|
|
||||||
return generateDefaultsFunctionImpl(
|
|
||||||
context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility, copiedAnnotations, false, useConstructorMarker
|
|
||||||
).also {
|
|
||||||
context.mapping.defaultArgumentsDispatchFunction[this] = it
|
|
||||||
context.mapping.defaultArgumentsOriginalFunction[it] = this
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrFunction.generateDefaultsFunctionImpl(
|
if (useConstructorMarker) {
|
||||||
context: CommonBackendContext,
|
val markerType = context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable()
|
||||||
newOrigin: IrDeclarationOrigin,
|
addValueParameter("marker".synthesizedString, markerType, IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER)
|
||||||
newVisibility: DescriptorVisibility,
|
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||||
copiedAnnotations: List<IrConstructorCall>,
|
addValueParameter(
|
||||||
isFakeOverride: Boolean,
|
"handler".synthesizedString,
|
||||||
useConstructorMarker: Boolean
|
context.irBuiltIns.anyNType,
|
||||||
): IrFunction {
|
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION
|
||||||
val newFunction = when (this) {
|
)
|
||||||
is IrConstructor ->
|
}
|
||||||
factory.buildConstructor {
|
|
||||||
updateFrom(this@generateDefaultsFunctionImpl)
|
|
||||||
origin = newOrigin
|
|
||||||
isExternal = false
|
|
||||||
isPrimary = false
|
|
||||||
isExpect = false
|
|
||||||
visibility = newVisibility
|
|
||||||
}
|
|
||||||
is IrSimpleFunction ->
|
|
||||||
factory.buildFun {
|
|
||||||
updateFrom(this@generateDefaultsFunctionImpl)
|
|
||||||
name = Name.identifier("${this@generateDefaultsFunctionImpl.name}\$default")
|
|
||||||
origin = newOrigin
|
|
||||||
this.isFakeOverride = isFakeOverride
|
|
||||||
modality = Modality.FINAL
|
|
||||||
isExternal = false
|
|
||||||
isTailrec = false
|
|
||||||
visibility = newVisibility
|
|
||||||
}
|
|
||||||
else -> throw IllegalStateException("Unknown function type")
|
|
||||||
}
|
|
||||||
(newFunction as? IrAttributeContainer)?.copyAttributes(this@generateDefaultsFunctionImpl as? IrAttributeContainer)
|
|
||||||
newFunction.copyTypeParametersFrom(this)
|
|
||||||
newFunction.parent = parent
|
|
||||||
newFunction.returnType = returnType.remapTypeParameters(classIfConstructor, newFunction.classIfConstructor)
|
|
||||||
newFunction.dispatchReceiverParameter = dispatchReceiverParameter?.copyTo(newFunction)
|
|
||||||
newFunction.extensionReceiverParameter = extensionReceiverParameter?.copyTo(newFunction)
|
|
||||||
newFunction.contextReceiverParametersCount = contextReceiverParametersCount
|
|
||||||
|
|
||||||
newFunction.valueParameters = valueParameters.map {
|
|
||||||
val newType = it.type.remapTypeParameters(classIfConstructor, newFunction.classIfConstructor)
|
|
||||||
val makeNullable = it.defaultValue != null &&
|
|
||||||
(context.ir.unfoldInlineClassType(it.type) ?: it.type) !in context.irBuiltIns.primitiveIrTypes
|
|
||||||
it.copyTo(
|
|
||||||
newFunction,
|
|
||||||
type = if (makeNullable) newType.makeNullable() else newType,
|
|
||||||
defaultValue = if (it.defaultValue != null) {
|
|
||||||
factory.createExpressionBody(IrErrorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, "Default Stub"))
|
|
||||||
} else null,
|
|
||||||
isAssignable = it.defaultValue != null
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0 until (valueParameters.size + 31) / 32) {
|
|
||||||
newFunction.addValueParameter("mask$i".synthesizedString, context.irBuiltIns.intType, IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION)
|
|
||||||
}
|
|
||||||
if (useConstructorMarker) {
|
|
||||||
val markerType = context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable()
|
|
||||||
newFunction.addValueParameter("marker".synthesizedString, markerType, IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER)
|
|
||||||
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
|
||||||
newFunction.addValueParameter(
|
|
||||||
"handler".synthesizedString,
|
|
||||||
context.irBuiltIns.anyNType,
|
|
||||||
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant.
|
|
||||||
newFunction.annotations += copiedAnnotations
|
|
||||||
return newFunction
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrValueParameter.isMovedReceiver() =
|
private fun IrValueParameter.isMovedReceiver() =
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ object JsLoweredDeclarationOrigin : IrDeclarationOrigin {
|
|||||||
object BRIDGE_PROPERTY_ACCESSOR : IrDeclarationOriginImpl("BRIDGE_PROPERTY_ACCESSOR")
|
object BRIDGE_PROPERTY_ACCESSOR : IrDeclarationOriginImpl("BRIDGE_PROPERTY_ACCESSOR")
|
||||||
object OBJECT_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("OBJECT_GET_INSTANCE_FUNCTION")
|
object OBJECT_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("OBJECT_GET_INSTANCE_FUNCTION")
|
||||||
object JS_SHADOWED_EXPORT : IrDeclarationOriginImpl("JS_SHADOWED_EXPORT")
|
object JS_SHADOWED_EXPORT : IrDeclarationOriginImpl("JS_SHADOWED_EXPORT")
|
||||||
|
object JS_SUPER_CONTEXT_PARAMETER : IrDeclarationOriginImpl("JS_SUPER_CONTEXT_PARAMETER")
|
||||||
object JS_SHADOWED_DEFAULT_PARAMETER : IrDeclarationOriginImpl("JS_SHADOWED_DEFAULT_PARAMETER")
|
object JS_SHADOWED_DEFAULT_PARAMETER : IrDeclarationOriginImpl("JS_SHADOWED_DEFAULT_PARAMETER")
|
||||||
object ENUM_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("ENUM_GET_INSTANCE_FUNCTION")
|
object ENUM_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("ENUM_GET_INSTANCE_FUNCTION")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
// TODO: Should we drop operator intrinsics in favor of IrDynamicOperatorExpression?
|
// TODO: Should we drop operator intrinsics in favor of IrDynamicOperatorExpression?
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
|
val void = getInternalProperty("VOID")
|
||||||
val globalThis = getInternalProperty("globalThis")
|
val globalThis = getInternalProperty("globalThis")
|
||||||
|
|
||||||
// Equality operations:
|
// Equality operations:
|
||||||
@@ -140,7 +141,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
|
|
||||||
// Other:
|
// Other:
|
||||||
|
|
||||||
val jsObjectCreate = getInternalFunction("objectCreate") // Object.create
|
|
||||||
val jsCode = getInternalFunction("js") // js("<code>")
|
val jsCode = getInternalFunction("js") // js("<code>")
|
||||||
val jsHashCode = getInternalFunction("hashCode")
|
val jsHashCode = getInternalFunction("hashCode")
|
||||||
val jsGetNumberHashCode = getInternalFunction("getNumberHashCode")
|
val jsGetNumberHashCode = getInternalFunction("getNumberHashCode")
|
||||||
@@ -313,11 +313,13 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
|
|
||||||
val jsArraySlice = getInternalFunction("slice")
|
val jsArraySlice = getInternalFunction("slice")
|
||||||
|
|
||||||
|
val jsCall = getInternalFunction("jsCall")
|
||||||
val jsBind = getInternalFunction("jsBind")
|
val jsBind = getInternalFunction("jsBind")
|
||||||
|
|
||||||
// TODO move to IntrinsifyCallsLowering
|
// TODO move to IntrinsifyCallsLowering
|
||||||
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify"))
|
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify"))
|
||||||
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
|
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
|
||||||
|
val jsNameAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsName"))
|
||||||
|
|
||||||
val jsImplicitExportAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsImplicitExport"))
|
val jsImplicitExportAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsImplicitExport"))
|
||||||
|
|
||||||
@@ -341,6 +343,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
val jsCharSequenceLength = getInternalFunction("charSequenceLength")
|
val jsCharSequenceLength = getInternalFunction("charSequenceLength")
|
||||||
val jsCharSequenceSubSequence = getInternalFunction("charSequenceSubSequence")
|
val jsCharSequenceSubSequence = getInternalFunction("charSequenceSubSequence")
|
||||||
|
|
||||||
|
val jsContexfulRef = getInternalFunction("jsContextfulRef")
|
||||||
val jsBoxIntrinsic = getInternalFunction("boxIntrinsic")
|
val jsBoxIntrinsic = getInternalFunction("boxIntrinsic")
|
||||||
val jsUnboxIntrinsic = getInternalFunction("unboxIntrinsic")
|
val jsUnboxIntrinsic = getInternalFunction("unboxIntrinsic")
|
||||||
|
|
||||||
@@ -350,10 +353,12 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
val readSharedBox = getInternalFunction("sharedBoxRead")
|
val readSharedBox = getInternalFunction("sharedBoxRead")
|
||||||
val writeSharedBox = getInternalFunction("sharedBoxWrite")
|
val writeSharedBox = getInternalFunction("sharedBoxWrite")
|
||||||
|
|
||||||
val jsUndefined = getInternalFunction("jsUndefined")
|
|
||||||
|
|
||||||
val linkageErrorSymbol = getInternalFunction("throwLinkageError")
|
val linkageErrorSymbol = getInternalFunction("throwLinkageError")
|
||||||
|
|
||||||
|
val jsPrototypeOfSymbol = getInternalFunction("protoOf")
|
||||||
|
val jsDefinePropertySymbol = getInternalFunction("defineProp")
|
||||||
|
val jsObjectCreateSymbol = getInternalFunction("objectCreate") // Object.create
|
||||||
|
|
||||||
// Helpers:
|
// Helpers:
|
||||||
|
|
||||||
private fun getInternalFunction(name: String) =
|
private fun getInternalFunction(name: String) =
|
||||||
|
|||||||
@@ -555,7 +555,7 @@ private val defaultArgumentPatchOverridesPhase = makeDeclarationTransformerPhase
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val defaultParameterInjectorPhase = makeBodyLoweringPhase(
|
private val defaultParameterInjectorPhase = makeBodyLoweringPhase(
|
||||||
{ context -> DefaultParameterInjector(context, skipExternalMethods = true, forceSetOverrideSymbols = false) },
|
::JsDefaultParameterInjector,
|
||||||
name = "DefaultParameterInjector",
|
name = "DefaultParameterInjector",
|
||||||
description = "Replace callsite with default parameters with corresponding stub function",
|
description = "Replace callsite with default parameters with corresponding stub function",
|
||||||
prerequisite = setOf(interopCallableReferenceLoweringPhase, innerClassesLoweringPhase)
|
prerequisite = setOf(interopCallableReferenceLoweringPhase, innerClassesLoweringPhase)
|
||||||
@@ -567,19 +567,6 @@ private val defaultParameterCleanerPhase = makeDeclarationTransformerPhase(
|
|||||||
description = "Clean default parameters up"
|
description = "Clean default parameters up"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
private val exportedDefaultParameterStubPhase = makeDeclarationTransformerPhase(
|
|
||||||
::ExportedDefaultParameterStub,
|
|
||||||
name = "ExportedDefaultParameterStub",
|
|
||||||
description = "Generates default stub for exported entity and renames the non-default counterpart"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val jsDefaultCallbackGeneratorPhase = makeBodyLoweringPhase(
|
|
||||||
::JsDefaultCallbackGenerator,
|
|
||||||
name = "JsDefaultCallbackGenerator",
|
|
||||||
description = "Build binding for super calls with default parameters"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val varargLoweringPhase = makeBodyLoweringPhase(
|
private val varargLoweringPhase = makeBodyLoweringPhase(
|
||||||
::VarargLowering,
|
::VarargLowering,
|
||||||
name = "VarargLowering",
|
name = "VarargLowering",
|
||||||
@@ -811,6 +798,7 @@ private val cleanupLoweringPhase = makeBodyLoweringPhase(
|
|||||||
name = "CleanupLowering",
|
name = "CleanupLowering",
|
||||||
description = "Clean up IR before codegen"
|
description = "Clean up IR before codegen"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val moveOpenClassesToSeparatePlaceLowering = makeCustomJsModulePhase(
|
private val moveOpenClassesToSeparatePlaceLowering = makeCustomJsModulePhase(
|
||||||
{ context, module ->
|
{ context, module ->
|
||||||
if (context.granularity == JsGenerationGranularity.PER_FILE)
|
if (context.granularity == JsGenerationGranularity.PER_FILE)
|
||||||
@@ -899,12 +887,10 @@ val loweringList = listOf<Lowering>(
|
|||||||
computeStringTrimPhase,
|
computeStringTrimPhase,
|
||||||
privateMembersLoweringPhase,
|
privateMembersLoweringPhase,
|
||||||
privateMemberUsagesLoweringPhase,
|
privateMemberUsagesLoweringPhase,
|
||||||
exportedDefaultParameterStubPhase,
|
|
||||||
defaultArgumentStubGeneratorPhase,
|
defaultArgumentStubGeneratorPhase,
|
||||||
defaultArgumentPatchOverridesPhase,
|
defaultArgumentPatchOverridesPhase,
|
||||||
defaultParameterInjectorPhase,
|
defaultParameterInjectorPhase,
|
||||||
defaultParameterCleanerPhase,
|
defaultParameterCleanerPhase,
|
||||||
jsDefaultCallbackGeneratorPhase,
|
|
||||||
throwableSuccessorsLoweringPhase,
|
throwableSuccessorsLoweringPhase,
|
||||||
es6AddInternalParametersToConstructorPhase,
|
es6AddInternalParametersToConstructorPhase,
|
||||||
es6ConstructorLowering,
|
es6ConstructorLowering,
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ class IrToJs(
|
|||||||
|
|
||||||
val globalNames = NameTable<String>(nameGenerator.staticNames)
|
val globalNames = NameTable<String>(nameGenerator.staticNames)
|
||||||
val exporter = ExportModelToJsStatements(
|
val exporter = ExportModelToJsStatements(
|
||||||
nameGenerator,
|
staticContext,
|
||||||
declareNewNamespace = { globalNames.declareFreshName(it, it) }
|
declareNewNamespace = { globalNames.declareFreshName(it, it) }
|
||||||
)
|
)
|
||||||
exportedDeclarations.forEach {
|
exportedDeclarations.forEach {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
fun eliminateDeadDeclarations(
|
fun eliminateDeadDeclarations(
|
||||||
modules: Iterable<IrModuleFragment>,
|
modules: Iterable<IrModuleFragment>,
|
||||||
@@ -116,6 +117,7 @@ private fun buildRoots(modules: Iterable<IrModuleFragment>, context: JsIrBackend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addIfNotNull(context.intrinsics.void.owner.backingField)
|
||||||
addAll(context.testFunsPerFile.values)
|
addAll(context.testFunsPerFile.values)
|
||||||
addAll(context.additionalExportedDeclarations)
|
addAll(context.additionalExportedDeclarations)
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-3
@@ -67,9 +67,9 @@ internal class JsUsefulDeclarationProcessor(
|
|||||||
val ref = expression.getTypeArgument(0)?.classOrNull ?: context.irBuiltIns.anyClass
|
val ref = expression.getTypeArgument(0)?.classOrNull ?: context.irBuiltIns.anyClass
|
||||||
referencedJsClassesFromExpressions += ref.owner
|
referencedJsClassesFromExpressions += ref.owner
|
||||||
}
|
}
|
||||||
context.intrinsics.jsObjectCreate -> {
|
context.intrinsics.jsObjectCreateSymbol -> {
|
||||||
val classToCreate = expression.getTypeArgument(0)!!.classifierOrFail.owner as IrClass
|
val classToCreate = expression.getTypeArgument(0)!!.classifierOrFail.owner as IrClass
|
||||||
classToCreate.enqueue(data, "intrinsic: jsObjectCreate")
|
classToCreate.enqueue(data, "intrinsic: jsObjectCreateSymbol")
|
||||||
constructedClasses += classToCreate
|
constructedClasses += classToCreate
|
||||||
}
|
}
|
||||||
context.intrinsics.jsEquals -> {
|
context.intrinsics.jsEquals -> {
|
||||||
@@ -129,11 +129,29 @@ internal class JsUsefulDeclarationProcessor(
|
|||||||
if (irClass.containsMetadata()) {
|
if (irClass.containsMetadata()) {
|
||||||
when {
|
when {
|
||||||
irClass.isObject -> context.intrinsics.metadataObjectConstructorSymbol.owner.enqueue(irClass, "object metadata")
|
irClass.isObject -> context.intrinsics.metadataObjectConstructorSymbol.owner.enqueue(irClass, "object metadata")
|
||||||
|
|
||||||
irClass.isInterface -> {
|
irClass.isInterface -> {
|
||||||
context.intrinsics.implementSymbol.owner.enqueue(irClass, "interface metadata")
|
context.intrinsics.implementSymbol.owner.enqueue(irClass, "interface metadata")
|
||||||
context.intrinsics.metadataInterfaceConstructorSymbol.owner.enqueue(irClass, "interface metadata")
|
context.intrinsics.metadataInterfaceConstructorSymbol.owner.enqueue(irClass, "interface metadata")
|
||||||
}
|
}
|
||||||
else -> context.intrinsics.metadataClassConstructorSymbol.owner.enqueue(irClass, "class metadata")
|
|
||||||
|
else -> {
|
||||||
|
context.intrinsics.metadataClassConstructorSymbol.owner.enqueue(irClass, "class metadata")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!irClass.isExpect && !irClass.isExternal && !irClass.defaultType.isAny()) {
|
||||||
|
if (!irClass.isInterface) {
|
||||||
|
context.intrinsics.jsPrototypeOfSymbol.owner.enqueue(irClass, "class metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irClass.superTypes.any { !it.isInterface() }) {
|
||||||
|
context.intrinsics.jsObjectCreateSymbol.owner.enqueue(irClass, "class metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irClass.isInner || irClass.isObject) {
|
||||||
|
context.intrinsics.jsDefinePropertySymbol.owner.enqueue(irClass, "class metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
context.intrinsics.setMetadataForSymbol.owner.enqueue(irClass, "metadata")
|
context.intrinsics.setMetadataForSymbol.owner.enqueue(irClass, "metadata")
|
||||||
@@ -146,6 +164,12 @@ internal class JsUsefulDeclarationProcessor(
|
|||||||
if (irFunction.isReal && irFunction.body != null) {
|
if (irFunction.isReal && irFunction.body != null) {
|
||||||
irFunction.parentClassOrNull?.takeIf { it.isInterface }?.enqueue(irFunction, "interface default method is used")
|
irFunction.parentClassOrNull?.takeIf { it.isInterface }?.enqueue(irFunction, "interface default method is used")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val property = irFunction.correspondingPropertySymbol?.owner ?: return
|
||||||
|
|
||||||
|
if (property.isExported(context) || property.isOverriddenExternal()) {
|
||||||
|
context.intrinsics.jsDefinePropertySymbol.owner.enqueue(irFunction, "property for export")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrClass.containsMetadata(): Boolean =
|
private fun IrClass.containsMetadata(): Boolean =
|
||||||
|
|||||||
+6
-3
@@ -218,14 +218,17 @@ abstract class UsefulDeclarationProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.isAccessorForOverriddenExternalField(): Boolean {
|
protected fun IrSimpleFunction.isAccessorForOverriddenExternalField(): Boolean {
|
||||||
return correspondingPropertySymbol?.owner?.isExternalOrOverriddenExternal() ?: false
|
return correspondingPropertySymbol?.owner?.isExternalOrOverriddenExternal() ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrProperty.isExternalOrOverriddenExternal(): Boolean {
|
protected fun IrProperty.isExternalOrOverriddenExternal(): Boolean {
|
||||||
return isEffectivelyExternal() || overriddenSymbols.any { it.owner.isExternalOrOverriddenExternal() }
|
return isEffectivelyExternal() || isOverriddenExternal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun IrProperty.isOverriddenExternal(): Boolean =
|
||||||
|
overriddenSymbols.any { it.owner.isExternalOrOverriddenExternal() }
|
||||||
|
|
||||||
protected open fun handleAssociatedObjects(): Unit = Unit
|
protected open fun handleAssociatedObjects(): Unit = Unit
|
||||||
|
|
||||||
fun collectDeclarations(rootDeclarations: Iterable<IrDeclaration>): Set<IrDeclaration> {
|
fun collectDeclarations(rootDeclarations: Iterable<IrDeclaration>): Set<IrDeclaration> {
|
||||||
|
|||||||
+8
-3
@@ -86,13 +86,15 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
|||||||
ExportedFunction(
|
ExportedFunction(
|
||||||
function.getExportedIdentifier(),
|
function.getExportedIdentifier(),
|
||||||
returnType = exportType(function.returnType),
|
returnType = exportType(function.returnType),
|
||||||
parameters = (listOfNotNull(function.extensionReceiverParameter) + function.valueParameters).map { exportParameter(it) },
|
|
||||||
typeParameters = function.typeParameters.map(::exportTypeParameter),
|
typeParameters = function.typeParameters.map(::exportTypeParameter),
|
||||||
isMember = parent is IrClass,
|
isMember = parent is IrClass,
|
||||||
isStatic = function.isStaticMethodOfClass,
|
isStatic = function.isStaticMethodOfClass,
|
||||||
isAbstract = parent is IrClass && !parent.isInterface && function.modality == Modality.ABSTRACT,
|
isAbstract = parent is IrClass && !parent.isInterface && function.modality == Modality.ABSTRACT,
|
||||||
isProtected = function.visibility == DescriptorVisibilities.PROTECTED,
|
isProtected = function.visibility == DescriptorVisibilities.PROTECTED,
|
||||||
ir = function
|
ir = function,
|
||||||
|
parameters = (listOfNotNull(function.extensionReceiverParameter) + function.valueParameters)
|
||||||
|
.filter { it.shouldBeExported() }
|
||||||
|
.map { exportParameter(it) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,6 +364,10 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
|||||||
return isInterface && !isExternal || isJsImplicitExport()
|
return isInterface && !isExternal || isJsImplicitExport()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrValueParameter.shouldBeExported(): Boolean {
|
||||||
|
return origin != JsLoweredDeclarationOrigin.JS_SUPER_CONTEXT_PARAMETER
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrClass.shouldContainImplementationOfMagicProperty(superTypes: Iterable<IrType>): Boolean {
|
private fun IrClass.shouldContainImplementationOfMagicProperty(superTypes: Iterable<IrType>): Boolean {
|
||||||
return !isExternal && superTypes.any {
|
return !isExternal && superTypes.any {
|
||||||
val superClass = it.classOrNull?.owner ?: return@any false
|
val superClass = it.classOrNull?.owner ?: return@any false
|
||||||
@@ -640,7 +646,6 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
|||||||
if (function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME ||
|
if (function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME ||
|
||||||
function.origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR ||
|
function.origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR ||
|
||||||
function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME ||
|
function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME ||
|
||||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
|
||||||
function.origin == JsLoweredDeclarationOrigin.OBJECT_GET_INSTANCE_FUNCTION ||
|
function.origin == JsLoweredDeclarationOrigin.OBJECT_GET_INSTANCE_FUNCTION ||
|
||||||
function.origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT ||
|
function.origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT ||
|
||||||
function.origin == JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION
|
function.origin == JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION
|
||||||
|
|||||||
+9
-15
@@ -5,21 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.export
|
package org.jetbrains.kotlin.ir.backend.js.export
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsAstUtils
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.defineProperty
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.prototypeOf
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsElementAccess
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.IrNamer
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
|
||||||
import org.jetbrains.kotlin.ir.util.companionObject
|
import org.jetbrains.kotlin.ir.util.companionObject
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
|
||||||
|
|
||||||
class ExportModelToJsStatements(
|
class ExportModelToJsStatements(
|
||||||
private val namer: IrNamer,
|
private val namer: JsStaticContext,
|
||||||
private val declareNewNamespace: (String) -> String
|
private val declareNewNamespace: (String) -> String
|
||||||
) {
|
) {
|
||||||
private val namespaceToRefMap = mutableMapOf<String, JsNameRef>()
|
private val namespaceToRefMap = mutableMapOf<String, JsNameRef>()
|
||||||
@@ -88,7 +81,7 @@ class ExportModelToJsStatements(
|
|||||||
require(namespace != null) { "Only namespaced properties are allowed" }
|
require(namespace != null) { "Only namespaced properties are allowed" }
|
||||||
val getter = declaration.irGetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) }
|
val getter = declaration.irGetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) }
|
||||||
val setter = declaration.irSetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) }
|
val setter = declaration.irSetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) }
|
||||||
listOf(defineProperty(namespace, declaration.name, getter, setter).makeStmt())
|
listOf(defineProperty(namespace, declaration.name, getter, setter, namer).makeStmt())
|
||||||
}
|
}
|
||||||
|
|
||||||
is ErrorDeclaration -> emptyList()
|
is ErrorDeclaration -> emptyList()
|
||||||
@@ -98,7 +91,7 @@ class ExportModelToJsStatements(
|
|||||||
val newNameSpace = jsElementAccess(declaration.name, namespace)
|
val newNameSpace = jsElementAccess(declaration.name, namespace)
|
||||||
val getter = JsNameRef(namer.getNameForStaticDeclaration(declaration.irGetter))
|
val getter = JsNameRef(namer.getNameForStaticDeclaration(declaration.irGetter))
|
||||||
val staticsExport = declaration.nestedClasses.flatMap { generateDeclarationExport(it, newNameSpace, esModules) }
|
val staticsExport = declaration.nestedClasses.flatMap { generateDeclarationExport(it, newNameSpace, esModules) }
|
||||||
listOf(defineProperty(namespace, declaration.name, getter, null).makeStmt()) + staticsExport
|
listOf(defineProperty(namespace, declaration.name, getter, null, namer).makeStmt()) + staticsExport
|
||||||
}
|
}
|
||||||
|
|
||||||
is ExportedRegularClass -> {
|
is ExportedRegularClass -> {
|
||||||
@@ -106,7 +99,7 @@ class ExportModelToJsStatements(
|
|||||||
val newNameSpace = if (namespace != null)
|
val newNameSpace = if (namespace != null)
|
||||||
jsElementAccess(declaration.name, namespace)
|
jsElementAccess(declaration.name, namespace)
|
||||||
else
|
else
|
||||||
JsNameRef(Namer.PROTOTYPE_NAME, namer.getNameForClass(declaration.ir).makeRef())
|
prototypeOf(namer.getNameForClass(declaration.ir).makeRef(), namer)
|
||||||
val name = namer.getNameForStaticDeclaration(declaration.ir)
|
val name = namer.getNameForStaticDeclaration(declaration.ir)
|
||||||
val klassExport =
|
val klassExport =
|
||||||
if (esModules) {
|
if (esModules) {
|
||||||
@@ -173,14 +166,15 @@ class ExportModelToJsStatements(
|
|||||||
blockStatements.add(JsReturn(bindConstructor.makeRef()))
|
blockStatements.add(JsReturn(bindConstructor.makeRef()))
|
||||||
|
|
||||||
return defineProperty(
|
return defineProperty(
|
||||||
prototypeOf(outerClassRef),
|
prototypeOf(outerClassRef, namer),
|
||||||
name,
|
name,
|
||||||
JsFunction(
|
JsFunction(
|
||||||
emptyScope,
|
emptyScope,
|
||||||
JsBlock(*blockStatements.toTypedArray()),
|
JsBlock(*blockStatements.toTypedArray()),
|
||||||
"inner class '$name' getter"
|
"inner class '$name' getter"
|
||||||
),
|
),
|
||||||
null
|
null,
|
||||||
|
namer
|
||||||
).makeStmt()
|
).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ object JsIrBuilder {
|
|||||||
fun buildGetValue(symbol: IrValueSymbol) =
|
fun buildGetValue(symbol: IrValueSymbol) =
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, JsStatementOrigins.SYNTHESIZED_STATEMENT)
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, JsStatementOrigins.SYNTHESIZED_STATEMENT)
|
||||||
|
|
||||||
|
fun buildSetValue(symbol: IrValueSymbol, value: IrExpression) =
|
||||||
|
IrSetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, value, JsStatementOrigins.SYNTHESIZED_STATEMENT)
|
||||||
|
|
||||||
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) =
|
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) =
|
||||||
IrSetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, JsStatementOrigins.SYNTHESIZED_STATEMENT)
|
IrSetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, JsStatementOrigins.SYNTHESIZED_STATEMENT)
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -227,10 +227,14 @@ class AutoboxingTransformer(context: JsCommonBackendContext) : AbstractValueUsag
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (expression.symbol == irBuiltIns.eqeqeqSymbol && expression.allArgumentsHaveType(irBuiltIns.charType)) {
|
return if (
|
||||||
return expression.apply { transformChildrenVoid() }
|
expression.symbol != irBuiltIns.eqeqeqSymbol ||
|
||||||
|
!expression.allArgumentsHaveType(irBuiltIns.charType) &&
|
||||||
|
expression.origin != IrStatementOrigin.SYNTHETIC_NOT_AUTOBOXED_CHECK
|
||||||
|
) {
|
||||||
|
super.visitCall(expression)
|
||||||
} else {
|
} else {
|
||||||
return super.visitCall(expression)
|
expression.apply { transformChildrenVoid() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-154
@@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsAnnotations
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
|
|
||||||
private fun IrConstructorCall.isAnnotation(name: FqName): Boolean {
|
|
||||||
return symbol.owner.parentAsClass.fqNameWhenAvailable == name
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExportedDefaultParameterStub(val context: JsIrBackendContext) : DeclarationTransformer {
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.createDefaultResolutionExpression(
|
|
||||||
fromParameter: IrValueParameter,
|
|
||||||
toParameter: IrValueParameter,
|
|
||||||
): IrExpression? {
|
|
||||||
return fromParameter.defaultValue?.let { defaultValue ->
|
|
||||||
irIfThenElse(
|
|
||||||
toParameter.type,
|
|
||||||
irEqeqeq(
|
|
||||||
irGet(toParameter, context.irBuiltIns.anyNType),
|
|
||||||
irCall(this@ExportedDefaultParameterStub.context.intrinsics.jsUndefined)
|
|
||||||
),
|
|
||||||
defaultValue.expression,
|
|
||||||
irGet(toParameter)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrConstructor.introduceDefaultResolution(): IrConstructor {
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
|
||||||
|
|
||||||
val variables = mutableMapOf<IrValueParameter, IrValueDeclaration>()
|
|
||||||
|
|
||||||
val defaultResolutionStatements = valueParameters.mapNotNull { valueParameter ->
|
|
||||||
irBuilder.createDefaultResolutionExpression(valueParameter, valueParameter)?.let { initializer ->
|
|
||||||
JsIrBuilder.buildVar(
|
|
||||||
valueParameter.type,
|
|
||||||
this@introduceDefaultResolution,
|
|
||||||
name = valueParameter.name.asString(),
|
|
||||||
initializer = initializer
|
|
||||||
).also {
|
|
||||||
variables[valueParameter] = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variables.isNotEmpty()) {
|
|
||||||
body?.transformChildren(VariableRemapper(variables), null)
|
|
||||||
|
|
||||||
body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
|
||||||
statements += defaultResolutionStatements
|
|
||||||
statements += body?.statements ?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return also {
|
|
||||||
valueParameters.forEach {
|
|
||||||
if (it.defaultValue != null) {
|
|
||||||
it.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
|
||||||
if (declaration !is IrFunction) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!declaration.hasStableJsName(context)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!declaration.valueParameters.any { it.defaultValue != null }) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration is IrConstructor) {
|
|
||||||
return listOf(declaration.introduceDefaultResolution())
|
|
||||||
}
|
|
||||||
|
|
||||||
val exportedDefaultStubFun = context.irFactory.buildFun {
|
|
||||||
updateFrom(declaration)
|
|
||||||
name = declaration.name
|
|
||||||
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
|
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration.isExported(context)) {
|
|
||||||
context.additionalExportedDeclarations.add(exportedDefaultStubFun)
|
|
||||||
}
|
|
||||||
|
|
||||||
exportedDefaultStubFun.parent = declaration.parent
|
|
||||||
exportedDefaultStubFun.copyParameterDeclarationsFrom(declaration)
|
|
||||||
exportedDefaultStubFun.returnType = declaration.returnType.remapTypeParameters(declaration, exportedDefaultStubFun)
|
|
||||||
exportedDefaultStubFun.valueParameters.forEach {
|
|
||||||
if (it.defaultValue != null) {
|
|
||||||
it.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER
|
|
||||||
}
|
|
||||||
|
|
||||||
it.defaultValue = null
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
declaration.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT
|
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(exportedDefaultStubFun.symbol, exportedDefaultStubFun.startOffset, exportedDefaultStubFun.endOffset)
|
|
||||||
exportedDefaultStubFun.body = irBuilder.irBlockBody(exportedDefaultStubFun) {
|
|
||||||
+irReturn(irCall(declaration).apply {
|
|
||||||
passTypeArgumentsFrom(declaration)
|
|
||||||
dispatchReceiver = exportedDefaultStubFun.dispatchReceiverParameter?.let { irGet(it) }
|
|
||||||
extensionReceiver = exportedDefaultStubFun.extensionReceiverParameter?.let { irGet(it) }
|
|
||||||
|
|
||||||
declaration.valueParameters.forEachIndexed { index, irValueParameter ->
|
|
||||||
val exportedParameter = exportedDefaultStubFun.valueParameters[index]
|
|
||||||
val value = createDefaultResolutionExpression(irValueParameter, exportedParameter) ?: irGet(exportedParameter)
|
|
||||||
putValueArgument(index, value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
val (exportAnnotations, irrelevantAnnotations) = declaration.annotations.map { it.deepCopyWithSymbols(declaration as? IrDeclarationParent) }
|
|
||||||
.partition {
|
|
||||||
it.isAnnotation(JsAnnotations.jsExportFqn) || (it.isAnnotation(JsAnnotations.jsNameFqn))
|
|
||||||
}
|
|
||||||
|
|
||||||
declaration.annotations = irrelevantAnnotations
|
|
||||||
exportedDefaultStubFun.annotations = exportAnnotations
|
|
||||||
|
|
||||||
return listOf(exportedDefaultStubFun, declaration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentFunctionFactory
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.copyTypeParametersFrom
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.isTopLevel
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
class JsDefaultArgumentFunctionFactory(override val context: JsIrBackendContext) : DefaultArgumentFunctionFactory(context) {
|
||||||
|
override fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean) {
|
||||||
|
copyAttributesFrom(original)
|
||||||
|
copyTypeParametersFrom(original)
|
||||||
|
copyReturnTypeFrom(original)
|
||||||
|
copyReceiversFrom(original)
|
||||||
|
copyValueParametersFrom(original, wrapWithNullable = false)
|
||||||
|
|
||||||
|
if (!original.isTopLevel) {
|
||||||
|
introduceContextParam()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.introduceContextParam() = addValueParameter {
|
||||||
|
name = Name.identifier("\$super")
|
||||||
|
type = parentAsClass.defaultType
|
||||||
|
origin = JsLoweredDeclarationOrigin.JS_SUPER_CONTEXT_PARAMETER
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+215
-85
@@ -1,117 +1,247 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentStubGenerator
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.LoweredStatementOrigins
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsAnnotations
|
import org.jetbrains.kotlin.ir.backend.js.utils.JsAnnotations
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
|
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irImplicitCast
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : DefaultArgumentStubGenerator(context, true, true, false) {
|
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
|
||||||
|
DefaultArgumentStubGenerator(
|
||||||
|
context,
|
||||||
|
skipExternalMethods = true,
|
||||||
|
forceSetOverrideSymbols = false,
|
||||||
|
factory = JsDefaultArgumentFunctionFactory(context)
|
||||||
|
) {
|
||||||
|
|
||||||
override fun needSpecialDispatch(irFunction: IrSimpleFunction) = irFunction.isOverridableOrOverrides
|
private fun IrBuilderWithScope.createDefaultResolutionExpression(
|
||||||
|
defaultExpression: IrExpression?,
|
||||||
override fun IrFunction.resolveAnnotations(): List<IrConstructorCall> = copyAnnotationsWhen {
|
toParameter: IrValueParameter,
|
||||||
!(isAnnotation(JsAnnotations.jsExportFqn) || isAnnotation(JsAnnotations.jsNameFqn))
|
): IrExpression? {
|
||||||
}
|
return defaultExpression?.let {
|
||||||
|
irIfThenElse(
|
||||||
override fun IrBlockBodyBuilder.generateHandleCall(
|
toParameter.type,
|
||||||
handlerDeclaration: IrValueParameter,
|
irEqeqeqWithoutBox(
|
||||||
oldIrFunction: IrFunction,
|
irGet(toParameter, toParameter.type),
|
||||||
newIrFunction: IrFunction,
|
this@JsDefaultArgumentStubGenerator.context.getVoid()
|
||||||
params: MutableList<IrValueDeclaration>
|
),
|
||||||
): IrExpression {
|
it,
|
||||||
val paramCount = oldIrFunction.valueParameters.size
|
irGet(toParameter)
|
||||||
val invokeFunctionN = resolveInvoke(paramCount)
|
)
|
||||||
|
|
||||||
return irCall(invokeFunctionN, IrStatementOrigin.INVOKE).apply {
|
|
||||||
dispatchReceiver = irImplicitCast(irGet(handlerDeclaration), invokeFunctionN.dispatchReceiverParameter!!.type)
|
|
||||||
// NOTE: currently we do not have a syntax to perform super extension call
|
|
||||||
// that's why we've used to just fail with an exception in case we have extension function in for JS IR compilation
|
|
||||||
// TODO: that was overkill, however, we still need to revisit this issue later on
|
|
||||||
params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.prepareToBeUsedIn(function: IrFunction): IrExpression {
|
private fun IrBuilderWithScope.createResolutionStatement(
|
||||||
return deepCopyWithVariables().also {
|
parameter: IrValueParameter,
|
||||||
it.patchDeclarationParents(function)
|
defaultExpression: IrExpression?,
|
||||||
|
): IrSetValue? {
|
||||||
|
return createDefaultResolutionExpression(defaultExpression, parameter)?.let {
|
||||||
|
JsIrBuilder.buildSetValue(parameter.symbol, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveInvoke(paramCount: Int): IrSimpleFunction {
|
private fun IrFunction.introduceDefaultResolution(): IrFunction {
|
||||||
assert(paramCount > 0)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
val functionKlass = context.ir.symbols.functionN(paramCount).owner
|
|
||||||
return functionKlass.declarations.filterIsInstance<IrSimpleFunction>().first { it.name == Name.identifier("invoke") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JsDefaultCallbackGenerator(val context: JsIrBackendContext): BodyLoweringPass {
|
val variables = mutableMapOf<IrValueParameter, IrValueParameter>()
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
|
||||||
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
super.visitCall(expression)
|
|
||||||
if (expression.origin != LoweredStatementOrigins.DEFAULT_DISPATCH_CALL || expression.superQualifierSymbol == null) return expression
|
|
||||||
|
|
||||||
val binding = buildBoundSuperCall(expression)
|
valueParameters = valueParameters.map { param ->
|
||||||
|
param.takeIf { it.defaultValue != null }
|
||||||
|
?.copyTo(this, isAssignable = true, origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER)
|
||||||
|
?.also { new -> variables[param] = new } ?: param
|
||||||
|
}
|
||||||
|
|
||||||
expression.putValueArgument(expression.valueArgumentsCount - 1, binding)
|
val defaultResolutionStatements = valueParameters.mapNotNull {
|
||||||
|
irBuilder.createResolutionStatement(it, it.defaultValue?.expression)
|
||||||
|
}
|
||||||
|
|
||||||
return expression
|
if (variables.isNotEmpty()) {
|
||||||
|
body?.transformChildren(VariableRemapper(variables), null)
|
||||||
|
|
||||||
|
body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||||
|
statements += defaultResolutionStatements
|
||||||
|
statements += body?.statements ?: emptyList()
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildBoundSuperCall(irCall: IrCall): IrExpression {
|
|
||||||
|
|
||||||
val originalFunction = context.mapping.defaultArgumentsOriginalFunction[irCall.symbol.owner]!!
|
|
||||||
|
|
||||||
val reference = irCall.run {
|
|
||||||
IrFunctionReferenceImpl(
|
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
context.irBuiltIns.anyType,
|
|
||||||
originalFunction.symbol,
|
|
||||||
typeArgumentsCount = 0,
|
|
||||||
valueArgumentsCount = originalFunction.valueParameters.size,
|
|
||||||
reflectionTarget = originalFunction.symbol,
|
|
||||||
origin = JsStatementOrigins.BIND_CALL
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return irCall.run {
|
return also {
|
||||||
IrCallImpl(
|
context.mapping.defaultArgumentsDispatchFunction[it] = it
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
context.irBuiltIns.anyType,
|
|
||||||
context.intrinsics.jsBind,
|
|
||||||
valueArgumentsCount = 2,
|
|
||||||
typeArgumentsCount = 0,
|
|
||||||
origin = JsStatementOrigins.BIND_CALL,
|
|
||||||
superQualifierSymbol = superQualifierSymbol
|
|
||||||
)
|
|
||||||
}.apply {
|
|
||||||
putValueArgument(0, irCall.dispatchReceiver?.deepCopyWithSymbols())
|
|
||||||
putValueArgument(1, reference)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||||
|
if (declaration !is IrFunction || declaration.isExternalOrInheritedFromExternal()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration.hasDefaultArgs() && (declaration is IrConstructor || declaration.isTopLevel)) {
|
||||||
|
return listOf(declaration.introduceDefaultResolution())
|
||||||
|
}
|
||||||
|
|
||||||
|
val (originalFun, defaultFunStub) = super.transformFlat(declaration) ?: return null
|
||||||
|
|
||||||
|
if (originalFun !is IrFunction || defaultFunStub !is IrFunction) {
|
||||||
|
return listOf(originalFun, defaultFunStub)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defaultFunStub.isFakeOverride) {
|
||||||
|
with(defaultFunStub) {
|
||||||
|
valueParameters.forEach {
|
||||||
|
if (it.defaultValue != null) {
|
||||||
|
it.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER
|
||||||
|
}
|
||||||
|
it.defaultValue = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalFun.isExported(context)) {
|
||||||
|
context.additionalExportedDeclarations.add(defaultFunStub)
|
||||||
|
|
||||||
|
if (!originalFun.hasAnnotation(JsAnnotations.jsNameFqn)) {
|
||||||
|
annotations += originalFun.generateJsNameAnnotationCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val (exportAnnotations, irrelevantAnnotations) = originalFun.annotations
|
||||||
|
.map { it.deepCopyWithSymbols(originalFun as? IrDeclarationParent) }
|
||||||
|
.partition {
|
||||||
|
it.isAnnotation(JsAnnotations.jsExportFqn) || (it.isAnnotation(JsAnnotations.jsNameFqn))
|
||||||
|
}
|
||||||
|
|
||||||
|
originalFun.annotations = irrelevantAnnotations
|
||||||
|
defaultFunStub.annotations += exportAnnotations
|
||||||
|
originalFun.origin = JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT
|
||||||
|
|
||||||
|
return listOf(originalFun, defaultFunStub)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun IrFunction.generateDefaultStubBody(originalDeclaration: IrFunction): IrBody {
|
||||||
|
val ctx = context
|
||||||
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
|
|
||||||
|
val variables = mutableMapOf<IrValueParameter, IrValueDeclaration>().apply {
|
||||||
|
originalDeclaration.dispatchReceiverParameter?.let {
|
||||||
|
set(it, dispatchReceiverParameter!!)
|
||||||
|
}
|
||||||
|
originalDeclaration.extensionReceiverParameter?.let {
|
||||||
|
set(it, extensionReceiverParameter!!)
|
||||||
|
}
|
||||||
|
originalDeclaration.valueParameters.forEachIndexed { index, param ->
|
||||||
|
set(param, valueParameters[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return irBuilder.irBlockBody(this) {
|
||||||
|
+valueParameters.zip(originalDeclaration.valueParameters)
|
||||||
|
.mapNotNull { (new, original) ->
|
||||||
|
createResolutionStatement(
|
||||||
|
new,
|
||||||
|
original.defaultValue?.expression?.transform(VariableRemapper(variables), null),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val wrappedFunctionCall = irCall(originalDeclaration, JsStatementOrigins.IMPLEMENTATION_DELEGATION_CALL).apply {
|
||||||
|
passTypeArgumentsFrom(originalDeclaration)
|
||||||
|
dispatchReceiver = dispatchReceiverParameter?.let { irGet(it) }
|
||||||
|
extensionReceiver = extensionReceiverParameter?.let { irGet(it) }
|
||||||
|
|
||||||
|
originalDeclaration.valueParameters.forEachIndexed { index, irValueParameter ->
|
||||||
|
putValueArgument(index, irGet(variables[irValueParameter] ?: valueParameters[index]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var superContextValueParam: IrValueParameter? = null
|
||||||
|
|
||||||
|
val superFunCall = runIf(wrappedFunctionCall.dispatchReceiver != null && !originalDeclaration.isExported(ctx)) {
|
||||||
|
val superContext = valueParameters.last().also {
|
||||||
|
superContextValueParam = it
|
||||||
|
}
|
||||||
|
val realOverrideTarget = originalDeclaration.realOverrideTarget.takeIf {
|
||||||
|
it !is IrOverridableMember || it.modality !== Modality.ABSTRACT
|
||||||
|
}
|
||||||
|
if (realOverrideTarget?.parentClassOrNull?.isInterface == true) {
|
||||||
|
irCall(realOverrideTarget).apply {
|
||||||
|
extensionReceiver = wrappedFunctionCall.extensionReceiver?.deepCopyWithSymbols()
|
||||||
|
(0 until wrappedFunctionCall.valueArgumentsCount).forEach {
|
||||||
|
putValueArgument(it, wrappedFunctionCall.getValueArgument(it)?.deepCopyWithSymbols())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
irCall(ctx.intrinsics.jsCall).apply {
|
||||||
|
putValueArgument(0, wrappedFunctionCall.dispatchReceiver!!.deepCopyWithSymbols())
|
||||||
|
putValueArgument(
|
||||||
|
1,
|
||||||
|
irCall(ctx.intrinsics.jsContexfulRef).apply {
|
||||||
|
putValueArgument(0, irGet(superContext))
|
||||||
|
putValueArgument(1, irRawFunctionReference(ctx.dynamicType, originalDeclaration.symbol))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
putValueArgument(2, irVararg(ctx.dynamicType, buildList {
|
||||||
|
addIfNotNull(wrappedFunctionCall.extensionReceiver?.deepCopyWithSymbols())
|
||||||
|
(0 until wrappedFunctionCall.valueArgumentsCount).forEach {
|
||||||
|
addIfNotNull(wrappedFunctionCall.getValueArgument(it)?.deepCopyWithSymbols())
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+irReturn(
|
||||||
|
if (superFunCall == null) {
|
||||||
|
wrappedFunctionCall
|
||||||
|
} else {
|
||||||
|
irIfThenElse(
|
||||||
|
originalDeclaration.returnType,
|
||||||
|
irEqeqeqWithoutBox(irGet(superContextValueParam!!), ctx.getVoid()),
|
||||||
|
wrappedFunctionCall,
|
||||||
|
superFunCall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.generateJsNameAnnotationCall(): IrConstructorCall {
|
||||||
|
val builder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
|
|
||||||
|
return with(context) {
|
||||||
|
builder.irCall(intrinsics.jsNameAnnotationSymbol.constructors.single())
|
||||||
|
.apply {
|
||||||
|
putValueArgument(
|
||||||
|
0,
|
||||||
|
IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irBuiltIns.stringType, name.identifier)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrConstructorCall.isAnnotation(name: FqName): Boolean {
|
||||||
|
return symbol.owner.parentAsClass.fqNameWhenAvailable == name
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.hasDefaultArgs(): Boolean =
|
||||||
|
valueParameters.any { it.defaultValue != null }
|
||||||
}
|
}
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.copyAnnotations
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.isTopLevel
|
||||||
|
import org.jetbrains.kotlin.ir.util.isVararg
|
||||||
|
|
||||||
|
class JsDefaultParameterInjector(override val context: JsIrBackendContext) :
|
||||||
|
DefaultParameterInjector(
|
||||||
|
context,
|
||||||
|
skipExternalMethods = true,
|
||||||
|
forceSetOverrideSymbols = false,
|
||||||
|
factory = JsDefaultArgumentFunctionFactory(context)
|
||||||
|
) {
|
||||||
|
override fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? =
|
||||||
|
if (irParameter.isVararg && !irParameter.hasDefaultValue()) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
context.getVoid()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
|
||||||
|
return super.shouldReplaceWithSyntheticFunction(functionAccess) || functionAccess.symbol.owner.run {
|
||||||
|
origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT &&
|
||||||
|
!isTopLevel &&
|
||||||
|
functionAccess.origin != JsStatementOrigins.IMPLEMENTATION_DELEGATION_CALL &&
|
||||||
|
isExported(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
|
||||||
|
val stubFunction = factory.findBaseFunctionWithDefaultArgumentsFor(declaration, skipInline, skipExternalMethods)?.let {
|
||||||
|
factory.generateDefaultsFunction(
|
||||||
|
it,
|
||||||
|
skipInline,
|
||||||
|
skipExternalMethods,
|
||||||
|
forceSetOverrideSymbols,
|
||||||
|
defaultArgumentStubVisibility(declaration),
|
||||||
|
useConstructorMarker(declaration),
|
||||||
|
it.copyAnnotations(),
|
||||||
|
)
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
return stubFunction.symbol to buildList {
|
||||||
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
|
val declaredParameter = stubFunction.valueParameters[i]
|
||||||
|
val actualParameter = expression.getValueArgument(i)
|
||||||
|
add(actualParameter ?: nullConst(startOffset, endOffset, declaredParameter))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expression is IrCall && stubFunction.hasSuperContextParameter()) {
|
||||||
|
add(expression.superQualifierSymbol?.prototypeOf() ?: context.getVoid())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.hasSuperContextParameter(): Boolean {
|
||||||
|
return valueParameters.lastOrNull()?.origin == JsLoweredDeclarationOrigin.JS_SUPER_CONTEXT_PARAMETER
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrClassSymbol.prototypeOf(): IrExpression {
|
||||||
|
return IrCallImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
context.dynamicType,
|
||||||
|
context.intrinsics.jsPrototypeOfSymbol,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
).apply {
|
||||||
|
putValueArgument(
|
||||||
|
0,
|
||||||
|
IrCallImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
context.dynamicType,
|
||||||
|
context.intrinsics.jsClass,
|
||||||
|
1,
|
||||||
|
0
|
||||||
|
).apply {
|
||||||
|
putTypeArgument(0, owner.defaultType)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrValueParameter.hasDefaultValue(): Boolean =
|
||||||
|
origin == JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER
|
||||||
|
}
|
||||||
|
|
||||||
+5
@@ -24,6 +24,11 @@ class JsPropertyAccessorInlineLowering(
|
|||||||
if (!isTopLevel && !context.icCompatibleIr2Js.incrementalCacheEnabled)
|
if (!isTopLevel && !context.icCompatibleIr2Js.incrementalCacheEnabled)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
// Just undefined value
|
||||||
|
if (symbol == context.intrinsics.void) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: teach the deserializer to load constant property initializers
|
// TODO: teach the deserializer to load constant property initializers
|
||||||
if (context.icCompatibleIr2Js.isCompatible) {
|
if (context.icCompatibleIr2Js.isCompatible) {
|
||||||
val accessFile = accessContainer.fileOrNull ?: return false
|
val accessFile = accessContainer.fileOrNull ?: return false
|
||||||
|
|||||||
+4
-1
@@ -52,8 +52,11 @@ private val JsPackage = FqName("kotlin.js")
|
|||||||
|
|
||||||
private val JsIntrinsicFqName = FqName("kotlin.js.JsIntrinsic")
|
private val JsIntrinsicFqName = FqName("kotlin.js.JsIntrinsic")
|
||||||
|
|
||||||
|
private fun IrDeclaration.isPlacedInsideInternalPackage() =
|
||||||
|
(parent as? IrPackageFragment)?.fqName == JsPackage
|
||||||
|
|
||||||
private fun isIntrinsic(declaration: IrDeclaration): Boolean =
|
private fun isIntrinsic(declaration: IrDeclaration): Boolean =
|
||||||
declaration is IrSimpleFunction && (declaration.parent as? IrPackageFragment)?.fqName == JsPackage &&
|
declaration is IrSimpleFunction && declaration.isPlacedInsideInternalPackage() &&
|
||||||
declaration.annotations.any { it.symbol.owner.constructedClass.fqNameWhenAvailable == JsIntrinsicFqName }
|
declaration.annotations.any { it.symbol.owner.constructedClass.fqNameWhenAvailable == JsIntrinsicFqName }
|
||||||
|
|
||||||
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
|
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio
|
|||||||
private fun generateFactoryBody(constructor: IrConstructor, irClass: IrClass, stub: IrSimpleFunction, delegate: IrSimpleFunction) {
|
private fun generateFactoryBody(constructor: IrConstructor, irClass: IrClass, stub: IrSimpleFunction, delegate: IrSimpleFunction) {
|
||||||
stub.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
stub.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||||
val type = irClass.defaultType
|
val type = irClass.defaultType
|
||||||
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
|
val createFunctionIntrinsic = context.intrinsics.jsObjectCreateSymbol
|
||||||
val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic, type, listOf(type))
|
val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic, type, listOf(type))
|
||||||
val irDelegateCall = JsIrBuilder.buildCall(delegate.symbol, type).also { call ->
|
val irDelegateCall = JsIrBuilder.buildCall(delegate.symbol, type).also { call ->
|
||||||
for (i in 0 until stub.typeParameters.size) {
|
for (i in 0 until stub.typeParameters.size) {
|
||||||
|
|||||||
+2
-3
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.getVoid
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||||
@@ -28,10 +29,8 @@ class ThrowableLowering(
|
|||||||
|
|
||||||
private val throwableConstructors = context.throwableConstructors
|
private val throwableConstructors = context.throwableConstructors
|
||||||
private val newThrowableFunction = context.newThrowableSymbol
|
private val newThrowableFunction = context.newThrowableSymbol
|
||||||
private val jsUndefined = context.intrinsics.jsUndefined
|
|
||||||
|
|
||||||
fun nullValue(): IrExpression = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType)
|
private fun undefinedValue(): IrExpression = context.getVoid()
|
||||||
fun undefinedValue(): IrExpression = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType, jsUndefined, 0, 0)
|
|
||||||
|
|
||||||
data class ThrowableArguments(
|
data class ThrowableArguments(
|
||||||
val message: IrExpression,
|
val message: IrExpression,
|
||||||
|
|||||||
+1
-1
@@ -158,7 +158,7 @@ class IrModuleToJsTransformer(
|
|||||||
val moduleBody = generateModuleBody(modules, staticContext)
|
val moduleBody = generateModuleBody(modules, staticContext)
|
||||||
val internalModuleName = ReservedJsNames.makeInternalModuleName()
|
val internalModuleName = ReservedJsNames.makeInternalModuleName()
|
||||||
val globalNames = NameTable<String>(namer.globalNames)
|
val globalNames = NameTable<String>(namer.globalNames)
|
||||||
val exportStatements = ExportModelToJsStatements(nameGenerator) { globalNames.declareFreshName(it, it) }
|
val exportStatements = ExportModelToJsStatements(staticContext) { globalNames.declareFreshName(it, it) }
|
||||||
.generateModuleExport(exportedModule, internalModuleName)
|
.generateModuleExport(exportedModule, internalModuleName)
|
||||||
|
|
||||||
val (crossModuleImports, importedKotlinModules) = generateCrossModuleImports(nameGenerator, modules, dependencies, { JsName(sanitizeName(it), false) })
|
val (crossModuleImports, importedKotlinModules) = generateCrossModuleImports(nameGenerator, modules, dependencies, { JsName(sanitizeName(it), false) })
|
||||||
|
|||||||
+6
-3
@@ -38,7 +38,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
private val baseClassRef by lazy { // Lazy in case was not collected by namer during JsClassGenerator construction
|
private val baseClassRef by lazy { // Lazy in case was not collected by namer during JsClassGenerator construction
|
||||||
if (baseClass != null && !baseClass.isAny()) baseClass.getClassRef(context) else null
|
if (baseClass != null && !baseClass.isAny()) baseClass.getClassRef(context) else null
|
||||||
}
|
}
|
||||||
private val classPrototypeRef = prototypeOf(classNameRef)
|
private val classPrototypeRef = prototypeOf(classNameRef, context.staticContext)
|
||||||
private val classBlock = JsCompositeBlock()
|
private val classBlock = JsCompositeBlock()
|
||||||
private val classModel = JsIrClassModel(irClass)
|
private val classModel = JsIrClassModel(irClass)
|
||||||
|
|
||||||
@@ -202,7 +202,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
classPrototypeRef,
|
classPrototypeRef,
|
||||||
context.getNameForProperty(property).ident,
|
context.getNameForProperty(property).ident,
|
||||||
getter = getterForwarder,
|
getter = getterForwarder,
|
||||||
setter = setterForwarder
|
setter = setterForwarder,
|
||||||
|
context.staticContext
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -328,11 +329,13 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
val associatedObjects = generateAssociatedObjects()
|
val associatedObjects = generateAssociatedObjects()
|
||||||
val suspendArity = generateSuspendArity()
|
val suspendArity = generateSuspendArity()
|
||||||
|
|
||||||
|
val undefined = context.staticContext.backendContext.getVoid().accept(IrElementToJsExpressionTransformer(), context)
|
||||||
|
|
||||||
return JsInvocation(
|
return JsInvocation(
|
||||||
JsNameRef(context.getNameForStaticFunction(setMetadataFor)),
|
JsNameRef(context.getNameForStaticFunction(setMetadataFor)),
|
||||||
listOf(ctor, name, metadataConstructor, parent, interfaces, associatedObjectKey, associatedObjects, suspendArity)
|
listOf(ctor, name, metadataConstructor, parent, interfaces, associatedObjectKey, associatedObjects, suspendArity)
|
||||||
.dropLastWhile { it == null }
|
.dropLastWhile { it == null }
|
||||||
.map { it ?: Namer.JS_UNDEFINED }
|
.map { it ?: undefined }
|
||||||
).makeStmt()
|
).makeStmt()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-8
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrRawFunctionReference
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
@@ -86,11 +87,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
|
|
||||||
prefixOp(intrinsics.jsTypeOf, JsUnaryOperator.TYPEOF)
|
prefixOp(intrinsics.jsTypeOf, JsUnaryOperator.TYPEOF)
|
||||||
|
|
||||||
add(intrinsics.jsObjectCreate) { call, context ->
|
add(intrinsics.jsObjectCreateSymbol) { call, context ->
|
||||||
val classToCreate = call.getTypeArgument(0)!!.classifierOrFail.owner as IrClass
|
val classToCreate = call.getTypeArgument(0)!!.classifierOrFail.owner as IrClass
|
||||||
val className = context.getNameForClass(classToCreate)
|
val className = context.getNameForClass(classToCreate)
|
||||||
val prototype = prototypeOf(className.makeRef())
|
objectCreate(prototypeOf(className.makeRef(), context.staticContext), context.staticContext)
|
||||||
JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add(intrinsics.jsClass) { call, context ->
|
add(intrinsics.jsClass) { call, context ->
|
||||||
@@ -194,6 +194,16 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
JsNameRef(fieldName, arg)
|
JsNameRef(fieldName, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(intrinsics.jsCall) { call, context: JsGenerationContext ->
|
||||||
|
val args = translateCallArguments(call, context)
|
||||||
|
val receiver = args[0]
|
||||||
|
val target = args[1]
|
||||||
|
val varargs = args[2] as? JsArrayLiteral ?: error("Expect to have JsArrayLiteral, because of vararg with dynamic element type")
|
||||||
|
|
||||||
|
val callRef = JsNameRef(Namer.CALL_FUNCTION, target)
|
||||||
|
JsInvocation(callRef, receiver, *varargs.expressions.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
add(intrinsics.jsBind) { call, context: JsGenerationContext ->
|
add(intrinsics.jsBind) { call, context: JsGenerationContext ->
|
||||||
val receiver = call.getValueArgument(0)!!
|
val receiver = call.getValueArgument(0)!!
|
||||||
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
|
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
@@ -202,7 +212,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
val superClass = call.superQualifierSymbol!!
|
val superClass = call.superQualifierSymbol!!
|
||||||
val functionName = context.getNameForMemberFunction(target.symbol.owner as IrSimpleFunction)
|
val functionName = context.getNameForMemberFunction(target.symbol.owner as IrSimpleFunction)
|
||||||
val superName = context.getNameForClass(superClass.owner).makeRef()
|
val superName = context.getNameForClass(superClass.owner).makeRef()
|
||||||
JsNameRef(functionName, prototypeOf(superName))
|
JsNameRef(functionName, prototypeOf(superName, context.staticContext))
|
||||||
}
|
}
|
||||||
is IrFunctionExpression -> target.accept(IrElementToJsExpressionTransformer(), context)
|
is IrFunctionExpression -> target.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
else -> compilationException(
|
else -> compilationException(
|
||||||
@@ -214,6 +224,15 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
JsInvocation(bindRef, jsReceiver)
|
JsInvocation(bindRef, jsReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(intrinsics.jsContexfulRef) { call, context: JsGenerationContext ->
|
||||||
|
val receiver = call.getValueArgument(0)!!
|
||||||
|
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
|
val target = call.getValueArgument(1) as IrRawFunctionReference
|
||||||
|
val jsTarget = context.getNameForMemberFunction(target.symbol.owner as IrSimpleFunction)
|
||||||
|
|
||||||
|
JsNameRef(jsTarget, jsReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
add(intrinsics.unreachable) { _, _ ->
|
add(intrinsics.unreachable) { _, _ ->
|
||||||
JsInvocation(JsNameRef(Namer.UNREACHABLE_NAME))
|
JsInvocation(JsNameRef(Namer.UNREACHABLE_NAME))
|
||||||
}
|
}
|
||||||
@@ -234,9 +253,6 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
val value = args[1]
|
val value = args[1]
|
||||||
jsAssignment(JsNameRef(Namer.SHARED_BOX_V, box), value)
|
jsAssignment(JsNameRef(Namer.SHARED_BOX_V, box), value)
|
||||||
}
|
}
|
||||||
add(intrinsics.jsUndefined) { _, _ ->
|
|
||||||
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
|
|
||||||
}
|
|
||||||
|
|
||||||
val suspendInvokeTransform: (IrCall, JsGenerationContext) -> JsExpression = { call, context: JsGenerationContext ->
|
val suspendInvokeTransform: (IrCall, JsGenerationContext) -> JsExpression = { call, context: JsGenerationContext ->
|
||||||
// Because it is intrinsic, we know everything about this function
|
// Because it is intrinsic, we know everything about this function
|
||||||
@@ -263,7 +279,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateCallArguments(expression: IrCall, context: JsGenerationContext): List<JsExpression> {
|
private fun translateCallArguments(expression: IrCall, context: JsGenerationContext): List<JsExpression> {
|
||||||
return translateCallArguments(expression, context, IrElementToJsExpressionTransformer())
|
return translateCallArguments(expression, context, IrElementToJsExpressionTransformer(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableMap<IrSymbol, IrCallTransformer>.add(functionSymbol: IrSymbol, t: IrCallTransformer) {
|
private fun MutableMap<IrSymbol, IrCallTransformer>.add(functionSymbol: IrSymbol, t: IrCallTransformer) {
|
||||||
|
|||||||
+55
-26
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.compilationException
|
|||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrFileEntry
|
import org.jetbrains.kotlin.ir.IrFileEntry
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||||
import org.jetbrains.kotlin.ir.backend.js.sourceMapsInfo
|
import org.jetbrains.kotlin.ir.backend.js.sourceMapsInfo
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
@@ -31,6 +32,14 @@ import java.io.IOException
|
|||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
|
||||||
|
fun jsUndefined(context: IrNamer, backendContext: JsIrBackendContext): JsExpression {
|
||||||
|
return when (val void = backendContext.getVoid()) {
|
||||||
|
is IrGetField -> context.getNameForField(void.symbol.owner).makeRef()
|
||||||
|
else -> JsNullLiteral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
|
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
|
||||||
val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context)
|
val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
return JsVars(JsVars.JsVar(name, jsInitializer))
|
return JsVars(JsVars.JsVar(name, jsInitializer))
|
||||||
@@ -63,7 +72,34 @@ fun jsElementAccess(name: JsName, receiver: JsExpression?): JsExpression =
|
|||||||
|
|
||||||
fun jsAssignment(left: JsExpression, right: JsExpression) = JsBinaryOperation(JsBinaryOperator.ASG, left, right)
|
fun jsAssignment(left: JsExpression, right: JsExpression) = JsBinaryOperation(JsBinaryOperator.ASG, left, right)
|
||||||
|
|
||||||
fun prototypeOf(classNameRef: JsExpression) = JsNameRef(Namer.PROTOTYPE_NAME, classNameRef)
|
fun prototypeOf(classNameRef: JsExpression, context: JsStaticContext) =
|
||||||
|
JsInvocation(
|
||||||
|
context
|
||||||
|
.getNameForStaticFunction(context.backendContext.intrinsics.jsPrototypeOfSymbol.owner)
|
||||||
|
.makeRef(),
|
||||||
|
classNameRef
|
||||||
|
)
|
||||||
|
|
||||||
|
fun objectCreate(prototype: JsExpression, context: JsStaticContext) =
|
||||||
|
JsInvocation(
|
||||||
|
context
|
||||||
|
.getNameForStaticFunction(context.backendContext.intrinsics.jsObjectCreateSymbol.owner)
|
||||||
|
.makeRef(),
|
||||||
|
prototype
|
||||||
|
)
|
||||||
|
|
||||||
|
fun defineProperty(obj: JsExpression, name: String, getter: JsExpression?, setter: JsExpression?, context: JsStaticContext) =
|
||||||
|
JsInvocation(
|
||||||
|
context
|
||||||
|
.getNameForStaticFunction(context.backendContext.intrinsics.jsDefinePropertySymbol.owner)
|
||||||
|
.makeRef(),
|
||||||
|
obj,
|
||||||
|
JsStringLiteral(name),
|
||||||
|
*listOf(getter, setter)
|
||||||
|
.dropLastWhile { it == null }
|
||||||
|
.map { it ?: jsUndefined(context, context.backendContext) }
|
||||||
|
.toTypedArray()
|
||||||
|
)
|
||||||
|
|
||||||
fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerationContext): JsFunction {
|
fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerationContext): JsFunction {
|
||||||
context.staticContext.backendContext.getJsCodeForFunction(declaration.symbol)?.let { function ->
|
context.staticContext.backendContext.getJsCodeForFunction(declaration.symbol)?.let { function ->
|
||||||
@@ -167,7 +203,7 @@ fun translateCall(
|
|||||||
} else {
|
} else {
|
||||||
val qualifierName = context.getNameForClass(klass).makeRef()
|
val qualifierName = context.getNameForClass(klass).makeRef()
|
||||||
val targetName = context.getNameForMemberFunction(target)
|
val targetName = context.getNameForMemberFunction(target)
|
||||||
val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName))
|
val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName, context.staticContext))
|
||||||
JsNameRef(Namer.CALL_FUNCTION, qPrototype)
|
JsNameRef(Namer.CALL_FUNCTION, qPrototype)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +372,7 @@ fun translateCallArguments(
|
|||||||
expression: IrMemberAccessExpression<IrFunctionSymbol>,
|
expression: IrMemberAccessExpression<IrFunctionSymbol>,
|
||||||
context: JsGenerationContext,
|
context: JsGenerationContext,
|
||||||
transformer: IrElementToJsExpressionTransformer,
|
transformer: IrElementToJsExpressionTransformer,
|
||||||
|
allowDropTailVoids: Boolean = true
|
||||||
): List<JsExpression> {
|
): List<JsExpression> {
|
||||||
val size = expression.valueArgumentsCount
|
val size = expression.valueArgumentsCount
|
||||||
|
|
||||||
@@ -344,13 +381,15 @@ fun translateCallArguments(
|
|||||||
val validWithNullArgs = expression.validWithNullArgs()
|
val validWithNullArgs = expression.validWithNullArgs()
|
||||||
val arguments = (0 until size)
|
val arguments = (0 until size)
|
||||||
.mapTo(ArrayList(size)) { index ->
|
.mapTo(ArrayList(size)) { index ->
|
||||||
val argument = expression.getValueArgument(index)
|
expression.getValueArgument(index).checkOnNullability(validWithNullArgs)
|
||||||
argument?.accept(transformer, context)
|
|
||||||
}
|
}
|
||||||
.onEach { result ->
|
.dropLastWhile {
|
||||||
if (result == null) {
|
allowDropTailVoids &&
|
||||||
assert(validWithNullArgs)
|
it is IrGetField &&
|
||||||
}
|
it.symbol.owner.correspondingPropertySymbol == context.staticContext.backendContext.intrinsics.void
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
it?.accept(transformer, context)
|
||||||
}
|
}
|
||||||
.mapIndexed { index, result ->
|
.mapIndexed { index, result ->
|
||||||
val isEmptyExternalVararg = validWithNullArgs &&
|
val isEmptyExternalVararg = validWithNullArgs &&
|
||||||
@@ -363,34 +402,24 @@ fun translateCallArguments(
|
|||||||
} else result
|
} else result
|
||||||
}
|
}
|
||||||
.dropLastWhile { it == null }
|
.dropLastWhile { it == null }
|
||||||
.map { it ?: JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1)) }
|
.map { it ?: jsUndefined(context, context.staticContext.backendContext) }
|
||||||
|
|
||||||
check(!expression.symbol.isSuspend) { "Suspend functions should be lowered" }
|
check(!expression.symbol.isSuspend) { "Suspend functions should be lowered" }
|
||||||
return arguments
|
return arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrExpression?.checkOnNullability(validWithNullArgs: Boolean) =
|
||||||
|
also {
|
||||||
|
if (it == null) {
|
||||||
|
assert(validWithNullArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrMemberAccessExpression<*>.validWithNullArgs() =
|
private fun IrMemberAccessExpression<*>.validWithNullArgs() =
|
||||||
this is IrFunctionAccessExpression && symbol.owner.isExternalOrInheritedFromExternal()
|
this is IrFunctionAccessExpression && symbol.owner.isExternalOrInheritedFromExternal()
|
||||||
|
|
||||||
fun JsStatement.asBlock() = this as? JsBlock ?: JsBlock(this)
|
fun JsStatement.asBlock() = this as? JsBlock ?: JsBlock(this)
|
||||||
|
|
||||||
fun defineProperty(receiver: JsExpression, name: String, value: () -> JsExpression): JsInvocation {
|
|
||||||
val objectDefineProperty = JsNameRef("defineProperty", Namer.JS_OBJECT)
|
|
||||||
return JsInvocation(objectDefineProperty, receiver, JsStringLiteral(name), value())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun defineProperty(receiver: JsExpression, name: String, getter: JsExpression?, setter: JsExpression? = null) =
|
|
||||||
defineProperty(receiver, name) {
|
|
||||||
JsObjectLiteral(true).apply {
|
|
||||||
propertyInitializers += JsPropertyInitializer(JsStringLiteral("configurable"), JsBooleanLiteral(true))
|
|
||||||
if (getter != null)
|
|
||||||
propertyInitializers += JsPropertyInitializer(JsStringLiteral("get"), getter)
|
|
||||||
if (setter != null)
|
|
||||||
propertyInitializers += JsPropertyInitializer(JsStringLiteral("set"), setter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Partially copied from org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
// Partially copied from org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
object JsAstUtils {
|
object JsAstUtils {
|
||||||
private fun deBlockIfPossible(statement: JsStatement): JsStatement {
|
private fun deBlockIfPossible(statement: JsStatement): JsStatement {
|
||||||
|
|||||||
@@ -7,10 +7,14 @@ package org.jetbrains.kotlin.ir.backend.js.utils
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.isClass
|
import org.jetbrains.kotlin.descriptors.isClass
|
||||||
import org.jetbrains.kotlin.descriptors.isInterface
|
import org.jetbrains.kotlin.descriptors.isInterface
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -41,3 +45,18 @@ fun IrDeclarationWithName.getFqNameWithJsNameWhenAvailable(shouldIncludePackage:
|
|||||||
private fun getKotlinOrJsQualifier(parent: IrPackageFragment, shouldIncludePackage: Boolean): FqName? {
|
private fun getKotlinOrJsQualifier(parent: IrPackageFragment, shouldIncludePackage: Boolean): FqName? {
|
||||||
return (parent as? IrFile)?.getJsQualifier()?.let { FqName(it) } ?: parent.fqName.takeIf { shouldIncludePackage }
|
return (parent as? IrFile)?.getJsQualifier()?.let { FqName(it) } ?: parent.fqName.takeIf { shouldIncludePackage }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: the code is written to pass Repl tests, so we should understand. why in Repl tests we don't have backingField
|
||||||
|
fun JsIrBackendContext.getVoid(): IrExpression =
|
||||||
|
intrinsics.void.owner.backingField?.let {
|
||||||
|
IrGetFieldImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
it.symbol,
|
||||||
|
irBuiltIns.nothingNType
|
||||||
|
)
|
||||||
|
} ?: IrConstImpl.constNull(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
irBuiltIns.nothingNType
|
||||||
|
)
|
||||||
|
|||||||
@@ -136,7 +136,10 @@ fun calculateJsFunctionSignature(declaration: IrFunction, context: JsIrBackendCo
|
|||||||
nameBuilder.append("_r$${it.type.asString()}")
|
nameBuilder.append("_r$${it.type.asString()}")
|
||||||
}
|
}
|
||||||
declaration.valueParameters.ifNotEmpty {
|
declaration.valueParameters.ifNotEmpty {
|
||||||
joinTo(nameBuilder, "") { "_${it.type.asString()}" }
|
joinTo(nameBuilder, "") {
|
||||||
|
val defaultValueSign = if (it.origin == JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER) "?" else ""
|
||||||
|
"_${it.type.asString()}$defaultValueSign"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
declaration.returnType.let {
|
declaration.returnType.let {
|
||||||
// Return type is only used in signature for inline class and Unit types because
|
// Return type is only used in signature for inline class and Unit types because
|
||||||
|
|||||||
@@ -27,12 +27,7 @@ object Namer {
|
|||||||
|
|
||||||
val JS_ERROR = JsNameRef("Error")
|
val JS_ERROR = JsNameRef("Error")
|
||||||
|
|
||||||
val JS_OBJECT = JsNameRef("Object")
|
|
||||||
val JS_UNDEFINED = JsNameRef("undefined")
|
|
||||||
val JS_OBJECT_CREATE_FUNCTION = JsNameRef("create", JS_OBJECT)
|
|
||||||
|
|
||||||
val METADATA = "\$metadata\$"
|
val METADATA = "\$metadata\$"
|
||||||
val INTERFACES_MASK = "\$imask\$"
|
|
||||||
|
|
||||||
val KCALLABLE_GET_NAME = "<get-name>"
|
val KCALLABLE_GET_NAME = "<get-name>"
|
||||||
val KCALLABLE_NAME = "callableName"
|
val KCALLABLE_NAME = "callableName"
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ fun IrFunction.hasStableJsName(context: JsIrBackendContext): Boolean {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT ||
|
origin == JsLoweredDeclarationOrigin.JS_SHADOWED_EXPORT ||
|
||||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
|
||||||
origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME ||
|
origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME ||
|
||||||
origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR
|
origin == JsLoweredDeclarationOrigin.BRIDGE_PROPERTY_ACCESSOR
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ fun IrBuilderWithScope.irSet(variable: IrValueSymbol, value: IrExpression, origi
|
|||||||
fun IrBuilderWithScope.irSet(variable: IrValueDeclaration, value: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.EQ) =
|
fun IrBuilderWithScope.irSet(variable: IrValueDeclaration, value: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.EQ) =
|
||||||
irSet(variable.symbol, value, origin)
|
irSet(variable.symbol, value, origin)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
|
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField, type: IrType = field.type) =
|
||||||
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
|
IrGetFieldImpl(startOffset, endOffset, field.symbol, type, receiver)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression, origin: IrStatementOrigin? = null) =
|
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression, origin: IrStatementOrigin? = null) =
|
||||||
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, context.irBuiltIns.unitType, origin = origin)
|
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, context.irBuiltIns.unitType, origin = origin)
|
||||||
@@ -161,6 +161,17 @@ fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol
|
|||||||
fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
|
fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
|
||||||
context.eqeqeq(startOffset, endOffset, arg1, arg2)
|
context.eqeqeq(startOffset, endOffset, arg1, arg2)
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.irEqeqeqWithoutBox(arg1: IrExpression, arg2: IrExpression) =
|
||||||
|
primitiveOp2(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
context.irBuiltIns.eqeqeqSymbol,
|
||||||
|
context.irBuiltIns.booleanType,
|
||||||
|
IrStatementOrigin.SYNTHETIC_NOT_AUTOBOXED_CHECK,
|
||||||
|
arg1,
|
||||||
|
arg2
|
||||||
|
)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irNull() =
|
fun IrBuilderWithScope.irNull() =
|
||||||
irNull(context.irBuiltIns.nothingNType)
|
irNull(context.irBuiltIns.nothingNType)
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ abstract class IrStatementsBuilder<out T : IrElement>(
|
|||||||
addStatement(this)
|
addStatement(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun List<IrStatement>.unaryPlus() {
|
||||||
|
forEach(::addStatement)
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract fun addStatement(irStatement: IrStatement)
|
protected abstract fun addStatement(irStatement: IrStatement)
|
||||||
abstract fun doBuild(): T
|
abstract fun doBuild(): T
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.expressions
|
package org.jetbrains.kotlin.ir.expressions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||||
|
|
||||||
abstract class IrStatementOriginImpl(val debugName: String) : IrStatementOrigin {
|
abstract class IrStatementOriginImpl(val debugName: String) : IrStatementOrigin {
|
||||||
override fun toString(): String = debugName
|
override fun toString(): String = debugName
|
||||||
}
|
}
|
||||||
@@ -90,6 +92,8 @@ interface IrStatementOrigin {
|
|||||||
|
|
||||||
object BRIDGE_DELEGATION : IrStatementOriginImpl("BRIDGE_DELEGATION")
|
object BRIDGE_DELEGATION : IrStatementOriginImpl("BRIDGE_DELEGATION")
|
||||||
|
|
||||||
|
object SYNTHETIC_NOT_AUTOBOXED_CHECK : IrStatementOriginImpl("SYNTHETIC_NOT_AUTOBOXED_CHECK")
|
||||||
|
|
||||||
data class COMPONENT_N private constructor(val index: Int) : IrStatementOriginImpl("COMPONENT_$index") {
|
data class COMPONENT_N private constructor(val index: Int) : IrStatementOriginImpl("COMPONENT_$index") {
|
||||||
companion object {
|
companion object {
|
||||||
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
||||||
|
|||||||
+1
@@ -19,4 +19,5 @@ interface JsStatementOrigins {
|
|||||||
object COROUTINE_ROOT_LOOP : IrStatementOriginImpl("COROUTINE_ROOT_LOOP")
|
object COROUTINE_ROOT_LOOP : IrStatementOriginImpl("COROUTINE_ROOT_LOOP")
|
||||||
object COROUTINE_SWITCH : IrStatementOriginImpl("COROUTINE_SWITCH")
|
object COROUTINE_SWITCH : IrStatementOriginImpl("COROUTINE_SWITCH")
|
||||||
object CLASS_REFERENCE : IrStatementOriginImpl("CLASS_REFERENCE")
|
object CLASS_REFERENCE : IrStatementOriginImpl("CLASS_REFERENCE")
|
||||||
|
object IMPLEMENTATION_DELEGATION_CALL : IrStatementOriginImpl("IMPLEMENTATION_DELEGATION_CALL")
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,8 @@ fun trimMarginConstantCustomPrefixInterpolatedUsingConstant(): String {
|
|||||||
""".trimMargin(marginPrefix = "$OCTOTHORPE@$OCTOTHORPE")
|
""".trimMargin(marginPrefix = "$OCTOTHORPE@$OCTOTHORPE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginNotConstant
|
// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginNotConstant IGNORED_BACKENDS=JS_IR
|
||||||
|
// CHECK_CALLED_IN_SCOPE: function=trimMargin scope=trimMarginNotConstant TARGET_BACKENDS=JS_IR
|
||||||
fun trimMarginNotConstant(arg: String): String {
|
fun trimMarginNotConstant(arg: String): String {
|
||||||
return arg.trimMargin()
|
return arg.trimMargin()
|
||||||
}
|
}
|
||||||
@@ -100,7 +101,8 @@ fun trimMarginNotConstantCustomPrefix(arg: String): String {
|
|||||||
return arg.trimMargin("###")
|
return arg.trimMargin("###")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginInterpolated
|
// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginInterpolated IGNORED_BACKENDS=JS_IR
|
||||||
|
// CHECK_CALLED_IN_SCOPE: function=trimMargin scope=trimMarginInterpolated TARGET_BACKENDS=JS_IR
|
||||||
fun trimMarginInterpolated(arg: Int): String {
|
fun trimMarginInterpolated(arg: Int): String {
|
||||||
return """
|
return """
|
||||||
|Hello,
|
|Hello,
|
||||||
|
|||||||
+2
-2
@@ -30,5 +30,5 @@ fun box() {
|
|||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:9 box
|
// test.kt:9 box
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:4 A.foo_26di_k$
|
// test.kt:4 protoOf.foo_26di_k$
|
||||||
// test.kt:5 box
|
// test.kt:5 box
|
||||||
+2
-2
@@ -32,9 +32,9 @@ fun box() {
|
|||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:9 box
|
// test.kt:9 box
|
||||||
// test.kt:10 box
|
// test.kt:10 box
|
||||||
// test.kt:4 A.foo_26di_k$
|
// test.kt:4 protoOf.foo_26di_k$
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:4 A.foo_26di_k$
|
// test.kt:4 protoOf.foo_26di_k$
|
||||||
// test.kt:5 box
|
// test.kt:5 box
|
||||||
// test.kt:13 box
|
// test.kt:13 box
|
||||||
// test.kt:5 box
|
// test.kt:5 box
|
||||||
|
|||||||
+1
-1
@@ -45,4 +45,4 @@ fun box() {
|
|||||||
// test.kt:15 box
|
// test.kt:15 box
|
||||||
// test.kt:16 box
|
// test.kt:16 box
|
||||||
// test.kt:16 box
|
// test.kt:16 box
|
||||||
// test.kt:8 Companion_19.foo_26di_k$
|
// test.kt:8 protoOf.foo_26di_k$
|
||||||
+21
-23
@@ -68,29 +68,27 @@ fun box() {
|
|||||||
// test.kt:3 D
|
// test.kt:3 D
|
||||||
// test.kt:3 D
|
// test.kt:3 D
|
||||||
// test.kt:14 box
|
// test.kt:14 box
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:1 D.equals
|
// test.kt:1 protoOf.equals
|
||||||
// test.kt:15 box
|
// test.kt:15 box
|
||||||
// test.kt:1 D.hashCode
|
// test.kt:1 protoOf.hashCode
|
||||||
// test.kt:1 D.hashCode
|
// test.kt:1 protoOf.hashCode
|
||||||
// test.kt:16 box
|
// test.kt:16 box
|
||||||
// test.kt:1 D.toString
|
// test.kt:1 protoOf.toString
|
||||||
// test.kt:17 box
|
// test.kt:17 box
|
||||||
// test.kt:17 box
|
// test.kt:17 box
|
||||||
// test.kt:1 D.component1_7eebsc_k$
|
// test.kt:1 protoOf.component1_7eebsc_k$
|
||||||
// test.kt:17 box
|
// test.kt:17 box
|
||||||
// test.kt:1 D.component2_7eebsb_k$
|
// test.kt:1 protoOf.component2_7eebsb_k$
|
||||||
// test.kt:18 box
|
// test.kt:18 box
|
||||||
// test.kt:1 D.copy$default_cbhffz_k$
|
// test.kt:1 protoOf.copy$default_roih85_k$
|
||||||
// test.kt:1 D.copy$default_cbhffz_k$
|
// test.kt:1 protoOf.copy$default_roih85_k$
|
||||||
// test.kt:1 D.copy$default_cbhffz_k$
|
// test.kt:1 protoOf.copy$default_roih85_k$
|
||||||
// test.kt:1 D.copy$default_cbhffz_k$
|
// test.kt:1 protoOf.copy_t8q04r_k$
|
||||||
// test.kt:1 D.copy$default_cbhffz_k$
|
|
||||||
// test.kt:1 D.copy_t8q04r_k$
|
|
||||||
// test.kt:3 D
|
// test.kt:3 D
|
||||||
// test.kt:3 D
|
// test.kt:3 D
|
||||||
// test.kt:19 box
|
// test.kt:19 box
|
||||||
@@ -100,17 +98,17 @@ fun box() {
|
|||||||
// test.kt:5 E
|
// test.kt:5 E
|
||||||
// test.kt:5 E
|
// test.kt:5 E
|
||||||
// test.kt:20 box
|
// test.kt:20 box
|
||||||
// test.kt:7 E.equals
|
// test.kt:7 protoOf.equals
|
||||||
// test.kt:21 box
|
// test.kt:21 box
|
||||||
// test.kt:8 E.hashCode
|
// test.kt:8 protoOf.hashCode
|
||||||
// test.kt:22 box
|
// test.kt:22 box
|
||||||
// test.kt:6 E.toString
|
// test.kt:6 protoOf.toString
|
||||||
// test.kt:23 box
|
// test.kt:23 box
|
||||||
// test.kt:23 box
|
// test.kt:23 box
|
||||||
// test.kt:1 E.component1_7eebsc_k$
|
// test.kt:1 protoOf.component1_7eebsc_k$
|
||||||
// test.kt:23 box
|
// test.kt:23 box
|
||||||
// test.kt:1 E.component2_7eebsb_k$
|
// test.kt:1 protoOf.component2_7eebsb_k$
|
||||||
// test.kt:24 box
|
// test.kt:24 box
|
||||||
// test.kt:9 E.copy_1tks5_k$
|
// test.kt:9 protoOf.copy_1tks5_k$
|
||||||
// test.kt:5 E
|
// test.kt:5 E
|
||||||
// test.kt:5 E
|
// test.kt:5 E
|
||||||
|
|||||||
+5
-4
@@ -26,7 +26,8 @@ fun box() {
|
|||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:6 A.foo$default_dec9f7_k$
|
// test.kt:6 protoOf.foo$default_ourpn2_k$
|
||||||
// test.kt:6 A.foo$default_dec9f7_k$
|
// test.kt:4 protoOf.computeParam_vubdyi_k$
|
||||||
// test.kt:4 A.computeParam_vubdyi_k$
|
// test.kt:6 protoOf.foo$default_ourpn2_k$
|
||||||
// test.kt:6 A.foo$default_dec9f7_k$
|
// test.kt:6 protoOf.foo$default_ourpn2_k$
|
||||||
|
// test.kt:6 protoOf.foo$default_ourpn2_k$
|
||||||
+1
-1
@@ -57,7 +57,7 @@ fun box() {
|
|||||||
// test.kt:11 E
|
// test.kt:11 E
|
||||||
// test.kt:11 E
|
// test.kt:11 E
|
||||||
// test.kt:22 box
|
// test.kt:22 box
|
||||||
// test.kt:9 E.foo_26di_k$
|
// test.kt:9 protoOf.foo_26di_k$
|
||||||
// test.kt:15 E2_initEntries
|
// test.kt:15 E2_initEntries
|
||||||
// test.kt:14 E2
|
// test.kt:14 E2
|
||||||
// test.kt:17 E2_initEntries
|
// test.kt:17 E2_initEntries
|
||||||
|
|||||||
@@ -24,6 +24,4 @@ inline fun bar(i: Int = 1) {
|
|||||||
|
|
||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:4 box
|
// test.kt:4 box
|
||||||
// test.kt:8 foo$default
|
// test.kt:8 foo
|
||||||
// test.kt:8 foo$default
|
|
||||||
// test.kt:8 foo$default
|
|
||||||
+1
-1
@@ -22,4 +22,4 @@ fun box() {
|
|||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
// test.kt:6 A.get_prop_wosl9o_k$
|
// test.kt:6 protoOf.get_prop_wosl9o_k$
|
||||||
+1
-4
@@ -18,7 +18,4 @@ fun box(): String {
|
|||||||
|
|
||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:8 box
|
// test.kt:8 box
|
||||||
// test.kt:3 ifoo$default
|
// test.kt:3 ifoo
|
||||||
// test.kt:3 ifoo$default
|
|
||||||
// test.kt:3 ifoo$default
|
|
||||||
// test.kt:4 ifoo
|
|
||||||
@@ -19,7 +19,7 @@ suspend fun box() {
|
|||||||
// test.kt:11 box
|
// test.kt:11 box
|
||||||
|
|
||||||
// EXPECTATIONS JS_IR
|
// EXPECTATIONS JS_IR
|
||||||
// test.kt:8 $boxCOROUTINE$0.doResume_5yljmg_k$
|
// test.kt:8 protoOf.doResume_5yljmg_k$
|
||||||
// test.kt:4 foo
|
// test.kt:4 foo
|
||||||
// test.kt:4 foo
|
// test.kt:4 foo
|
||||||
// test.kt:9 box$lambda
|
// test.kt:9 box$lambda
|
||||||
|
|||||||
@@ -1220,6 +1220,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("interfaceSuperCall.kt")
|
||||||
|
public void testInterfaceSuperCall() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/defaultArguments/interfaceSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overloadFunWithDefArg.kt")
|
@TestMetadata("overloadFunWithDefArg.kt")
|
||||||
public void testOverloadFunWithDefArg() throws Exception {
|
public void testOverloadFunWithDefArg() throws Exception {
|
||||||
@@ -2130,6 +2136,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exportDefaultParameterAndOverrideIt.kt")
|
||||||
|
public void testExportDefaultParameterAndOverrideIt() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/export/exportDefaultParameterAndOverrideIt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("exportEnumClass.kt")
|
@TestMetadata("exportEnumClass.kt")
|
||||||
public void testExportEnumClass() throws Exception {
|
public void testExportEnumClass() throws Exception {
|
||||||
|
|||||||
+12
@@ -1284,6 +1284,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest {
|
|||||||
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("interfaceSuperCall.kt")
|
||||||
|
public void testInterfaceSuperCall() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/defaultArguments/interfaceSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overloadFunWithDefArg.kt")
|
@TestMetadata("overloadFunWithDefArg.kt")
|
||||||
public void testOverloadFunWithDefArg() throws Exception {
|
public void testOverloadFunWithDefArg() throws Exception {
|
||||||
@@ -2602,6 +2608,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest {
|
|||||||
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exportDefaultParameterAndOverrideIt.kt")
|
||||||
|
public void testExportDefaultParameterAndOverrideIt() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/export/exportDefaultParameterAndOverrideIt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("exportEnumClass.kt")
|
@TestMetadata("exportEnumClass.kt")
|
||||||
public void testExportEnumClass() throws Exception {
|
public void testExportEnumClass() throws Exception {
|
||||||
|
|||||||
+12
@@ -1284,6 +1284,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
runTest("js/js.translator/testData/box/defaultArguments/inheritViaAnotherInterfaceIndirectly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("interfaceSuperCall.kt")
|
||||||
|
public void testInterfaceSuperCall() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/defaultArguments/interfaceSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overloadFunWithDefArg.kt")
|
@TestMetadata("overloadFunWithDefArg.kt")
|
||||||
public void testOverloadFunWithDefArg() throws Exception {
|
public void testOverloadFunWithDefArg() throws Exception {
|
||||||
@@ -2602,6 +2608,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
runTest("js/js.translator/testData/box/export/exportClassWithInternalOneFile.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exportDefaultParameterAndOverrideIt.kt")
|
||||||
|
public void testExportDefaultParameterAndOverrideIt() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/export/exportDefaultParameterAndOverrideIt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("exportEnumClass.kt")
|
@TestMetadata("exportEnumClass.kt")
|
||||||
public void testExportEnumClass() throws Exception {
|
public void testExportEnumClass() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1299
|
||||||
|
package foo
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
open fun foo(x: Int = 20, y: Int = 3) = x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B : A {
|
||||||
|
override fun foo(x: Int, y: Int) = 0
|
||||||
|
fun bar1() = super.foo()
|
||||||
|
|
||||||
|
fun bar2() = super.foo(30)
|
||||||
|
|
||||||
|
fun bar3() = super.foo(y = 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val v1 = B().bar1()
|
||||||
|
if (v1 != 23) return "fail1: $v1"
|
||||||
|
|
||||||
|
val v2 = B().bar2()
|
||||||
|
if (v2 != 33) return "fail2: $v2"
|
||||||
|
|
||||||
|
val v3 = B().bar3()
|
||||||
|
if (v3 != 24) return "fail3: $v3"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1252
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
// INFER_MAIN_MODULE
|
||||||
|
// SKIP_DCE_DRIVEN
|
||||||
|
// IGNORE_BACKEND: JS
|
||||||
|
|
||||||
|
// MODULE: export_default_method
|
||||||
|
// FILE: lib.kt
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
abstract class Adapter {
|
||||||
|
abstract fun method(o: String = "O", k: String = "K")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class TwoArgumentsWrapper(val adapter: Adapter) {
|
||||||
|
fun method(a: String, b: String) {
|
||||||
|
adapter.method(a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class OneArgumentWrapper(val adapter: Adapter) {
|
||||||
|
fun method(param: String) {
|
||||||
|
adapter.method(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class NoArgumentsWrapper(val adapter: Adapter) {
|
||||||
|
fun method() {
|
||||||
|
adapter.method()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: test.js
|
||||||
|
|
||||||
|
function box() {
|
||||||
|
const Adapter = this.export_default_method.Adapter
|
||||||
|
const Wrapper2 = this.export_default_method.TwoArgumentsWrapper
|
||||||
|
const Wrapper1 = this.export_default_method.OneArgumentWrapper
|
||||||
|
const Wrapper0 = this.export_default_method.NoArgumentsWrapper
|
||||||
|
|
||||||
|
class WebAdapter extends Adapter {
|
||||||
|
constructor(name) {
|
||||||
|
super()
|
||||||
|
this.resetError(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
method(o = "O", k = "K") {
|
||||||
|
this.result = o + k
|
||||||
|
}
|
||||||
|
|
||||||
|
resetError(name) {
|
||||||
|
this.result = `Error: ${name}'s overridden method was not called`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const webAdapter = new WebAdapter("webAdapter2")
|
||||||
|
|
||||||
|
const wrapper2 = new Wrapper2(webAdapter)
|
||||||
|
wrapper2.method("O", "K")
|
||||||
|
|
||||||
|
if (webAdapter.result !== "OK") return webAdapter.result
|
||||||
|
|
||||||
|
webAdapter.resetError("webAdapter1")
|
||||||
|
|
||||||
|
const wrapper1 = new Wrapper1(webAdapter)
|
||||||
|
wrapper1.method("O")
|
||||||
|
|
||||||
|
if (webAdapter.result !== "OK") return webAdapter.result
|
||||||
|
|
||||||
|
webAdapter.resetError("webAdapter0")
|
||||||
|
|
||||||
|
const wrapper0 = new Wrapper0(webAdapter)
|
||||||
|
wrapper0.method()
|
||||||
|
|
||||||
|
if (webAdapter.result !== "OK") return webAdapter.result
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Vendored
+1
-2
@@ -15,8 +15,7 @@ inline fun <reified T> boo() = "boo"
|
|||||||
// MODULE: main(#my_libr@ry)
|
// MODULE: main(#my_libr@ry)
|
||||||
// MODULE_KIND: PLAIN
|
// MODULE_KIND: PLAIN
|
||||||
// FILE: box.kt
|
// FILE: box.kt
|
||||||
// CHECK_CONTAINS_NO_CALLS: box except=assertEquals TARGET_BACKENDS=JS
|
// CHECK_CONTAINS_NO_CALLS: box except=assertEquals
|
||||||
// CHECK_CONTAINS_NO_CALLS: box except=assertEquals$default IGNORED_BACKENDS=JS
|
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
assertEquals("foo", foo())
|
assertEquals("foo", foo())
|
||||||
|
|||||||
+1
-1
@@ -12,4 +12,4 @@ fun baz() = 1
|
|||||||
fun bar() = 2
|
fun bar() = 2
|
||||||
|
|
||||||
// LINES(JS): 1 3 3 2 2 4 3 4 4 4 5 5 2 8 8 10 10 10 12 12 12
|
// LINES(JS): 1 3 3 2 2 4 3 4 4 4 5 5 2 8 8 10 10 10 12 12 12
|
||||||
// LINES(JS_IR): 8 8 * 1 3 3 1 4 5 1 1 * 10 10 * 12 12
|
// LINES(JS_IR): 1 3 3 4 5 1 * 8 8 * 10 10 * 12 12
|
||||||
|
|||||||
+1
-1
@@ -6,4 +6,4 @@ data class A(
|
|||||||
// LINES(JS): 1 2 3 * 1 2 2 1 3 3 1 1 1 2 3 1 1 1 2 3 1 1 1 2 3 1 1 1 1 1 2 3
|
// LINES(JS): 1 2 3 * 1 2 2 1 3 3 1 1 1 2 3 1 1 1 2 3 1 1 1 2 3 1 1 1 1 1 2 3
|
||||||
|
|
||||||
// FIXME: componentN function body should point to the corresponding property.
|
// FIXME: componentN function body should point to the corresponding property.
|
||||||
// LINES(JS_IR): 2 2 3 3 * 2 2 * 3 3 * 1 1 * 1 1 * 1 1 * 1 1 1 1 1 1 1 1 * 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
// LINES(JS_IR): 2 2 3 3 * 2 2 * 3 3 * 1 1 * 1 1 * 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ class B : A() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LINES(JS): 1 2 2 2 2 2 2 2 2 2 4 4 4 * 7 7 8 10 9 9
|
// LINES(JS): 1 2 2 2 2 2 2 2 2 2 4 4 4 * 7 7 8 10 9 9
|
||||||
// LINES(JS_IR): 2 2 * 2 2 2 2 2 * 4 4 * 7 * 9 9
|
// LINES(JS_IR): 2 2 * 2 2 2 * 4 4 * 7 * 9 9
|
||||||
|
|||||||
+1
-1
@@ -8,4 +8,4 @@ fun box(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LINES(JS): 1 8 2 2 2 2 3 3 3 4 6 6 7 7
|
// LINES(JS): 1 8 2 2 2 2 3 3 3 4 6 6 7 7
|
||||||
// LINES(JS_IR): 1 1 2 1 4 1 * 6 6 7 7 * 1 1 2 1 1 4 1 1
|
// LINES(JS_IR): 1 2 1 1 4 1 6 6 7 7
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ internal fun captureStack(instance: Throwable, constructorFunction: Any) {
|
|||||||
internal fun newThrowable(message: String?, cause: Throwable?): Throwable {
|
internal fun newThrowable(message: String?, cause: Throwable?): Throwable {
|
||||||
val throwable = js("new Error()")
|
val throwable = js("new Error()")
|
||||||
throwable.message = if (isUndefined(message)) {
|
throwable.message = if (isUndefined(message)) {
|
||||||
if (isUndefined(cause)) message else cause?.toString() ?: undefined
|
if (isUndefined(cause)) message else cause?.toString() ?: VOID
|
||||||
} else message ?: undefined
|
} else message ?: VOID
|
||||||
throwable.cause = cause
|
throwable.cause = cause
|
||||||
throwable.name = "Throwable"
|
throwable.name = "Throwable"
|
||||||
return throwable.unsafeCast<Throwable>()
|
return throwable.unsafeCast<Throwable>()
|
||||||
@@ -109,10 +109,10 @@ internal fun setPropertiesToThrowableInstance(this_: dynamic, message: String?,
|
|||||||
@Suppress("SENSELESS_COMPARISON")
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
if (message !== null) {
|
if (message !== null) {
|
||||||
// undefined
|
// undefined
|
||||||
cause?.toString() ?: undefined
|
cause?.toString() ?: VOID
|
||||||
} else {
|
} else {
|
||||||
// real null
|
// real null
|
||||||
undefined
|
VOID
|
||||||
}
|
}
|
||||||
} else message
|
} else message
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,19 @@ internal fun errorCode(description: String): Nothing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SENSELESS_COMPARISON")
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
internal fun isUndefined(value: dynamic): Boolean = value === undefined
|
internal fun isUndefined(value: dynamic): Boolean = value === VOID
|
||||||
|
|
||||||
internal fun <T, R> boxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
internal fun <T, R> boxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
||||||
internal fun <T, R> unboxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
internal fun <T, R> unboxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
internal fun protoOf(constructor: Any) =
|
||||||
|
js("constructor.prototype")
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
internal fun <T> objectCreate(proto: T?) =
|
||||||
|
js("Object.create(proto)")
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
internal fun defineProp(obj: Any, name: String, getter: Any?, setter: Any?) =
|
||||||
|
js("Object.defineProperty(obj, name, { configurable: true, get: getter, set: setter })")
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ internal fun jsEqeq(a: Any?, b: Any?): Boolean
|
|||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun jsNotEq(a: Any?, b: Any?): Boolean
|
internal fun jsNotEq(a: Any?, b: Any?): Boolean
|
||||||
|
|
||||||
|
@JsIntrinsic
|
||||||
|
internal fun jsUndefined(): Nothing?
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun jsEqeqeq(a: Any?, b: Any?): Boolean
|
internal fun jsEqeqeq(a: Any?, b: Any?): Boolean
|
||||||
|
|
||||||
@@ -172,9 +175,6 @@ internal fun float32ArrayOf(a: Any?): Any?
|
|||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun float64ArrayOf(a: Any?): Any?
|
internal fun float64ArrayOf(a: Any?): Any?
|
||||||
|
|
||||||
@JsIntrinsic
|
|
||||||
internal fun <T> objectCreate(): T
|
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun <T> sharedBoxCreate(v: T?): dynamic
|
internal fun <T> sharedBoxCreate(v: T?): dynamic
|
||||||
|
|
||||||
@@ -184,15 +184,15 @@ internal fun <T> sharedBoxRead(box: dynamic): T?
|
|||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun <T> sharedBoxWrite(box: dynamic, nv: T?)
|
internal fun <T> sharedBoxWrite(box: dynamic, nv: T?)
|
||||||
|
|
||||||
@JsIntrinsic
|
|
||||||
internal fun jsUndefined(): Nothing?
|
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun <T> DefaultType(): T
|
internal fun <T> DefaultType(): T
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun jsBind(receiver: Any?, target: Any?): Any?
|
internal fun jsBind(receiver: Any?, target: Any?): Any?
|
||||||
|
|
||||||
|
@JsIntrinsic
|
||||||
|
internal fun jsCall(receiver: Any?, target: Any?, vararg args: Any?): Any?
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun <A> slice(a: A): A
|
internal fun <A> slice(a: A): A
|
||||||
|
|
||||||
@@ -220,4 +220,7 @@ internal fun <reified T : Any> jsClassIntrinsic(): JsClass<T>
|
|||||||
internal fun jsInIntrinsic(lhs: Any?, rhs: Any): Boolean
|
internal fun jsInIntrinsic(lhs: Any?, rhs: Any): Boolean
|
||||||
|
|
||||||
@JsIntrinsic
|
@JsIntrinsic
|
||||||
internal fun jsDelete(e: Any?)
|
internal fun jsDelete(e: Any?)
|
||||||
|
|
||||||
|
@JsIntrinsic
|
||||||
|
internal fun jsContextfulRef(context: dynamic, fn: dynamic): dynamic
|
||||||
@@ -44,8 +44,7 @@ private fun getKPropMetadata(paramCount: Int, setter: Any?): dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun metadataObject(): Metadata {
|
private fun metadataObject(): Metadata {
|
||||||
val undef = js("undefined")
|
return classMeta(VOID, VOID, VOID, VOID)
|
||||||
return classMeta(undef, undef, undef, undef)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val propertyRefClassMetadataCache: Array<Array<dynamic>> = arrayOf<Array<dynamic>>(
|
private val propertyRefClassMetadataCache: Array<Array<dynamic>> = arrayOf<Array<dynamic>>(
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ internal fun classMeta(name: String?, associatedObjectKey: Number?, associatedOb
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Seems like we need to disable this check if variables are used inside js annotation
|
// Seems like we need to disable this check if variables are used inside js annotation
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||||
private fun createMetadata(
|
private fun createMetadata(
|
||||||
kind: String,
|
kind: String,
|
||||||
name: String?,
|
name: String?,
|
||||||
@@ -53,13 +53,14 @@ private fun createMetadata(
|
|||||||
suspendArity: Array<Int>?,
|
suspendArity: Array<Int>?,
|
||||||
iid: Int?
|
iid: Int?
|
||||||
): Metadata {
|
): Metadata {
|
||||||
|
val undef = VOID
|
||||||
return js("""({
|
return js("""({
|
||||||
kind: kind,
|
kind: kind,
|
||||||
simpleName: name,
|
simpleName: name,
|
||||||
associatedObjectKey: associatedObjectKey,
|
associatedObjectKey: associatedObjectKey,
|
||||||
associatedObjects: associatedObjects,
|
associatedObjects: associatedObjects,
|
||||||
suspendArity: suspendArity,
|
suspendArity: suspendArity,
|
||||||
${'$'}kClass$: undefined,
|
${'$'}kClass$: undef,
|
||||||
iid: iid
|
iid: iid
|
||||||
})""")
|
})""")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
package kotlin.js
|
||||||
|
|
||||||
|
internal val VOID: Nothing? = js("void 0")
|
||||||
Reference in New Issue
Block a user