From 995d96e5a37fc6dfa3e504a996b027a8ba060663 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Mon, 23 Nov 2020 15:21:06 +0300 Subject: [PATCH] [JS IR] Use one concat elements for non vararg and vararg arguments ^KT-42357 fixed --- .../IrElementToJsExpressionTransformer.kt | 2 +- .../js/transformers/irToJs/jsAstUtils.kt | 42 +++++++++++-------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index 40ad1c3ee49..0c3334b390a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -160,7 +160,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer, - varargParameterIndex: Int? + varargParameterIndex: Int, ): JsExpression { // 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. // For this purpose are concatenating non-vararg arguments with vararg. - var varargArgument: JsExpression? = null - val additionalSize = additionalReceiver?.let { 1 } ?: 0 - // size + 1 because arguments size + potential additionalReceiver - val nonVarArgs: MutableList = - ArrayList(arguments.size + additionalSize).apply { - additionalReceiver?.let { add(it) } - } + var arraysForConcat: MutableList = mutableListOf().apply { + additionalReceiver?.let { add(it) } + } + val concatElements: MutableList = mutableListOf() arguments .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 varargParameterIndex -> { - varargArgument = if (argument is JsArrayLiteral) { + concatElements.add(JsArrayLiteral(arraysForConcat)) + arraysForConcat = mutableListOf() + + val varargArgument = if (argument is JsArrayLiteral) { argument } else { val arraySliceCall = JsNameRef("call", JsNameRef("slice", JsArrayLiteral())) JsInvocation(arraySliceCall, argument) } + + concatElements.add(varargArgument) } - else -> nonVarArgs.add(argument) + else -> { + arraysForConcat.add(argument) + } } } - val nonVarArgArrayLiteral = JsArrayLiteral(nonVarArgs) - return varargArgument?.let { - JsInvocation( - JsNameRef("concat", nonVarArgArrayLiteral), - it + if (arraysForConcat.isNotEmpty() || concatElements.isEmpty()) { + concatElements.add(JsArrayLiteral(arraysForConcat)) + } + + return concatElements.singleOrNull() + ?: JsInvocation( + JsNameRef("concat", concatElements.first()), + concatElements.drop(1) ) - } ?: nonVarArgArrayLiteral } fun IrFunction.varargParameterIndex() = valueParameters.indexOfFirst { it.varargElementType != null }