[JS IR] Emit original names for local vars to sourcemaps
#KT-35655 Fixed
This commit is contained in:
committed by
Space Team
parent
8efa72ca36
commit
7b7c517dbb
+22
-11
@@ -6,18 +6,24 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.compilationException
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
private typealias Replacement = Pair<JsExpression, IrValueParameter>
|
||||
|
||||
class FunctionWithJsFuncAnnotationInliner(private val jsFuncCall: IrCall, private val context: JsGenerationContext) {
|
||||
private val function = getJsFunctionImplementation()
|
||||
private val replacements = collectReplacementsForCall()
|
||||
|
||||
fun generateResultStatement(): List<JsStatement> {
|
||||
val irFunction = jsFuncCall.symbol.owner
|
||||
val newContext = context.newFile(irFunction.file, irFunction, context.localNames)
|
||||
return function.body.statements
|
||||
.run {
|
||||
SimpleJsCodeInliner(replacements)
|
||||
SimpleJsCodeInliner(replacements, newContext)
|
||||
.apply { acceptList(this@run) }
|
||||
.withTemporaryVariablesForExpressions(this)
|
||||
}
|
||||
@@ -27,9 +33,10 @@ class FunctionWithJsFuncAnnotationInliner(private val jsFuncCall: IrCall, privat
|
||||
context.staticContext.backendContext.getJsCodeForFunction(jsFuncCall.symbol)?.deepCopy()
|
||||
?: compilationException("JS function not found", jsFuncCall)
|
||||
|
||||
private fun collectReplacementsForCall(): Map<JsName, JsExpression> {
|
||||
private fun collectReplacementsForCall(): Map<JsName, Replacement> {
|
||||
val translatedArguments = Array(jsFuncCall.valueArgumentsCount) {
|
||||
jsFuncCall.getValueArgument(it)!!.accept(IrElementToJsExpressionTransformer(), context)
|
||||
jsFuncCall.getValueArgument(it)!!
|
||||
.accept(IrElementToJsExpressionTransformer(), context) to jsFuncCall.symbol.owner.valueParameters[it]
|
||||
}
|
||||
return function.parameters
|
||||
.mapIndexed { i, param -> param.name to translatedArguments[i] }
|
||||
@@ -37,15 +44,19 @@ class FunctionWithJsFuncAnnotationInliner(private val jsFuncCall: IrCall, privat
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleJsCodeInliner(private val replacements: Map<JsName, JsExpression>): RecursiveJsVisitor() {
|
||||
private val temporaryNamesForExpressions = mutableMapOf<JsName, JsExpression>()
|
||||
private class SimpleJsCodeInliner(private val replacements: Map<JsName, Replacement>, val context: JsGenerationContext) :
|
||||
RecursiveJsVisitor()
|
||||
{
|
||||
private val temporaryNamesForExpressions = mutableMapOf<JsName, Replacement>()
|
||||
|
||||
fun withTemporaryVariablesForExpressions(statements: List<JsStatement>): List<JsStatement> {
|
||||
if (temporaryNamesForExpressions.isEmpty()) {
|
||||
return statements
|
||||
}
|
||||
|
||||
val variableDeclarations = temporaryNamesForExpressions.map { JsVars(JsVars.JsVar(it.key, it.value)) }
|
||||
val variableDeclarations = temporaryNamesForExpressions.map {
|
||||
JsVars(JsVars.JsVar(it.key, it.value.first).withSource(it.value.second, context, useNameOf = it.value.second))
|
||||
}
|
||||
return variableDeclarations + statements
|
||||
}
|
||||
|
||||
@@ -55,16 +66,16 @@ private class SimpleJsCodeInliner(private val replacements: Map<JsName, JsExpres
|
||||
nameRef.name = nameRef.name?.getReplacement() ?: return
|
||||
}
|
||||
|
||||
private fun JsName.declareNewTemporaryFor(expression: JsExpression): JsName {
|
||||
private fun JsName.declareNewTemporaryFor(expression: JsExpression, irValueParameter: IrValueParameter): JsName {
|
||||
return JsName(ident, true)
|
||||
.also { temporaryNamesForExpressions[it] = expression }
|
||||
.also { temporaryNamesForExpressions[it] = expression to irValueParameter }
|
||||
}
|
||||
|
||||
private fun JsName.getReplacement(): JsName? {
|
||||
val expression = replacements[this] ?: return null
|
||||
val (expression, irValueParameter) = replacements[this] ?: return null
|
||||
return when {
|
||||
expression is JsNameRef && expression.qualifier == null -> expression.name!!
|
||||
else -> declareNewTemporaryFor(expression)
|
||||
else -> declareNewTemporaryFor(expression, irValueParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -148,7 +148,8 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
}
|
||||
}
|
||||
|
||||
return jsVar(varName, value, context).withSource(declaration, context)
|
||||
val jsInitializer = value?.accept(IrElementToJsExpressionTransformer(), context)
|
||||
return JsVars(JsVars.JsVar(varName, jsInitializer).withSource(declaration, context, useNameOf = declaration))
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, context: JsGenerationContext): JsStatement {
|
||||
@@ -214,4 +215,3 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-10
@@ -6,10 +6,12 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.compilationException
|
||||
import org.jetbrains.kotlin.backend.common.lower.BOUND_VALUE_PARAMETER
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrFileEntry
|
||||
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.JsStatementOrigins
|
||||
import org.jetbrains.kotlin.ir.backend.js.sourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||
@@ -38,11 +40,6 @@ fun jsUndefined(context: IrNamer, backendContext: JsIrBackendContext): JsExpress
|
||||
}
|
||||
}
|
||||
|
||||
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
|
||||
val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context)
|
||||
return JsVars(JsVars.JsVar(name, jsInitializer))
|
||||
}
|
||||
|
||||
fun <T : JsNode> IrWhen.toJsNode(
|
||||
tr: BaseIrElementToJsNodeTransformer<T, JsGenerationContext>,
|
||||
context: JsGenerationContext,
|
||||
@@ -113,7 +110,7 @@ fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerat
|
||||
|
||||
val functionContext = context.newDeclaration(declaration, localNameGenerator)
|
||||
|
||||
val functionParams = declaration.valueParameters.map { functionContext.getNameForValueDeclaration(it) }
|
||||
val functionParams = declaration.valueParameters.map { it to functionContext.getNameForValueDeclaration(it) }
|
||||
val body = declaration.body?.accept(IrElementToJsStatementTransformer(), functionContext) as? JsBlock ?: JsBlock()
|
||||
|
||||
val function = JsFunction(emptyScope, body, "member function ${name ?: "annon"}")
|
||||
@@ -121,12 +118,12 @@ fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerat
|
||||
|
||||
function.name = name
|
||||
|
||||
fun JsFunction.addParameter(parameter: JsName) {
|
||||
parameters.add(JsParameter(parameter))
|
||||
fun JsFunction.addParameter(parameter: JsName, irValueParameter: IrValueParameter) {
|
||||
parameters.add(JsParameter(parameter).withSource(irValueParameter, functionContext, useNameOf = irValueParameter))
|
||||
}
|
||||
|
||||
declaration.extensionReceiverParameter?.let { function.addParameter(functionContext.getNameForValueDeclaration(it)) }
|
||||
functionParams.forEach { function.addParameter(it) }
|
||||
declaration.extensionReceiverParameter?.let { function.addParameter(functionContext.getNameForValueDeclaration(it), it) }
|
||||
functionParams.forEach { (irValueParameter, name) -> function.addParameter(name, irValueParameter) }
|
||||
check(!declaration.isSuspend) { "All Suspend functions should be lowered" }
|
||||
|
||||
return function
|
||||
@@ -621,6 +618,19 @@ private fun IrDeclarationWithName.originalNameForUseInSourceMap(policy: SourceMa
|
||||
return it.asString()
|
||||
}
|
||||
}
|
||||
|
||||
is IrValueDeclaration -> if (origin !in nameMappingOriginAllowList) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return name.asString()
|
||||
}
|
||||
|
||||
private val nameMappingOriginAllowList = setOf(
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrDeclarationOrigin.FOR_LOOP_VARIABLE,
|
||||
IrDeclarationOrigin.CATCH_PARAMETER,
|
||||
IrDeclarationOrigin.CONTINUATION,
|
||||
BOUND_VALUE_PARAMETER,
|
||||
JsLoweredDeclarationOrigin.JS_SHADOWED_DEFAULT_PARAMETER,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user