// WITH_RUNTIME // FULL_JDK import java.util.concurrent.CompletableFuture fun exception(v: String): CompletableFuture = CompletableFuture.supplyAsync { throw RuntimeException(v) } fun foobar(x: String, y: String) = x + y fun box(): String { var result = "" val future = async() { try { await(exception("OK")) } catch (e: Exception) { result = e.cause?.message!! } "56" } future.join() if (future.get() != "56") return "fail: ${future.get()}" if (result != "OK") return "fail notOk" val future2 = async() { await(exception("OK")) "fail" } try { future2.get() } catch (e: Exception) { if (e.cause!!.message != "OK") return "fail message: ${e.cause!!.message}" return "OK" } return "No exception" } fun async(coroutine c: FutureController.() -> Continuation): CompletableFuture { val controller = FutureController() c(controller).resume(Unit) return controller.future } class FutureController { val future = CompletableFuture() suspend fun await(f: CompletableFuture) = suspendWithCurrentContinuation { machine -> f.whenComplete { value, throwable -> if (throwable == null) machine.resume(value) else machine.resumeWithException(throwable) } Suspend } operator fun handleResult(value: T, c: Continuation) { future.complete(value) } operator fun handleException(t: Throwable, c: Continuation) { future.completeExceptionally(t) } }