JS: fix translation of suspend lambda when it's not passed to another function
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
import kotlin.coroutines.intrinsics.*
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
|||||||
+1
-7
@@ -5864,13 +5864,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
@TestMetadata("localVal.kt")
|
@TestMetadata("localVal.kt")
|
||||||
public void testLocalVal() throws Exception {
|
public void testLocalVal() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt");
|
||||||
try {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("manyParameters.kt")
|
@TestMetadata("manyParameters.kt")
|
||||||
|
|||||||
+2
-2
@@ -446,13 +446,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsNode visitLambdaExpression(@NotNull KtLambdaExpression expression, @NotNull TranslationContext context) {
|
public JsNode visitLambdaExpression(@NotNull KtLambdaExpression expression, @NotNull TranslationContext context) {
|
||||||
return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral(), null);
|
return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsNode visitNamedFunction(@NotNull KtNamedFunction expression, @NotNull TranslationContext context) {
|
public JsNode visitNamedFunction(@NotNull KtNamedFunction expression, @NotNull TranslationContext context) {
|
||||||
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, null);
|
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression);
|
||||||
|
|
||||||
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
||||||
JsNameRef nameRef = (JsNameRef) ReferenceTranslator.translateAsValueReference(descriptor, context);
|
JsNameRef nameRef = (JsNameRef) ReferenceTranslator.translateAsValueReference(descriptor, context);
|
||||||
|
|||||||
+6
-11
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.expression
|
package org.jetbrains.kotlin.js.translate.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
@@ -38,13 +37,9 @@ import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
|||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) {
|
class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) {
|
||||||
fun translate(
|
fun translate(declaration: KtDeclarationWithBody): JsExpression {
|
||||||
declaration: KtDeclarationWithBody,
|
|
||||||
continuationType: KotlinType? = null
|
|
||||||
): JsExpression {
|
|
||||||
val invokingContext = context()
|
val invokingContext = context()
|
||||||
val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration)
|
val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration)
|
||||||
|
|
||||||
@@ -80,7 +75,7 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
|
|||||||
lambda.name = tracker.getNameForCapturedDescriptor(descriptor)
|
lambda.name = tracker.getNameForCapturedDescriptor(descriptor)
|
||||||
}
|
}
|
||||||
lambdaCreator.name.staticRef = lambdaCreator
|
lambdaCreator.name.staticRef = lambdaCreator
|
||||||
lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor, continuationType)
|
lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor)
|
||||||
return lambdaCreator.withCapturedParameters(descriptor, descriptor.wrapContextForCoroutineIfNecessary(functionContext),
|
return lambdaCreator.withCapturedParameters(descriptor, descriptor.wrapContextForCoroutineIfNecessary(functionContext),
|
||||||
invokingContext)
|
invokingContext)
|
||||||
}
|
}
|
||||||
@@ -96,15 +91,15 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
|
|||||||
lambda.isLocal = true
|
lambda.isLocal = true
|
||||||
|
|
||||||
invokingContext.addDeclarationStatement(lambda.makeStmt())
|
invokingContext.addDeclarationStatement(lambda.makeStmt())
|
||||||
lambda.fillCoroutineMetadata(invokingContext, descriptor, continuationType)
|
lambda.fillCoroutineMetadata(invokingContext, descriptor)
|
||||||
lambda.name.staticRef = lambda
|
lambda.name.staticRef = lambda
|
||||||
return getReferenceToLambda(invokingContext, descriptor, lambda.name)
|
return getReferenceToLambda(invokingContext, descriptor, lambda.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsFunction.fillCoroutineMetadata(context: TranslationContext, descriptor: FunctionDescriptor, continuationType: KotlinType?) {
|
fun JsFunction.fillCoroutineMetadata(context: TranslationContext, descriptor: FunctionDescriptor) {
|
||||||
if (continuationType == null) return
|
if (!descriptor.isSuspend) return
|
||||||
|
|
||||||
fillCoroutineMetadata(context, descriptor, hasController = continuationType.isBuiltinExtensionFunctionalType, isLambda = true)
|
fillCoroutineMetadata(context, descriptor, hasController = descriptor.extensionReceiverParameter != null, isLambda = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
|
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
|
||||||
|
|||||||
+12
-30
@@ -16,24 +16,26 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.reference
|
package org.jetbrains.kotlin.js.translate.reference
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable
|
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.expression.LiteralFunctionTranslator
|
|
||||||
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator
|
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.*
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass
|
||||||
import org.jetbrains.kotlin.psi.ValueArgument
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -151,26 +153,11 @@ class CallArgumentTranslator private constructor(
|
|||||||
context: TranslationContext,
|
context: TranslationContext,
|
||||||
resolvedCall: ResolvedCall<*>
|
resolvedCall: ResolvedCall<*>
|
||||||
): Map<ValueArgument, JsExpression> {
|
): Map<ValueArgument, JsExpression> {
|
||||||
val argsToParameters = resolvedCall.valueArguments
|
|
||||||
.flatMap { (param, args) -> args.arguments.map { param to it } }
|
|
||||||
.associate { (param, arg) -> arg to param }
|
|
||||||
|
|
||||||
val argumentContexts = resolvedCall.call.valueArguments.associate { it to context.innerBlock() }
|
val argumentContexts = resolvedCall.call.valueArguments.associate { it to context.innerBlock() }
|
||||||
|
|
||||||
var result = resolvedCall.call.valueArguments.associate { arg ->
|
var result = resolvedCall.call.valueArguments.associate { arg ->
|
||||||
val argumentContext = argumentContexts[arg]!!
|
val argumentContext = argumentContexts[arg]!!
|
||||||
val argumentExpression = KtPsiUtil.deparenthesize(arg.getArgumentExpression())
|
val jsExpr = Translation.translateAsExpression(arg.getArgumentExpression()!!, argumentContext)
|
||||||
|
|
||||||
val lambdaDescriptor = argumentExpression?.let { argumentContext.extractLambda(it) }
|
|
||||||
val jsExpr = if (lambdaDescriptor?.isSuspendLambda == true) {
|
|
||||||
val lambdaExpression = (argumentExpression as KtLambdaExpression).functionLiteral
|
|
||||||
val param = argsToParameters[arg]!!
|
|
||||||
LiteralFunctionTranslator(argumentContext).translate(lambdaExpression, param.type)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Translation.translateAsExpression(arg.getArgumentExpression()!!, argumentContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
arg to jsExpr
|
arg to jsExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,11 +212,6 @@ class CallArgumentTranslator private constructor(
|
|||||||
return resolvedArgument.arguments.map { translatedArgs[it]!! }
|
return resolvedArgument.arguments.map { translatedArgs[it]!! }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TranslationContext.extractLambda(expression: KtExpression): CallableDescriptor? {
|
|
||||||
val lambdaExpression = expression as? KtLambdaExpression ?: return null
|
|
||||||
return BindingUtils.getFunctionDescriptor(bindingContext(), lambdaExpression.functionLiteral)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translateVarargArgument(
|
private fun translateVarargArgument(
|
||||||
resolvedArgument: ResolvedValueArgument,
|
resolvedArgument: ResolvedValueArgument,
|
||||||
translatedArgs: Map<ValueArgument, JsExpression>,
|
translatedArgs: Map<ValueArgument, JsExpression>,
|
||||||
|
|||||||
Reference in New Issue
Block a user