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)
|
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 outputPrefixFile = getOutputPrefixFile(filePath)
|
||||||
val outputPostfixFile = getOutputPostfixFile(filePath)
|
val outputPostfixFile = getOutputPostfixFile(filePath)
|
||||||
|
|
||||||
@@ -124,7 +126,7 @@ abstract class BasicBoxTest(
|
|||||||
generateJavaScriptFile(
|
generateJavaScriptFile(
|
||||||
file.parent, module, outputFileName, dependencies, friends, modules.size > 1,
|
file.parent, module, outputFileName, dependencies, friends, modules.size > 1,
|
||||||
!SKIP_SOURCEMAP_REMAPPING.matcher(fileContent).find(),
|
!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
|
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 EXPECTED_REACHABLE_NODES = Pattern.compile("^// *$EXPECTED_REACHABLE_NODES_DIRECTIVE: *([0-9]+) *$", Pattern.MULTILINE)
|
||||||
private val RECOMPILE_PATTERN = Pattern.compile("^// *RECOMPILE *$", 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 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"
|
val TEST_MODULE = "JS_TESTS"
|
||||||
private val DEFAULT_MODULE = "main"
|
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")
|
@TestMetadata("js/js.translator/testData/box/multiFile")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@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")
|
@TestMetadata("js/js.translator/testData/box/multiFile")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
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.declaration.FileDeclarationVisitor;
|
||||||
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor;
|
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor;
|
||||||
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator;
|
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.test.JSTestGenerator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.*;
|
import org.jetbrains.kotlin.js.translate.utils.*;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.mutator.AssignToExpressionMutator;
|
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.KtDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.constants.*;
|
import org.jetbrains.kotlin.resolve.constants.*;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
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.serialization.js.ast.JsAstDeserializer;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
@@ -468,8 +474,24 @@ public final class Translation {
|
|||||||
if (functionDescriptor == null) {
|
if (functionDescriptor == null) {
|
||||||
return 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());
|
context.addTopLevelStatement(call.makeStmt());
|
||||||
return staticContext.getFragment();
|
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