JS: fix translation of catch blocks so that all references to exception variable are referentially equivalent to each other
This commit is contained in:
+29
-12
@@ -18,11 +18,13 @@ package org.jetbrains.kotlin.js.translate.expression
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation.patternTranslator
|
import org.jetbrains.kotlin.js.translate.general.Translation.patternTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation.translateAsStatementAndMergeInBlockIfNeeded
|
import org.jetbrains.kotlin.js.translate.general.Translation.translateAsStatementAndMergeInBlockIfNeeded
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToBlock
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToBlock
|
||||||
import org.jetbrains.kotlin.psi.KtCatchClause
|
import org.jetbrains.kotlin.psi.KtCatchClause
|
||||||
@@ -68,34 +70,49 @@ class CatchTranslator(
|
|||||||
|
|
||||||
val firstCatch = catches.first()
|
val firstCatch = catches.first()
|
||||||
val catchParameter = firstCatch.catchParameter
|
val catchParameter = firstCatch.catchParameter
|
||||||
val parameterName = context().getNameForElement(catchParameter!!)
|
val parameterDescriptor = BindingUtils.getDescriptorForElement(bindingContext(), catchParameter!!)
|
||||||
val parameterRef = parameterName.makeRef()
|
val parameterName = context().getNameForDescriptor(parameterDescriptor).ident
|
||||||
|
|
||||||
return JsCatch(context().scope(),
|
val jsCatch = JsCatch(context().scope(), parameterName)
|
||||||
parameterRef.ident,
|
val parameterRef = jsCatch.parameter.name.makeRef()
|
||||||
translateCatches(parameterRef, catches.iterator()))
|
val catchContext = context().innerContextWithAliased(parameterDescriptor, parameterRef)
|
||||||
|
|
||||||
|
jsCatch.body = JsBlock(translateCatches(catchContext, parameterDescriptor, parameterRef, catches.iterator()))
|
||||||
|
|
||||||
|
return jsCatch
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateCatches(parameterRef: JsNameRef, catches: Iterator<KtCatchClause>): JsStatement {
|
private fun translateCatches(
|
||||||
|
context: TranslationContext,
|
||||||
|
parameterDescriptor: DeclarationDescriptor,
|
||||||
|
parameterRef: JsNameRef,
|
||||||
|
catches: Iterator<KtCatchClause>
|
||||||
|
): JsStatement {
|
||||||
if (!catches.hasNext()) return JsThrow(parameterRef)
|
if (!catches.hasNext()) return JsThrow(parameterRef)
|
||||||
|
|
||||||
|
var nextContext = context
|
||||||
|
|
||||||
val catch = catches.next()
|
val catch = catches.next()
|
||||||
val param = catch.catchParameter!!
|
val param = catch.catchParameter!!
|
||||||
val paramName = context().getNameForElement(param)
|
val paramName = context.getNameForElement(param)
|
||||||
val paramType = param.typeReference!!
|
val paramType = param.typeReference!!
|
||||||
|
|
||||||
val thenBlock = translateCatchBody(context(), catch)
|
val additionalStatements = mutableListOf<JsStatement>()
|
||||||
if (paramName.ident != parameterRef.ident)
|
if (paramName.ident != parameterRef.ident) {
|
||||||
thenBlock.statements.add(0, JsAstUtils.newVar(paramName, parameterRef))
|
additionalStatements += JsAstUtils.newVar(paramName, parameterRef)
|
||||||
|
nextContext = nextContext.innerContextWithAliased(parameterDescriptor, paramName.makeRef())
|
||||||
|
}
|
||||||
|
val thenBlock = translateCatchBody(context, catch)
|
||||||
|
thenBlock.statements.addAll(0, additionalStatements)
|
||||||
|
|
||||||
if (paramType.isThrowable) return thenBlock
|
if (paramType.isThrowable) return thenBlock
|
||||||
|
|
||||||
// translateIsCheck won't ever return `null` if its second argument is `null`
|
// translateIsCheck won't ever return `null` if its second argument is `null`
|
||||||
val typeCheck = with (patternTranslator(context())) {
|
val typeCheck = with (patternTranslator(nextContext)) {
|
||||||
translateIsCheck(parameterRef, null, paramType)
|
translateIsCheck(parameterRef, null, paramType)
|
||||||
}!!
|
}!!
|
||||||
|
|
||||||
val elseBlock = translateCatches(parameterRef, catches)
|
val elseBlock = translateCatches(nextContext, parameterDescriptor, parameterRef, catches)
|
||||||
return JsIf(typeCheck, thenBlock, elseBlock)
|
return JsIf(typeCheck, thenBlock, elseBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user