JS: support [suspend] fun main([args: Array<String>]) (KT-26628, KT-26572 fixed)
This commit is contained in:
committed by
Denis Zharkov
parent
7e9704e50d
commit
ead9b31e03
@@ -102,6 +102,8 @@ abstract class BasicBoxTest(
|
||||
fileContent = fileContent.replace("COROUTINES_PACKAGE", coroutinesPackage)
|
||||
}
|
||||
|
||||
val actualMainCallParameters = if (CALL_MAIN_PATTERN.matcher(fileContent).find()) MainCallParameters.mainWithArguments(listOf("testArg")) else mainCallParameters
|
||||
|
||||
val outputPrefixFile = getOutputPrefixFile(filePath)
|
||||
val outputPostfixFile = getOutputPostfixFile(filePath)
|
||||
|
||||
@@ -124,7 +126,7 @@ abstract class BasicBoxTest(
|
||||
generateJavaScriptFile(
|
||||
file.parent, module, outputFileName, dependencies, friends, modules.size > 1,
|
||||
!SKIP_SOURCEMAP_REMAPPING.matcher(fileContent).find(),
|
||||
outputPrefixFile, outputPostfixFile, mainCallParameters, testPackage, testFunction
|
||||
outputPrefixFile, outputPostfixFile, actualMainCallParameters, testPackage, testFunction
|
||||
)
|
||||
|
||||
if (!module.name.endsWith(OLD_MODULE_SUFFIX)) Pair(outputFileName, module) else null
|
||||
@@ -771,6 +773,7 @@ abstract class BasicBoxTest(
|
||||
private val EXPECTED_REACHABLE_NODES = Pattern.compile("^// *$EXPECTED_REACHABLE_NODES_DIRECTIVE: *([0-9]+) *$", Pattern.MULTILINE)
|
||||
private val RECOMPILE_PATTERN = Pattern.compile("^// *RECOMPILE *$", Pattern.MULTILINE)
|
||||
private val SOURCE_MAP_SOURCE_EMBEDDING = Regex("^// *SOURCE_MAP_EMBED_SOURCES: ([A-Z]+)*\$", RegexOption.MULTILINE)
|
||||
private val CALL_MAIN_PATTERN = Pattern.compile("^// *CALL_MAIN *$", Pattern.MULTILINE)
|
||||
|
||||
val TEST_MODULE = "JS_TESTS"
|
||||
private val DEFAULT_MODULE = "main"
|
||||
|
||||
+38
@@ -5493,6 +5493,44 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/main")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Main extends AbstractBoxJsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInMain() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/main"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("noArgs.kt")
|
||||
public void testNoArgs() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/noArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMain.kt")
|
||||
public void testSuspendMain() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMain.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMainNoArgs.kt")
|
||||
public void testSuspendMainNoArgs() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMainNoArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMainThrows.kt")
|
||||
public void testSuspendMainThrows() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMainThrows.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/multiFile")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+38
@@ -5493,6 +5493,44 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/main")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Main extends AbstractIrBoxJsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInMain() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/main"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("noArgs.kt")
|
||||
public void testNoArgs() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/noArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMain.kt")
|
||||
public void testSuspendMain() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMain.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMainNoArgs.kt")
|
||||
public void testSuspendMainNoArgs() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMainNoArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendMainThrows.kt")
|
||||
public void testSuspendMainThrows() throws Exception {
|
||||
runTest("js/js.translator/testData/box/main/suspendMainThrows.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/multiFile")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
||||
@@ -41,17 +42,22 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.FileDeclarationVisitor;
|
||||
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor;
|
||||
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.test.JSTestGenerator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.*;
|
||||
import org.jetbrains.kotlin.js.translate.utils.mutator.AssignToExpressionMutator;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstDeserializer;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
@@ -468,8 +474,24 @@ public final class Translation {
|
||||
if (functionDescriptor == null) {
|
||||
return null;
|
||||
}
|
||||
JsArrayLiteral argument = new JsArrayLiteral(toStringLiteralList(arguments));
|
||||
JsExpression call = CallTranslator.INSTANCE.buildCall(context, functionDescriptor, Collections.singletonList(argument), null);
|
||||
|
||||
int parameterCount = functionDescriptor.getValueParameters().size();
|
||||
assert parameterCount <= 1;
|
||||
|
||||
List<JsExpression> args = new ArrayList<>();
|
||||
if (parameterCount != 0) {
|
||||
args.add(new JsArrayLiteral(toStringLiteralList(arguments)));
|
||||
}
|
||||
|
||||
if (functionDescriptor.isSuspend()) {
|
||||
MemberScope scope = moduleDescriptor.getPackage(new FqNameUnsafe("kotlin.coroutines.js.internal").toSafe()).getMemberScope();
|
||||
PropertyDescriptor emptyContinuation = DescriptorUtils.getPropertyByName(scope, Name.identifier("EmptyContinuation"));
|
||||
|
||||
args.add(ReferenceTranslator.translateAsValueReference(emptyContinuation, context));
|
||||
args.add(new JsBooleanLiteral(false));
|
||||
}
|
||||
|
||||
JsExpression call = CallTranslator.INSTANCE.buildCall(context, functionDescriptor, args, null);
|
||||
context.addTopLevelStatement(call.makeStmt());
|
||||
return staticContext.getFragment();
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1281
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// CALL_MAIN
|
||||
|
||||
var ok: String = "fail"
|
||||
|
||||
fun main() {
|
||||
ok = "OK"
|
||||
}
|
||||
|
||||
fun box() = ok
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1281
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// CALL_MAIN
|
||||
|
||||
var ok: String = "fail"
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
assertEquals(1, args.size)
|
||||
assertEquals("testArg", args[0])
|
||||
|
||||
ok = "OK"
|
||||
}
|
||||
|
||||
fun box() = ok
|
||||
@@ -0,0 +1,28 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1296
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// CALL_MAIN
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var ok: String = "fail"
|
||||
|
||||
var callback: () -> Unit = {}
|
||||
|
||||
suspend fun main(args: Array<String>) {
|
||||
assertEquals(1, args.size)
|
||||
assertEquals("testArg", args[0])
|
||||
|
||||
suspendCoroutine<Unit> { cont ->
|
||||
callback = {
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
ok = "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("fail", ok)
|
||||
callback()
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1296
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// CALL_MAIN
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var ok: String = "fail"
|
||||
|
||||
var callback: () -> Unit = {}
|
||||
|
||||
suspend fun main() {
|
||||
suspendCoroutine<Unit> { cont ->
|
||||
callback = {
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
ok = "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("fail", ok)
|
||||
callback()
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1299
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// CALL_MAIN
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
var callback: () -> Unit = {}
|
||||
|
||||
val exception = Exception()
|
||||
|
||||
suspend fun main() {
|
||||
|
||||
suspendCoroutine<Unit> { cont ->
|
||||
callback = {
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
throw exception
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
callback()
|
||||
} catch (e: Exception) {
|
||||
assertTrue(e === exception)
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.coroutines.js.internal
|
||||
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
@PublishedApi
|
||||
internal val EmptyContinuation = Continuation<Any?>(EmptyCoroutineContext) { result ->
|
||||
result.getOrThrow()
|
||||
}
|
||||
Reference in New Issue
Block a user