[JS IR] [runtime] Remove valueOf method from Long

This method was used for coercing `Long` values to JavaScript
`number`. However, it caused issues when `Long` values were
concatenated to a string (see KT-8666, KT-26706).
This commit is contained in:
Sergej Jaskiewicz
2021-11-30 18:14:44 +03:00
committed by Space
parent 3b98c330fd
commit e13b6b2a90
5 changed files with 85 additions and 104 deletions
@@ -161,12 +161,6 @@ private val expectDeclarationsRemovingPhase = makeDeclarationTransformerPhase(
description = "Remove expect declaration from module fragment"
)
private val stringConcatenationLoweringPhase = makeJsModulePhase(
::JsStringConcatenationLowering,
name = "JsStringConcatenationLowering",
description = "Call toString() for values of some types when concatenating strings"
).toModuleLowering()
private val lateinitNullableFieldsPhase = makeDeclarationTransformerPhase(
::NullableFieldsForLateinitCreationLowering,
name = "LateinitNullableFields",
@@ -832,7 +826,6 @@ val loweringList = listOf<Lowering>(
copyInlineFunctionBodyLoweringPhase,
removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase,
createScriptFunctionsPhase,
stringConcatenationLoweringPhase,
callableReferenceLowering,
singleAbstractMethodPhase,
tailrecLoweringPhase,
@@ -1,89 +0,0 @@
/*
* Copyright 2010-2021 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.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JsStringConcatenationLowering(val context: CommonBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(JsStringConcatenationTransformer(context))
}
}
private class JsStringConcatenationTransformer(val context: CommonBackendContext) : IrElementTransformerVoid() {
private val IrType.shouldExplicitlyConvertToString: Boolean
get() {
// If the type is Long or a supertype of Long, we want to call toString() on values of that type.
// See KT-39891
if (this !is IrSimpleType) return false
return when (classifier.signature) {
IdSignatureValues.any, IdSignatureValues.comparable, IdSignatureValues.number, IdSignatureValues._long -> true
else -> false
}
}
private fun IrExpression.explicitlyConvertedToString(): IrExpression {
assert(type.shouldExplicitlyConvertToString)
return if (type.isNullable()) {
JsIrBuilder.buildCall(context.ir.symbols.extensionToString).apply {
extensionReceiver = this@explicitlyConvertedToString
}
} else {
JsIrBuilder.buildCall(context.ir.symbols.memberToString).apply {
dispatchReceiver = this@explicitlyConvertedToString
}
}
}
private val IrFunctionSymbol.isStringPlus: Boolean
get() = context.ir.symbols.isStringPlus(this)
override fun visitCall(expression: IrCall): IrExpression {
fun explicitlyConvertToStringIfNeeded(): IrExpression {
val lastArgIndex = expression.valueArgumentsCount - 1
val plusArg = expression.getValueArgument(lastArgIndex) ?: return super.visitCall(expression)
if (!plusArg.type.shouldExplicitlyConvertToString)
return super.visitCall(expression)
expression.putValueArgument(lastArgIndex, plusArg.explicitlyConvertedToString())
return expression
}
if (expression.valueArgumentsCount == 0)
return super.visitCall(expression)
if (expression.symbol.isStringPlus)
return explicitlyConvertToStringIfNeeded()
if (expression.dispatchReceiver.safeAs<IrFunctionReference>()?.symbol?.isStringPlus == true)
return explicitlyConvertToStringIfNeeded()
return super.visitCall(expression)
}
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
expression
.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitExpression(expression: IrExpression): IrExpression {
if (expression.type.shouldExplicitlyConvertToString)
return expression.explicitlyConvertedToString()
return expression
}
})
return super.visitStringConcatenation(expression)
}
}