JS: support non-local return from secondary constructor
See KT-14549
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
// TODO enable for JS backend too when KT-14549 will be fixed
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
inline fun run(block: () -> Unit) = block()
|
||||
|
||||
class A {
|
||||
|
||||
@@ -53,6 +53,8 @@ var JsNameRef.psiElement: PsiElement? by MetadataProperty(default = null)
|
||||
|
||||
var JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var JsFunction.forcedReturnVariable: JsName? by MetadataProperty(default = null)
|
||||
|
||||
var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var JsInvocation.typeCheck: TypeCheck? by MetadataProperty(default = null)
|
||||
|
||||
@@ -361,6 +361,22 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
// body of inline function can contain call to lambdas that need to be inlined
|
||||
JsStatement inlineableBodyWithLambdasInlined = accept(inlineableBody);
|
||||
assert inlineableBody == inlineableBodyWithLambdasInlined;
|
||||
|
||||
// Support non-local return from secondary constructor
|
||||
// Returns from secondary constructors should return `$this` object.
|
||||
JsFunction currentFunction = getCurrentNamedFunction();
|
||||
if (currentFunction != null) {
|
||||
JsName returnVariable = MetadataProperties.getForcedReturnVariable(currentFunction);
|
||||
if (returnVariable != null) {
|
||||
inlineableBody.accept(new RecursiveJsVisitor() {
|
||||
@Override
|
||||
public void visitReturn(@NotNull JsReturn x) {
|
||||
x.setExpression(returnVariable.makeRef());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
statementContext.addPrevious(flattenStatement(inlineableBody));
|
||||
|
||||
/*
|
||||
|
||||
+1
-7
@@ -21884,13 +21884,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("withNonLocalReturn.kt")
|
||||
public void testWithNonLocalReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withReturn.kt")
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.forcedReturnVariable
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
||||
import org.jetbrains.kotlin.js.translate.context.*
|
||||
@@ -281,6 +282,7 @@ class ClassTranslator private constructor(
|
||||
}
|
||||
|
||||
constructorInitializer.parameters += JsParameter(thisName)
|
||||
constructorInitializer.forcedReturnVariable = thisName
|
||||
|
||||
// Generate super/this call to insert to beginning of the function
|
||||
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(context.bindingContext(), constructorDescriptor)
|
||||
|
||||
Reference in New Issue
Block a user