[JS IR] Use one concat elements for non vararg and vararg arguments
^KT-42357 fixed
This commit is contained in:
+1
-1
@@ -160,7 +160,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
|||||||
if (varargParameterIndex == -1) {
|
if (varargParameterIndex == -1) {
|
||||||
JsNew(refForExternalClass, arguments)
|
JsNew(refForExternalClass, arguments)
|
||||||
} else {
|
} else {
|
||||||
val argumentsAsSingleArray = argumentsAsSingleArray(
|
val argumentsAsSingleArray = argumentsWithVarargAsSingleArray(
|
||||||
JsNullLiteral(),
|
JsNullLiteral(),
|
||||||
arguments,
|
arguments,
|
||||||
varargParameterIndex
|
varargParameterIndex
|
||||||
|
|||||||
+24
-18
@@ -137,7 +137,7 @@ fun translateCall(
|
|||||||
return if (isExternalVararg) {
|
return if (isExternalVararg) {
|
||||||
// TODO: Don't use `Function.prototype.apply` when number of arguments is known at compile time (e.g. there are no spread operators)
|
// TODO: Don't use `Function.prototype.apply` when number of arguments is known at compile time (e.g. there are no spread operators)
|
||||||
|
|
||||||
val argumentsAsSingleArray = argumentsAsSingleArray(
|
val argumentsAsSingleArray = argumentsWithVarargAsSingleArray(
|
||||||
jsExtensionReceiver,
|
jsExtensionReceiver,
|
||||||
arguments,
|
arguments,
|
||||||
varargParameterIndex
|
varargParameterIndex
|
||||||
@@ -183,21 +183,18 @@ fun translateCall(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun argumentsAsSingleArray(
|
fun argumentsWithVarargAsSingleArray(
|
||||||
additionalReceiver: JsExpression?,
|
additionalReceiver: JsExpression?,
|
||||||
arguments: List<JsExpression>,
|
arguments: List<JsExpression>,
|
||||||
varargParameterIndex: Int?
|
varargParameterIndex: Int,
|
||||||
): JsExpression {
|
): JsExpression {
|
||||||
// External vararg arguments should be represented in JS as multiple "plain" arguments (opposed to arrays in Kotlin)
|
// External vararg arguments should be represented in JS as multiple "plain" arguments (opposed to arrays in Kotlin)
|
||||||
// We are using `Function.prototype.apply` function to pass all arguments as a single array.
|
// We are using `Function.prototype.apply` function to pass all arguments as a single array.
|
||||||
// For this purpose are concatenating non-vararg arguments with vararg.
|
// For this purpose are concatenating non-vararg arguments with vararg.
|
||||||
var varargArgument: JsExpression? = null
|
var arraysForConcat: MutableList<JsExpression> = mutableListOf<JsExpression>().apply {
|
||||||
val additionalSize = additionalReceiver?.let { 1 } ?: 0
|
additionalReceiver?.let { add(it) }
|
||||||
// size + 1 because arguments size + potential additionalReceiver
|
}
|
||||||
val nonVarArgs: MutableList<JsExpression> =
|
val concatElements: MutableList<JsExpression> = mutableListOf()
|
||||||
ArrayList<JsExpression>(arguments.size + additionalSize).apply {
|
|
||||||
additionalReceiver?.let { add(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
arguments
|
arguments
|
||||||
.forEachIndexed { index, argument ->
|
.forEachIndexed { index, argument ->
|
||||||
@@ -205,25 +202,34 @@ internal fun argumentsAsSingleArray(
|
|||||||
|
|
||||||
// Call `Array.prototype.slice` on vararg arguments in order to convert array-like objects into proper arrays
|
// Call `Array.prototype.slice` on vararg arguments in order to convert array-like objects into proper arrays
|
||||||
varargParameterIndex -> {
|
varargParameterIndex -> {
|
||||||
varargArgument = if (argument is JsArrayLiteral) {
|
concatElements.add(JsArrayLiteral(arraysForConcat))
|
||||||
|
arraysForConcat = mutableListOf()
|
||||||
|
|
||||||
|
val varargArgument = if (argument is JsArrayLiteral) {
|
||||||
argument
|
argument
|
||||||
} else {
|
} else {
|
||||||
val arraySliceCall = JsNameRef("call", JsNameRef("slice", JsArrayLiteral()))
|
val arraySliceCall = JsNameRef("call", JsNameRef("slice", JsArrayLiteral()))
|
||||||
JsInvocation(arraySliceCall, argument)
|
JsInvocation(arraySliceCall, argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
concatElements.add(varargArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> nonVarArgs.add(argument)
|
else -> {
|
||||||
|
arraysForConcat.add(argument)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val nonVarArgArrayLiteral = JsArrayLiteral(nonVarArgs)
|
if (arraysForConcat.isNotEmpty() || concatElements.isEmpty()) {
|
||||||
return varargArgument?.let {
|
concatElements.add(JsArrayLiteral(arraysForConcat))
|
||||||
JsInvocation(
|
}
|
||||||
JsNameRef("concat", nonVarArgArrayLiteral),
|
|
||||||
it
|
return concatElements.singleOrNull()
|
||||||
|
?: JsInvocation(
|
||||||
|
JsNameRef("concat", concatElements.first()),
|
||||||
|
concatElements.drop(1)
|
||||||
)
|
)
|
||||||
} ?: nonVarArgArrayLiteral
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunction.varargParameterIndex() = valueParameters.indexOfFirst { it.varargElementType != null }
|
fun IrFunction.varargParameterIndex() = valueParameters.indexOfFirst { it.varargElementType != null }
|
||||||
|
|||||||
Reference in New Issue
Block a user