From 258ee0db75be3b41ac7be8b5137130279521e8c8 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 30 Jan 2017 19:24:53 +0300 Subject: [PATCH] Introduce startCoroutineUninterceptedOrReturn coroutine intrinsic #KT-15716 Fixed --- .../intrinsicSemantics/startCoroutine.kt | 44 ++++++++++ .../startCoroutineUninterceptedOrReturn.kt | 55 +++++++++++++ ...outineUninterceptedOrReturnInterception.kt | 80 +++++++++++++++++++ .../intrinsicSemantics/startCoroutine.txt | 32 ++++++++ .../startCoroutineUninterceptedOrReturn.txt | 32 ++++++++ ...utineUninterceptedOrReturnInterception.txt | 53 ++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 27 +++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 27 +++++++ .../src/core/coroutinesIntrinsics.kt | 34 ++++++++ .../semantics/JsCodegenBoxTestGenerated.java | 33 ++++++++ .../experimental/intrinsics/IntrinsicsJvm.kt | 35 ++++++++ 11 files changed, 452 insertions(+) create mode 100644 compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt create mode 100644 compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt create mode 100644 compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt create mode 100644 compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutine.txt create mode 100644 compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.txt create mode 100644 compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.txt create mode 100644 js/js.libraries/src/core/coroutinesIntrinsics.kt create mode 100644 libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/IntrinsicsJvm.kt diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt new file mode 100644 index 00000000000..fdb722e8560 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt @@ -0,0 +1,44 @@ +// WITH_RUNTIME +// WITH_COROUTINES +import kotlin.coroutines.experimental.* +import kotlin.coroutines.experimental.intrinsics.* +import kotlin.test.assertEquals + +suspend fun suspendHere(): String = suspendCoroutineOrReturn { x -> + x.resume("OK") + COROUTINE_SUSPENDED +} + +suspend fun suspendWithException(): String = suspendCoroutineOrReturn { x -> + x.resumeWithException(RuntimeException("OK")) + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> String): String { + var fromSuspension: String? = null + + c.startCoroutine(object: Continuation { + override val context: CoroutineContext + get() = EmptyCoroutineContext + + override fun resumeWithException(exception: Throwable) { + fromSuspension = "Exception: " + exception.message!! + } + + override fun resume(value: String) { + fromSuspension = value + } + }) + + return fromSuspension as String +} + +fun box(): String { + if (builder { "OK" } != "OK") return "fail 4" + if (builder { suspendHere() } != "OK") return "fail 5" + + if (builder { throw RuntimeException("OK") } != "Exception: OK") return "fail 6" + if (builder { suspendWithException() } != "Exception: OK") return "fail 7" + + return "OK" +} diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt new file mode 100644 index 00000000000..7ccdef95424 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt @@ -0,0 +1,55 @@ +// WITH_RUNTIME +// WITH_COROUTINES +import kotlin.coroutines.experimental.* +import kotlin.coroutines.experimental.intrinsics.* +import kotlin.test.assertEquals + +suspend fun suspendHere(): String = suspendCoroutineOrReturn { x -> + x.resume("OK") + COROUTINE_SUSPENDED +} + +suspend fun suspendWithException(): String = suspendCoroutineOrReturn { x -> + x.resumeWithException(RuntimeException("OK")) + COROUTINE_SUSPENDED +} + +fun builder(shouldSuspend: Boolean, c: suspend () -> String): String { + var fromSuspension: String? = null + + val result = try { + c.startCoroutineUninterceptedOrReturn(object: Continuation { + override val context: CoroutineContext + get() = EmptyCoroutineContext + + override fun resumeWithException(exception: Throwable) { + fromSuspension = "Exception: " + exception.message!! + } + + override fun resume(value: String) { + fromSuspension = value + } + }) + } catch (e: Exception) { + "Exception: ${e.message}" + } + + if (shouldSuspend) { + if (result !== COROUTINE_SUSPENDED) throw RuntimeException("fail 1") + if (fromSuspension == null) throw RuntimeException("fail 2") + return fromSuspension!! + } + + if (result === COROUTINE_SUSPENDED) throw RuntimeException("fail 3") + return result as String +} + +fun box(): String { + if (builder(false) { "OK" } != "OK") return "fail 4" + if (builder(true) { suspendHere() } != "OK") return "fail 5" + + if (builder(false) { throw RuntimeException("OK") } != "Exception: OK") return "fail 6" + if (builder(true) { suspendWithException() } != "Exception: OK") return "fail 7" + + return "OK" +} diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt new file mode 100644 index 00000000000..2ce967a3781 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt @@ -0,0 +1,80 @@ +// WITH_RUNTIME +// WITH_COROUTINES +// IGNORE_BACKEND: JS +import kotlin.coroutines.experimental.* +import kotlin.coroutines.experimental.intrinsics.* +import kotlin.test.assertEquals + +suspend fun suspendHere(): String = suspendCoroutineOrReturn { x -> + x.resume("OK") + COROUTINE_SUSPENDED +} + +suspend fun suspendWithException(): String = suspendCoroutineOrReturn { x -> + x.resumeWithException(RuntimeException("OK")) + COROUTINE_SUSPENDED +} + +fun builder(shouldSuspend: Boolean, expectedCount: Int, c: suspend () -> String): String { + var fromSuspension: String? = null + var counter = 0 + + val result = try { + c.startCoroutineUninterceptedOrReturn(object: Continuation { + override val context: CoroutineContext + get() = ContinuationDispatcher { counter++ } + + override fun resumeWithException(exception: Throwable) { + fromSuspension = "Exception: " + exception.message!! + } + + override fun resume(value: String) { + fromSuspension = value + } + }) + } catch (e: Exception) { + "Exception: ${e.message}" + } + + if (counter != expectedCount) throw RuntimeException("fail 0") + + if (shouldSuspend) { + if (result !== COROUTINE_SUSPENDED) throw RuntimeException("fail 1") + if (fromSuspension == null) throw RuntimeException("fail 2") + return fromSuspension!! + } + + if (result === COROUTINE_SUSPENDED) throw RuntimeException("fail 3") + return result as String +} + +class ContinuationDispatcher(val dispatcher: () -> Unit) : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor { + override fun interceptContinuation(continuation: Continuation): Continuation = DispatchedContinuation(dispatcher, continuation) +} + +private class DispatchedContinuation( + val dispatcher: () -> Unit, + val continuation: Continuation +): Continuation { + override val context: CoroutineContext = continuation.context + + override fun resume(value: T) { + dispatcher() + continuation.resume(value) + } + + override fun resumeWithException(exception: Throwable) { + dispatcher() + continuation.resumeWithException(exception) + } +} + +fun box(): String { + if (builder(false, 0) { "OK" } != "OK") return "fail 4" + if (builder(true, 1) { suspendHere() } != "OK") return "fail 5" + + if (builder(false, 0) { throw RuntimeException("OK") } != "Exception: OK") return "fail 6" + if (builder(true, 1) { suspendWithException() } != "Exception: OK") return "fail 7" + + return "OK" +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutine.txt b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutine.txt new file mode 100644 index 00000000000..f80ca065572 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutine.txt @@ -0,0 +1,32 @@ +@kotlin.Metadata +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation +} + +@kotlin.Metadata +public class EmptyContinuation { + public final static field Companion: EmptyContinuation.Companion + private final @org.jetbrains.annotations.NotNull field context: kotlin.coroutines.experimental.CoroutineContext + inner class EmptyContinuation/Companion + public @synthetic.kotlin.jvm.GeneratedByJvmOverloads method (): void + public method (@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.CoroutineContext): void + public synthetic method (p0: kotlin.coroutines.experimental.CoroutineContext, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public @org.jetbrains.annotations.NotNull method getContext(): kotlin.coroutines.experimental.CoroutineContext + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + +@kotlin.Metadata +public final static class EmptyContinuation/Companion { + inner class EmptyContinuation/Companion + private method (): void +} + +@kotlin.Metadata +public final class StartCoroutineKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): java.lang.String + public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method suspendWithException(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.txt b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.txt new file mode 100644 index 00000000000..7c8ec769f3b --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.txt @@ -0,0 +1,32 @@ +@kotlin.Metadata +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation +} + +@kotlin.Metadata +public class EmptyContinuation { + public final static field Companion: EmptyContinuation.Companion + private final @org.jetbrains.annotations.NotNull field context: kotlin.coroutines.experimental.CoroutineContext + inner class EmptyContinuation/Companion + public @synthetic.kotlin.jvm.GeneratedByJvmOverloads method (): void + public method (@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.CoroutineContext): void + public synthetic method (p0: kotlin.coroutines.experimental.CoroutineContext, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public @org.jetbrains.annotations.NotNull method getContext(): kotlin.coroutines.experimental.CoroutineContext + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + +@kotlin.Metadata +public final static class EmptyContinuation/Companion { + inner class EmptyContinuation/Companion + private method (): void +} + +@kotlin.Metadata +public final class StartCoroutineUninterceptedOrReturnKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method builder(p0: boolean, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1): java.lang.String + public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method suspendWithException(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.txt b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.txt new file mode 100644 index 00000000000..27eba7ba9db --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.txt @@ -0,0 +1,53 @@ +@kotlin.Metadata +public final class ContinuationDispatcher { + private final @org.jetbrains.annotations.NotNull field dispatcher: kotlin.jvm.functions.Function0 + public method (@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): void + public final @org.jetbrains.annotations.NotNull method getDispatcher(): kotlin.jvm.functions.Function0 + public @org.jetbrains.annotations.NotNull method interceptContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation +} + +@kotlin.Metadata +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation +} + +@kotlin.Metadata +final class DispatchedContinuation { + private final @org.jetbrains.annotations.NotNull field context: kotlin.coroutines.experimental.CoroutineContext + private final @org.jetbrains.annotations.NotNull field continuation: kotlin.coroutines.experimental.Continuation + private final @org.jetbrains.annotations.NotNull field dispatcher: kotlin.jvm.functions.Function0 + public method (@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): void + public @org.jetbrains.annotations.NotNull method getContext(): kotlin.coroutines.experimental.CoroutineContext + public final @org.jetbrains.annotations.NotNull method getContinuation(): kotlin.coroutines.experimental.Continuation + public final @org.jetbrains.annotations.NotNull method getDispatcher(): kotlin.jvm.functions.Function0 + public method resume(p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + +@kotlin.Metadata +public class EmptyContinuation { + public final static field Companion: EmptyContinuation.Companion + private final @org.jetbrains.annotations.NotNull field context: kotlin.coroutines.experimental.CoroutineContext + inner class EmptyContinuation/Companion + public @synthetic.kotlin.jvm.GeneratedByJvmOverloads method (): void + public method (@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.CoroutineContext): void + public synthetic method (p0: kotlin.coroutines.experimental.CoroutineContext, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public @org.jetbrains.annotations.NotNull method getContext(): kotlin.coroutines.experimental.CoroutineContext + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + +@kotlin.Metadata +public final static class EmptyContinuation/Companion { + inner class EmptyContinuation/Companion + private method (): void +} + +@kotlin.Metadata +public final class StartCoroutineUninterceptedOrReturnInterceptionKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method builder(p0: boolean, p1: int, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function1): java.lang.String + public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method suspendWithException(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object +} 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 73b3b7d0dd1..ca87c6fe82f 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 @@ -5156,6 +5156,33 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IntrinsicSemantics extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInIntrinsicSemantics() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/intrinsicSemantics"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("startCoroutine.kt") + public void testStartCoroutine() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturn.kt") + public void testStartCoroutineUninterceptedOrReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturnInterception.kt") + public void testStartCoroutineUninterceptedOrReturnInterception() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/multiModule") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3d307a81032..29796c370a5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5156,6 +5156,33 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IntrinsicSemantics extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInIntrinsicSemantics() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/intrinsicSemantics"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("startCoroutine.kt") + public void testStartCoroutine() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturn.kt") + public void testStartCoroutineUninterceptedOrReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturnInterception.kt") + public void testStartCoroutineUninterceptedOrReturnInterception() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/multiModule") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.libraries/src/core/coroutinesIntrinsics.kt b/js/js.libraries/src/core/coroutinesIntrinsics.kt new file mode 100644 index 00000000000..9d35af014e0 --- /dev/null +++ b/js/js.libraries/src/core/coroutinesIntrinsics.kt @@ -0,0 +1,34 @@ +/* + * 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 kotlin.coroutines.experimental.intrinsics + +import kotlin.coroutines.experimental.Continuation + +@SinceKotlin("1.1") +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( + completion: Continuation +): Any? = this.asDynamic()(completion, false) + +@SinceKotlin("1.1") +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + completion: Continuation +): Any? = this.asDynamic()(receiver, completion, false) 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 ad3e73e6fbf..ed429420e09 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 @@ -5847,6 +5847,39 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IntrinsicSemantics extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInIntrinsicSemantics() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/intrinsicSemantics"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("startCoroutine.kt") + public void testStartCoroutine() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutine.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturn.kt") + public void testStartCoroutineUninterceptedOrReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt"); + doTest(fileName); + } + + @TestMetadata("startCoroutineUninterceptedOrReturnInterception.kt") + public void testStartCoroutineUninterceptedOrReturnInterception() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.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("compiler/testData/codegen/box/coroutines/multiModule") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/IntrinsicsJvm.kt b/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/IntrinsicsJvm.kt new file mode 100644 index 00000000000..04385c149fc --- /dev/null +++ b/libraries/stdlib/src/kotlin/coroutines/experimental/intrinsics/IntrinsicsJvm.kt @@ -0,0 +1,35 @@ +/* + * 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. + */ + +@file:kotlin.jvm.JvmName("IntrinsicsJvmKt") +@file:kotlin.jvm.JvmVersion +package kotlin.coroutines.experimental.intrinsics +import kotlin.coroutines.experimental.* + +@SinceKotlin("1.1") +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( + completion: Continuation +): Any? = (this as Function1, Any?>).invoke(completion) + +@SinceKotlin("1.1") +@Suppress("UNCHECKED_CAST") +@kotlin.internal.InlineOnly +public inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + completion: Continuation +): Any? = (this as Function2, Any?>).invoke(receiver, completion)