From c15847a957b2de8746357930f0fdfa95f48f2c20 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 27 Sep 2017 17:14:33 +0300 Subject: [PATCH] JS: support non-local return from secondary constructor See KT-14549 --- .../secondaryConstructors/withNonLocalReturn.kt | 3 --- .../backend/ast/metadata/metadataProperties.kt | 2 ++ .../jetbrains/kotlin/js/inline/JsInliner.java | 16 ++++++++++++++++ .../semantics/JsCodegenBoxTestGenerated.java | 8 +------- .../js/translate/declaration/ClassTranslator.kt | 2 ++ 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt index 2e56fdc0e88..0b0be6bbbac 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt @@ -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 { diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt index a4e5eb3898d..718196510b7 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/metadata/metadataProperties.kt @@ -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) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java index 4b73f125329..33a09cc4b60 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java @@ -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)); /* diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index ba10b1f4037..445d959cd07 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index 45d06d93a54..7a065d1156f 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.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)