diff --git a/build-common/test/org/jetbrains/kotlin/serialization/js/ast/DebugJsAstProtoBuf.java b/build-common/test/org/jetbrains/kotlin/serialization/js/ast/DebugJsAstProtoBuf.java
index 5ee90c76468..8f32bf61ac4 100644
--- a/build-common/test/org/jetbrains/kotlin/serialization/js/ast/DebugJsAstProtoBuf.java
+++ b/build-common/test/org/jetbrains/kotlin/serialization/js/ast/DebugJsAstProtoBuf.java
@@ -211,6 +211,22 @@ public final class DebugJsAstProtoBuf {
* UNBOX_CHAR = 4;
*/
UNBOX_CHAR(3, 4),
+ /**
+ * SUSPEND_CALL = 5;
+ */
+ SUSPEND_CALL(4, 5),
+ /**
+ * COROUTINE_RESULT = 6;
+ */
+ COROUTINE_RESULT(5, 6),
+ /**
+ * COROUTINE_CONTROLLER = 7;
+ */
+ COROUTINE_CONTROLLER(6, 7),
+ /**
+ * COROUTINE_RECEIVER = 8;
+ */
+ COROUTINE_RECEIVER(7, 8),
;
/**
@@ -229,6 +245,22 @@ public final class DebugJsAstProtoBuf {
* UNBOX_CHAR = 4;
*/
public static final int UNBOX_CHAR_VALUE = 4;
+ /**
+ * SUSPEND_CALL = 5;
+ */
+ public static final int SUSPEND_CALL_VALUE = 5;
+ /**
+ * COROUTINE_RESULT = 6;
+ */
+ public static final int COROUTINE_RESULT_VALUE = 6;
+ /**
+ * COROUTINE_CONTROLLER = 7;
+ */
+ public static final int COROUTINE_CONTROLLER_VALUE = 7;
+ /**
+ * COROUTINE_RECEIVER = 8;
+ */
+ public static final int COROUTINE_RECEIVER_VALUE = 8;
public final int getNumber() { return value; }
@@ -239,6 +271,10 @@ public final class DebugJsAstProtoBuf {
case 2: return WRAP_FUNCTION;
case 3: return TO_BOXED_CHAR;
case 4: return UNBOX_CHAR;
+ case 5: return SUSPEND_CALL;
+ case 6: return COROUTINE_RESULT;
+ case 7: return COROUTINE_CONTROLLER;
+ case 8: return COROUTINE_RECEIVER;
default: return null;
}
}
@@ -49361,10 +49397,12 @@ public final class DebugJsAstProtoBuf {
"t.Fragment*@\n\013SideEffects\022\021\n\rAFFECTS_STA" +
"TE\020\001\022\024\n\020DEPENDS_ON_STATE\020\002\022\010\n\004PURE\020\003*?\n\016" +
"InlineStrategy\022\017\n\013AS_FUNCTION\020\000\022\014\n\010IN_PL" +
- "ACE\020\001\022\016\n\nNOT_INLINE\020\002*c\n\017SpecialFunction" +
- "\022\032\n\026DEFINE_INLINE_FUNCTION\020\001\022\021\n\rWRAP_FUN" +
- "CTION\020\002\022\021\n\rTO_BOXED_CHAR\020\003\022\016\n\nUNBOX_CHAR" +
- "\020\004B\024B\022DebugJsAstProtoBuf"
+ "ACE\020\001\022\016\n\nNOT_INLINE\020\002*\275\001\n\017SpecialFunctio" +
+ "n\022\032\n\026DEFINE_INLINE_FUNCTION\020\001\022\021\n\rWRAP_FU" +
+ "NCTION\020\002\022\021\n\rTO_BOXED_CHAR\020\003\022\016\n\nUNBOX_CHA" +
+ "R\020\004\022\020\n\014SUSPEND_CALL\020\005\022\024\n\020COROUTINE_RESUL" +
+ "T\020\006\022\030\n\024COROUTINE_CONTROLLER\020\007\022\026\n\022COROUTI" +
+ "NE_RECEIVER\020\010B\024B\022DebugJsAstProtoBuf"
};
org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new org.jetbrains.kotlin.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
diff --git a/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt
new file mode 100644
index 00000000000..ad5db0563d9
--- /dev/null
+++ b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt
@@ -0,0 +1,69 @@
+// IGNORE_BACKEND: NATIVE
+// WITH_COROUTINES
+// WITH_RUNTIME
+
+// MODULE: lib(support)
+// FILE: lib.kt
+
+import helpers.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+var continuation: () -> Unit = { }
+var log = ""
+var finished = false
+
+suspend fun foo(v: T): T = suspendCoroutineOrReturn { x ->
+ continuation = {
+ x.resume(v)
+ }
+ log += "foo($v);"
+ COROUTINE_SUSPENDED
+}
+
+inline suspend fun bar(v: String) {
+ log += "before bar($v);"
+ foo("1:$v")
+ log += "inside bar($v);"
+ foo("2:$v")
+ log += "after bar($v);"
+}
+
+fun builder(c: suspend () -> Unit) {
+ c.startCoroutine(handleResultContinuation {
+ continuation = { }
+ finished = true
+ })
+}
+
+// MODULE: main(lib)
+// FILE: main.kt
+
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+suspend fun baz() {
+ bar("A")
+ log += "between bar;"
+ bar("B")
+}
+
+val expectedString =
+ "before bar(A);foo(1:A);@;inside bar(A);foo(2:A);@;after bar(A);" +
+ "between bar;" +
+ "before bar(B);foo(1:B);@;inside bar(B);foo(2:B);@;after bar(B);"
+
+fun box(): String {
+ builder {
+ baz()
+ }
+
+ while (!finished) {
+ log += "@;"
+ continuation()
+ }
+
+ if (log != expectedString) return "fail: $log"
+
+ return "OK"
+}
diff --git a/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt
new file mode 100644
index 00000000000..bc9a47a50f5
--- /dev/null
+++ b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt
@@ -0,0 +1,80 @@
+// IGNORE_BACKEND: NATIVE
+// IGNORE_BACKEND: JVM
+// WITH_COROUTINES
+// WITH_RUNTIME
+
+// MODULE: lib(support)
+// FILE: lib.kt
+
+import helpers.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+var continuation: () -> Unit = { }
+var log = ""
+var finished = false
+
+suspend fun foo(v: T): T = suspendCoroutineOrReturn { x ->
+ continuation = {
+ x.resume(v)
+ }
+ log += "foo($v);"
+ COROUTINE_SUSPENDED
+}
+
+interface I {
+ suspend fun bar()
+}
+
+class A(val v: String) : I {
+ override inline suspend fun bar() {
+ log += "before bar($v);"
+ foo("1:$v")
+ log += "inside bar($v);"
+ foo("2:$v")
+ log += "after bar($v);"
+ }
+}
+
+fun builder(c: suspend () -> Unit) {
+ c.startCoroutine(handleResultContinuation {
+ continuation = { }
+ finished = true
+ })
+}
+
+// MODULE: main(lib)
+// FILE: main.kt
+
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+suspend fun baz() {
+ val a = A("A")
+ a.bar()
+
+ log += "between bar;"
+
+ val b: I = A("B")
+ b.bar()
+}
+
+val expectedString =
+ "before bar(A);foo(1:A);@;inside bar(A);foo(2:A);@;after bar(A);" +
+ "between bar;" +
+ "before bar(B);foo(1:B);@;inside bar(B);foo(2:B);@;after bar(B);"
+
+fun box(): String {
+ builder {
+ baz()
+ }
+
+ while (!finished) {
+ log += "@;"
+ continuation()
+ }
+
+ if (log != expectedString) return "fail: $log"
+
+ return "OK"
+}
diff --git a/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt
new file mode 100644
index 00000000000..902ef8e991f
--- /dev/null
+++ b/compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt
@@ -0,0 +1,77 @@
+// IGNORE_BACKEND: NATIVE
+// WITH_COROUTINES
+// WITH_RUNTIME
+
+// MODULE: lib(support)
+// FILE: lib.kt
+
+import helpers.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+var continuation: () -> Unit = { }
+var log = ""
+var finished = false
+
+class C {
+ var v: String = ""
+
+ inline suspend fun bar() {
+ log += "before bar($v);"
+ foo("1:$v")
+ log += "inside bar($v);"
+ foo("2:$v")
+ log += "after bar($v);"
+ }
+}
+
+suspend fun foo(v: T): T = suspendCoroutineOrReturn { x ->
+ continuation = {
+ x.resume(v)
+ }
+ log += "foo($v);"
+ COROUTINE_SUSPENDED
+}
+
+fun C.builder(c: suspend C.() -> Unit) {
+ c.startCoroutine(this, handleResultContinuation {
+ continuation = { }
+ finished = true
+ })
+}
+
+// MODULE: main(lib)
+// FILE: main.kt
+
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+suspend fun C.baz() {
+ v = "A"
+ bar()
+ log += "between bar;"
+ v = "B"
+ bar()
+}
+
+val expectedString =
+ "before bar(A);foo(1:A);@;inside bar(A);foo(2:A);@;after bar(A);" +
+ "between bar;" +
+ "before bar(B);foo(1:B);@;inside bar(B);foo(2:B);@;after bar(B);"
+
+fun box(): String {
+ var c = C()
+
+ c.builder {
+ baz()
+ }
+
+ while (!finished) {
+ log += "@;"
+ continuation()
+ }
+
+ if (log != expectedString) return "fail: $log"
+
+ return "OK"
+}
diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java
index 432c90eac09..4584c79d688 100644
--- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java
+++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java
@@ -5788,6 +5788,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
+ @TestMetadata("inlineMultiModule.kt")
+ public void testInlineMultiModule() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("inlineMultiModuleOverride.kt")
+ public void testInlineMultiModuleOverride() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt");
+ try {
+ doTest(fileName);
+ }
+ catch (Throwable ignore) {
+ return;
+ }
+ throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
+ }
+
+ @TestMetadata("inlineMultiModuleWithController.kt")
+ public void testInlineMultiModuleWithController() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/simple.kt");
diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java
index 76893a87724..7ad0b3590e2 100644
--- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java
@@ -5788,6 +5788,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
+ @TestMetadata("inlineMultiModule.kt")
+ public void testInlineMultiModule() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("inlineMultiModuleOverride.kt")
+ public void testInlineMultiModuleOverride() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt");
+ try {
+ doTest(fileName);
+ }
+ catch (Throwable ignore) {
+ return;
+ }
+ throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
+ }
+
+ @TestMetadata("inlineMultiModuleWithController.kt")
+ public void testInlineMultiModuleWithController() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/simple.kt");
diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
index 93dee7c4d1f..bcac1e48bcb 100644
--- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
@@ -5778,6 +5778,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MultiModule extends AbstractLightAnalysisModeTest {
+ @TestMetadata("inlineMultiModuleOverride.kt")
+ public void ignoreInlineMultiModuleOverride() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt");
+ try {
+ doTest(fileName);
+ }
+ catch (Throwable ignore) {
+ return;
+ }
+ throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
+ }
+
public void testAllFilesPresentInMultiModule() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/multiModule"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@@ -5788,6 +5800,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
+ @TestMetadata("inlineMultiModule.kt")
+ public void testInlineMultiModule() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("inlineMultiModuleWithController.kt")
+ public void testInlineMultiModuleWithController() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/simple.kt");
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
index 878f4d155f2..95c5dc6945d 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
@@ -59,19 +59,26 @@ public abstract class JsVisitorWithContext {
doAcceptStatementList(statements);
}
+ public void endVisit(@NotNull JsExpression x, @NotNull JsContext ctx) {
+ }
+
public void endVisit(@NotNull JsArrayAccess x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsArrayLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsBinaryOperation x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsBlock x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsBooleanLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsBreak x, @NotNull JsContext ctx) {
@@ -84,6 +91,7 @@ public abstract class JsVisitorWithContext {
}
public void endVisit(@NotNull JsConditional x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsContinue x, @NotNull JsContext ctx) {
@@ -111,12 +119,14 @@ public abstract class JsVisitorWithContext {
}
public void endVisit(@NotNull JsFunction x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsIf x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsInvocation x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsLabel x, @NotNull JsContext ctx) {
@@ -126,27 +136,33 @@ public abstract class JsVisitorWithContext {
}
public void endVisit(@NotNull JsNameRef x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsNew x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsNullLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsNumberLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsObjectLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsParameter x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsPostfixOperation x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsPrefixOperation x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsProgram x, @NotNull JsContext ctx) {
@@ -156,18 +172,21 @@ public abstract class JsVisitorWithContext {
}
public void endVisit(@NotNull JsRegExp x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsReturn x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsStringLiteral x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsSwitch x, @NotNull JsContext ctx) {
}
public void endVisit(@NotNull JsThisRef x, @NotNull JsContext ctx) {
+ endVisit((JsExpression) x, ctx);
}
public void endVisit(@NotNull JsThrow x, @NotNull JsContext ctx) {
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 1a54f7ff717..a4e5eb3898d 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
@@ -147,6 +147,10 @@ enum class SpecialFunction(val suggestedName: String) {
WRAP_FUNCTION("wrapFunction"),
TO_BOXED_CHAR("toBoxedChar"),
UNBOX_CHAR("unboxChar"),
+ SUSPEND_CALL("suspendCall"),
+ COROUTINE_RESULT("coroutineResult"),
+ COROUTINE_CONTROLLER("coroutineController"),
+ COROUTINE_RECEIVER("coroutineReceiver")
}
enum class BoxingKind {
diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt
index c01ad90a15d..aa1a6f34813 100644
--- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt
+++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt
@@ -49,7 +49,10 @@ private val JS_IDENTIFIER_PART = "$JS_IDENTIFIER_START\\p{Pc}\\p{Mc}\\p{Mn}\\d"
private val JS_IDENTIFIER="[$JS_IDENTIFIER_START][$JS_IDENTIFIER_PART]*"
private val DEFINE_MODULE_PATTERN = ("($JS_IDENTIFIER)\\.defineModule\\(\\s*(['\"])([^'\"]+)\\2\\s*,\\s*(\\w+)\\s*\\)").toRegex().toPattern()
private val DEFINE_MODULE_FIND_PATTERN = ".defineModule("
-private val WRAP_FUNCTION_PATTERN = Regex("var\\s+($JS_IDENTIFIER)\\s*=\\s*($JS_IDENTIFIER)\\.wrapFunction\\s*;").toPattern()
+
+private val specialFunctions = enumValues().joinToString("|") { it.suggestedName }
+private val specialFunctionsByName = enumValues().associateBy { it.suggestedName }
+private val SPECIAL_FUNCTION_PATTERN = Regex("var\\s+($JS_IDENTIFIER)\\s*=\\s*($JS_IDENTIFIER)\\.($specialFunctions)\\s*;").toPattern()
class FunctionReader(
private val reporter: JsConfig.Reporter,
@@ -72,13 +75,15 @@ class FunctionReader(
val fileContent: String,
val moduleVariable: String,
val kotlinVariable: String,
- val wrapFunctionVariable: String?,
+ val specialFunctions: Map,
offsetToSourceMappingProvider: () -> OffsetToSourceMapping,
val sourceMap: SourceMap?
) {
val offsetToSourceMapping by lazy(offsetToSourceMappingProvider)
- val wrapFunctionRegex = wrapFunctionVariable?.let { Regex("\\s*$it\\s*\\(\\s*").toPattern() }
+ val wrapFunctionRegex = specialFunctions.entries
+ .singleOrNull { (_, v) -> v == SpecialFunction.WRAP_FUNCTION }?.key
+ ?.let { Regex("\\s*$it\\s*\\(\\s*").toPattern() }
}
private val moduleNameToInfo by lazy {
@@ -100,8 +105,12 @@ class FunctionReader(
val moduleVariable = preciseMatcher.group(4)
val kotlinVariable = preciseMatcher.group(1)
- val wrapFunctionVariable = WRAP_FUNCTION_PATTERN.matcher(content).let { matcher ->
- if (matcher.find() && matcher.group(2) == kotlinVariable) matcher.group(1) else null
+ val matcher = SPECIAL_FUNCTION_PATTERN.matcher(content)
+ val specialFunctions = mutableMapOf()
+ while (matcher.find()) {
+ if (matcher.group(2) == kotlinVariable) {
+ specialFunctions[matcher.group(1)] = specialFunctionsByName[matcher.group(3)]!!
+ }
}
val sourceMap = sourceMapContent?.let {
@@ -120,7 +129,7 @@ class FunctionReader(
fileContent = content,
moduleVariable = moduleVariable,
kotlinVariable = kotlinVariable,
- wrapFunctionVariable = wrapFunctionVariable,
+ specialFunctions = specialFunctions,
offsetToSourceMappingProvider = { OffsetToSourceMapping(content) },
sourceMap = sourceMap
)
@@ -246,9 +255,9 @@ class FunctionReader(
function.markInlineArguments(descriptor)
markDefaultParams(function)
- info.wrapFunctionVariable.let { wrapFunction ->
- for (externalName in (collectReferencedNames(function) - allDefinedNames).filter { it.ident == wrapFunction }) {
- externalName.specialFunction = SpecialFunction.WRAP_FUNCTION
+ for (externalName in (collectReferencedNames(function) - allDefinedNames)) {
+ info.specialFunctions[externalName.ident]?.let {
+ externalName.specialFunction = it
}
}
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 1b88c5d3267..4b73f125329 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
@@ -43,6 +43,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.jetbrains.kotlin.js.inline.util.CollectUtilsKt.getImportTag;
+import static org.jetbrains.kotlin.js.translate.declaration.InlineCoroutineUtilKt.transformSpecialFunctionsToCoroutineMetadata;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.flattenStatement;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
@@ -348,6 +349,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
}
JsFunction function = functionWithWrapper.getFunction().deepCopy();
+ function.setBody(transformSpecialFunctionsToCoroutineMetadata(function.getBody()));
if (functionWithWrapper.getWrapperBody() != null) {
applyWrapper(functionWithWrapper.getWrapperBody(), function, functionWithWrapper.getFunction(), inliningContext);
}
diff --git a/js/js.libraries/src/js/markerFunctions.js b/js/js.libraries/src/js/markerFunctions.js
index eab19252910..e02aaafb26e 100644
--- a/js/js.libraries/src/js/markerFunctions.js
+++ b/js/js.libraries/src/js/markerFunctions.js
@@ -61,3 +61,16 @@ Kotlin.andPredicate = function (a, b) {
Kotlin.kotlinModuleMetadata = function (abiVersion, moduleName, data) {
};
+
+Kotlin.suspendCall = function(value) {
+ return value;
+};
+
+Kotlin.coroutineResult = function(qualifier) {
+};
+
+Kotlin.coroutineController = function(qualifier) {
+};
+
+Kotlin.coroutineReceiver = function(qualifier) {
+};
\ No newline at end of file
diff --git a/js/js.serializer/src/js-ast.proto b/js/js.serializer/src/js-ast.proto
index 6a904c7dee3..9635474d45d 100644
--- a/js/js.serializer/src/js-ast.proto
+++ b/js/js.serializer/src/js-ast.proto
@@ -435,6 +435,10 @@ enum SpecialFunction {
WRAP_FUNCTION = 2;
TO_BOXED_CHAR = 3;
UNBOX_CHAR = 4;
+ SUSPEND_CALL = 5;
+ COROUTINE_RESULT = 6;
+ COROUTINE_CONTROLLER = 7;
+ COROUTINE_RECEIVER = 8;
}
diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializer.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializer.kt
index 686dbe9c8c7..06ccb635204 100644
--- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializer.kt
+++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializer.kt
@@ -522,6 +522,10 @@ class JsAstDeserializer(program: JsProgram, private val sourceRoots: Iterable SpecialFunction.WRAP_FUNCTION
JsAstProtoBuf.SpecialFunction.TO_BOXED_CHAR -> SpecialFunction.TO_BOXED_CHAR
JsAstProtoBuf.SpecialFunction.UNBOX_CHAR -> SpecialFunction.UNBOX_CHAR
+ JsAstProtoBuf.SpecialFunction.SUSPEND_CALL -> SpecialFunction.SUSPEND_CALL
+ JsAstProtoBuf.SpecialFunction.COROUTINE_RESULT -> SpecialFunction.COROUTINE_RESULT
+ JsAstProtoBuf.SpecialFunction.COROUTINE_CONTROLLER -> SpecialFunction.COROUTINE_CONTROLLER
+ JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER -> SpecialFunction.COROUTINE_RECEIVER
}
private fun withLocation(fileId: Int?, location: Location?, action: () -> T): T {
diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java
index 21c70d3290c..cb5593bd162 100644
--- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java
+++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java
@@ -159,6 +159,22 @@ public final class JsAstProtoBuf {
* UNBOX_CHAR = 4;
*/
UNBOX_CHAR(3, 4),
+ /**
+ * SUSPEND_CALL = 5;
+ */
+ SUSPEND_CALL(4, 5),
+ /**
+ * COROUTINE_RESULT = 6;
+ */
+ COROUTINE_RESULT(5, 6),
+ /**
+ * COROUTINE_CONTROLLER = 7;
+ */
+ COROUTINE_CONTROLLER(6, 7),
+ /**
+ * COROUTINE_RECEIVER = 8;
+ */
+ COROUTINE_RECEIVER(7, 8),
;
/**
@@ -177,6 +193,22 @@ public final class JsAstProtoBuf {
* UNBOX_CHAR = 4;
*/
public static final int UNBOX_CHAR_VALUE = 4;
+ /**
+ * SUSPEND_CALL = 5;
+ */
+ public static final int SUSPEND_CALL_VALUE = 5;
+ /**
+ * COROUTINE_RESULT = 6;
+ */
+ public static final int COROUTINE_RESULT_VALUE = 6;
+ /**
+ * COROUTINE_CONTROLLER = 7;
+ */
+ public static final int COROUTINE_CONTROLLER_VALUE = 7;
+ /**
+ * COROUTINE_RECEIVER = 8;
+ */
+ public static final int COROUTINE_RECEIVER_VALUE = 8;
public final int getNumber() { return value; }
@@ -187,6 +219,10 @@ public final class JsAstProtoBuf {
case 2: return WRAP_FUNCTION;
case 3: return TO_BOXED_CHAR;
case 4: return UNBOX_CHAR;
+ case 5: return SUSPEND_CALL;
+ case 6: return COROUTINE_RESULT;
+ case 7: return COROUTINE_CONTROLLER;
+ case 8: return COROUTINE_RECEIVER;
default: return null;
}
}
diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt
index 46ac9253136..a6275fc2f62 100644
--- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt
+++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt
@@ -558,6 +558,10 @@ class JsAstSerializer(private val pathResolver: (File) -> String) {
SpecialFunction.WRAP_FUNCTION -> JsAstProtoBuf.SpecialFunction.WRAP_FUNCTION
SpecialFunction.TO_BOXED_CHAR -> JsAstProtoBuf.SpecialFunction.TO_BOXED_CHAR
SpecialFunction.UNBOX_CHAR -> JsAstProtoBuf.SpecialFunction.UNBOX_CHAR
+ SpecialFunction.SUSPEND_CALL -> JsAstProtoBuf.SpecialFunction.SUSPEND_CALL
+ SpecialFunction.COROUTINE_RESULT -> JsAstProtoBuf.SpecialFunction.COROUTINE_RESULT
+ SpecialFunction.COROUTINE_CONTROLLER -> JsAstProtoBuf.SpecialFunction.COROUTINE_CONTROLLER
+ SpecialFunction.COROUTINE_RECEIVER -> JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER
}
private fun serialize(name: JsName): Int = nameMap.getOrPut(name) {
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 f7196604228..ba10b1f4037 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
@@ -6424,6 +6424,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
+ @TestMetadata("inlineMultiModule.kt")
+ public void testInlineMultiModule() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModule.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("inlineMultiModuleOverride.kt")
+ public void testInlineMultiModuleOverride() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleOverride.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("inlineMultiModuleWithController.kt")
+ public void testInlineMultiModuleWithController() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/inlineMultiModuleWithController.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/multiModule/simple.kt");
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
index b932ba79101..5db760caffe 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java
@@ -95,7 +95,6 @@ public final class Namer {
public static final JsNameRef IS_ARRAY_FUN_REF = new JsNameRef("isArray", "Array");
public static final String DEFINE_INLINE_FUNCTION = "defineInlineFunction";
- private static final String WRAP_FUNCTION = "wrapFunction";
public static final String DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX = "$default";
private static final JsNameRef JS_OBJECT = new JsNameRef("Object");
@@ -324,30 +323,9 @@ public final class Namer {
return pureFqn("Long", kotlinObject());
}
- @NotNull
- private static JsNameRef createInlineFunction() {
- return pureFqn(DEFINE_INLINE_FUNCTION, kotlinObject());
- }
-
- @NotNull
- private static JsNameRef wrapFunction() {
- return pureFqn(WRAP_FUNCTION, kotlinObject());
- }
-
@NotNull
public static JsExpression createSpecialFunction(@NotNull SpecialFunction specialFunction) {
- switch (specialFunction) {
- case DEFINE_INLINE_FUNCTION:
- return createInlineFunction();
- case WRAP_FUNCTION:
- return wrapFunction();
- case TO_BOXED_CHAR:
- return pureFqn("toBoxedChar", kotlinObject());
- case UNBOX_CHAR:
- return pureFqn("unboxChar", kotlinObject());
- default:
- throw new IllegalArgumentException("Unknown function: " + specialFunction);
- }
+ return pureFqn(specialFunction.getSuggestedName(), kotlinObject());
}
@NotNull
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt
index 2b8ec1f5e3b..5c9a778fd8d 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt
@@ -21,15 +21,17 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.isOverridable
import org.jetbrains.kotlin.js.backend.ast.JsExpression
+import org.jetbrains.kotlin.js.backend.ast.JsFunction
import org.jetbrains.kotlin.js.backend.ast.JsName
+import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
+import org.jetbrains.kotlin.js.descriptorUtils.shouldBeExported
import org.jetbrains.kotlin.js.translate.context.TranslationContext
-import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
-import org.jetbrains.kotlin.js.translate.expression.translateFunction
-import org.jetbrains.kotlin.js.translate.expression.wrapWithInlineMetadata
+import org.jetbrains.kotlin.js.translate.expression.*
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
+import org.jetbrains.kotlin.resolve.source.getPsi
abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
override fun emptyResult(context: TranslationContext) { }
@@ -52,7 +54,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
val defaultTranslator = DefaultPropertyTranslator(descriptor, context, getBackingFieldReference(descriptor))
val getter = descriptor.getter!!
val getterExpr = if (expression.hasCustomGetter()) {
- translateFunction(getter, expression.getter!!, propertyContext)
+ translateFunction(getter, expression.getter!!, propertyContext).first
}
else {
val function = context.getFunctionObject(getter)
@@ -64,7 +66,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
val setterExpr = if (descriptor.isVar) {
val setter = descriptor.setter!!
if (expression.hasCustomSetter()) {
- translateFunction(setter, expression.setter!!, propertyContext)
+ translateFunction(setter, expression.setter!!, propertyContext).first
}
else {
val function = context.getFunctionObject(setter)
@@ -88,8 +90,23 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
override fun visitNamedFunction(expression: KtNamedFunction, context: TranslationContext) {
val descriptor = BindingUtils.getFunctionDescriptor(context.bindingContext(), expression)
- val jsFunction = if (descriptor.modality != Modality.ABSTRACT) translateFunction(descriptor, expression, context) else null
- addFunction(descriptor, jsFunction, expression)
+ val functionAndContext = if (descriptor.modality != Modality.ABSTRACT) {
+ translateFunction(descriptor, expression, context)
+ }
+ else {
+ null
+ }
+ addFunction(descriptor, functionAndContext?.first, expression)
+
+ if (descriptor.isSuspend && descriptor.isInline && descriptor.shouldBeExported(context.config) && functionAndContext != null) {
+ val innerContext = functionAndContext.second
+ val inlineFunction = transformCoroutineMetadataToSpecialFunctions(context, functionAndContext.first.deepCopy() as JsFunction)
+ inlineFunction.name = null
+ inlineFunction.coroutineMetadata = null
+ val metadata = InlineMetadata.compose(inlineFunction, descriptor, innerContext)
+ val functionWithMetadata = metadata.functionWithMetadata(context, descriptor.source.getPsi())
+ context.addDeclarationStatement(functionWithMetadata.makeStmt())
+ }
}
override fun visitTypeAlias(typeAlias: KtTypeAlias, data: TranslationContext?) {}
@@ -98,7 +115,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
descriptor: FunctionDescriptor,
expression: KtDeclarationWithBody,
context: TranslationContext
- ): JsExpression {
+ ): Pair {
val function = context.getFunctionObject(descriptor)
function.source = expression.finalElement
val innerContext = context.newDeclaration(descriptor).translateAndAliasParameters(descriptor, function.parameters)
@@ -113,7 +130,14 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() {
function.body.statements += FunctionBodyTranslator.setDefaultValueForArguments(descriptor, innerContext)
}
innerContext.translateFunction(expression, function)
- return innerContext.wrapWithInlineMetadata(context, function, descriptor)
+ val result = if (descriptor.isSuspend && descriptor.shouldBeExported(context.config)) {
+ function
+ }
+ else {
+ innerContext.wrapWithInlineMetadata(context, function, descriptor)
+ }
+
+ return Pair(result, innerContext)
}
// used from kotlinx.serialization
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/inlineCoroutineUtil.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/inlineCoroutineUtil.kt
new file mode 100644
index 00000000000..7c14f3749ff
--- /dev/null
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/inlineCoroutineUtil.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright 2010-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.js.translate.declaration
+
+import org.jetbrains.kotlin.js.backend.ast.*
+import org.jetbrains.kotlin.js.backend.ast.metadata.*
+import org.jetbrains.kotlin.js.translate.context.TranslationContext
+import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
+import org.jetbrains.kotlin.js.translate.utils.name
+
+fun transformCoroutineMetadataToSpecialFunctions(context: TranslationContext, node: T): T {
+ val visitor = object : JsVisitorWithContextImpl() {
+ override fun endVisit(x: JsNameRef, ctx: JsContext) {
+ val specialFunction = when {
+ x.coroutineController -> SpecialFunction.COROUTINE_CONTROLLER
+ x.coroutineReceiver -> SpecialFunction.COROUTINE_RECEIVER
+ x.coroutineResult -> SpecialFunction.COROUTINE_RESULT
+ else -> null
+ }
+ if (specialFunction != null) {
+ val arguments = listOfNotNull(x.qualifier).toTypedArray()
+ ctx.replaceMe(TranslationUtils.invokeSpecialFunction(context, specialFunction, *arguments).source(x.source))
+ }
+ else {
+ super.endVisit(x, ctx)
+ }
+ }
+
+ override fun endVisit(x: JsExpression, ctx: JsContext) {
+ if (x.isSuspend) {
+ x.isSuspend = false
+ ctx.replaceMe(TranslationUtils.invokeSpecialFunction(context, SpecialFunction.SUSPEND_CALL, x).source(x.source))
+ }
+ }
+ }
+ return visitor.accept(node)
+}
+
+fun transformSpecialFunctionsToCoroutineMetadata(node: T): T {
+ val visitor = object : JsVisitorWithContextImpl() {
+ override fun endVisit(x: JsInvocation, ctx: JsContext) {
+ x.qualifier.name?.specialFunction?.let { specialFunction ->
+ val replacement = when (specialFunction) {
+ SpecialFunction.COROUTINE_CONTROLLER -> {
+ JsNameRef("\$\$controller\$\$", x.arguments.getOrNull(0)).apply {
+ coroutineController = true
+ }
+ }
+ SpecialFunction.COROUTINE_RECEIVER -> {
+ JsNameRef("\$this\$", x.arguments.getOrNull(0)).apply {
+ coroutineReceiver = true
+ }
+ }
+ SpecialFunction.COROUTINE_RESULT -> {
+ JsNameRef("\$result\$", x.arguments.getOrNull(0)).apply {
+ coroutineResult = true
+ }
+ }
+ SpecialFunction.SUSPEND_CALL -> {
+ x.arguments[0].apply {
+ isSuspend = true
+ }
+ }
+ else -> null
+ }
+ replacement?.let { ctx.replaceMe(it) }
+ }
+ }
+ }
+ return visitor.accept(node)
+}
\ No newline at end of file
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt
index 73f55169dc5..ae52db9da4a 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt
@@ -112,7 +112,7 @@ fun TranslationContext.wrapWithInlineMetadata(
if (descriptor.shouldBeExported(config)) {
val metadata = InlineMetadata.compose(function, descriptor, this)
val functionWithMetadata = metadata.functionWithMetadata(outerContext, sourceInfo)
- config.configuration[JSConfigurationKeys.INCREMENTAL_RESULTS_CONSUMER]?.apply {
+ config.configuration[JSConfigurationKeys.INCREMENTAL_RESULTS_CONSUMER]?.apply {
val psiFile = (descriptor.source.containingFile as? PsiSourceFile)?.psiFile ?: return@apply
val file = VfsUtilCore.virtualToIoFile(psiFile.virtualFile)
diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
index 35d98c35268..3cfa71d1a67 100644
--- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
+++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java
@@ -526,7 +526,7 @@ public final class TranslationUtils {
}
@NotNull
- private static JsInvocation invokeSpecialFunction(
+ public static JsInvocation invokeSpecialFunction(
@NotNull TranslationContext context,
@NotNull SpecialFunction function, @NotNull JsExpression... arguments
) {