[JS IR BE] Fix runtime for Release coroutines
This commit is contained in:
@@ -15,16 +15,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import java.io.File
|
||||
|
||||
private val runtimeSources = listOfKtFilesFrom(
|
||||
// TODO: share more coroutine code between JS BEs
|
||||
// TODO: don't generate code for external declarations, until that:
|
||||
// it's important now than *H.kt files at the start since we generate code for them
|
||||
// and actual versions just will override them later.
|
||||
"libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/CoroutinesExperimentalH.kt",
|
||||
"libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/CoroutinesIntrinsicsExperimentalH.kt",
|
||||
"libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/SequenceBuilder.kt",
|
||||
"libraries/stdlib/coroutines-experimental/src/kotlin/coroutines/experimental/Coroutines.kt",
|
||||
|
||||
private val runtimeSourcesCommon = listOfKtFilesFrom(
|
||||
"core/builtins/src/kotlin",
|
||||
"libraries/stdlib/common/src",
|
||||
"libraries/stdlib/src/kotlin/",
|
||||
@@ -80,9 +71,27 @@ private val runtimeSources = listOfKtFilesFrom(
|
||||
"libraries/stdlib/js/irRuntime/rangeExtensions.kt"
|
||||
)
|
||||
|
||||
|
||||
private val coroutine12Files = listOfKtFilesFrom(
|
||||
"libraries/stdlib/js/irRuntime/coroutines_12"
|
||||
)
|
||||
|
||||
private val coroutine13Files = listOfKtFilesFrom(
|
||||
"libraries/stdlib/coroutines/common",
|
||||
"libraries/stdlib/coroutines/js/src/kotlin/coroutines/SafeContinuationJs.kt",
|
||||
"libraries/stdlib/coroutines/src",
|
||||
// TODO: merge coroutines_13 with JS BE coroutines
|
||||
"libraries/stdlib/js/irRuntime/coroutines_13"
|
||||
)
|
||||
|
||||
private var runtimeResult: Result? = null
|
||||
private val runtimeFile = File("js/js.translator/testData/out/irBox/testRuntime.js")
|
||||
|
||||
private val runtimeSources_12 = (runtimeSourcesCommon - coroutine13Files + coroutine12Files).distinct()
|
||||
private val runtimeSources_13 = (runtimeSourcesCommon - coroutine12Files + coroutine13Files).distinct()
|
||||
|
||||
private val runtimeSources = runtimeSources_13
|
||||
|
||||
abstract class BasicIrBoxTest(
|
||||
pathToTestDir: String,
|
||||
testGroupOutputDirPrefix: String,
|
||||
@@ -128,11 +137,11 @@ abstract class BasicIrBoxTest(
|
||||
LanguageFeature.MultiPlatformProjects to LanguageFeature.State.ENABLED
|
||||
),
|
||||
analysisFlags = mapOf(
|
||||
AnalysisFlag.useExperimental to listOf("kotlin.contracts.ExperimentalContracts", "kotlin.Experimental")
|
||||
AnalysisFlag.useExperimental to listOf("kotlin.contracts.ExperimentalContracts", "kotlin.Experimental"),
|
||||
AnalysisFlag.allowResultReturnType to true
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if (runtimeResult == null) {
|
||||
runtimeResult = compile(config.project, runtimeSources.map(::createPsiFile), runtimeConfiguration)
|
||||
runtimeFile.write(runtimeResult!!.generatedCode)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.js
|
||||
|
||||
import kotlin.js.coroutineAliases.*
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T> getContinuation(): ContinuationAlias<T> { throw Exception("Implemented as intrinsic") }
|
||||
// Do we really need this intrinsic in JS?
|
||||
|
||||
@PublishedApi
|
||||
internal suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T {
|
||||
throw Exception("Implemented as intrinsic")
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T> interceptContinuationIfNeeded(
|
||||
context: CoroutineContextAlias,
|
||||
continuation: ContinuationAlias<T>
|
||||
) = context[ContinuationInterceptorAlias]?.interceptContinuation(continuation) ?: continuation
|
||||
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
@PublishedApi
|
||||
internal suspend fun getCoroutineContext(): CoroutineContextAlias = getContinuation<Any?>().context
|
||||
|
||||
// TODO: remove `JS` suffix oncec `NameGenerator` is implemented
|
||||
@PublishedApi
|
||||
internal suspend fun <T> suspendCoroutineUninterceptedOrReturnJS(block: (ContinuationAlias<T>) -> Any?): T =
|
||||
returnIfSuspended<T>(block(getContinuation<T>()))
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
package kotlin.js.coroutineAliases
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
|
||||
typealias ContinuationAlias<T> = Continuation<T>
|
||||
typealias CoroutineContextAlias = CoroutineContext
|
||||
typealias ContinuationInterceptorAlias = ContinuationInterceptor
|
||||
+11
-11
@@ -7,11 +7,9 @@ package kotlin.coroutines.experimental.intrinsics
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.internal.InlineOnly
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public suspend inline fun <T> suspendCoroutineOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||
suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) }
|
||||
@PublishedApi
|
||||
internal fun <T> normalizeContinuation(continuation: Continuation<T>): Continuation<T> =
|
||||
(continuation as? CoroutineImpl)?.facade ?: continuation
|
||||
|
||||
/**
|
||||
* Obtains the current continuation instance inside suspend functions and either suspends
|
||||
@@ -19,9 +17,16 @@ public suspend inline fun <T> suspendCoroutineOrReturn(crossinline block: (Conti
|
||||
*
|
||||
* Unlike [suspendCoroutineOrReturn] it does not intercept continuation.
|
||||
*/
|
||||
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.internal.InlineOnly
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public suspend inline fun <T> suspendCoroutineOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||
suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) }
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public suspend fun <T> suspendCoroutineUninterceptedOrReturn(block: (Continuation<T>) -> Any?): T =
|
||||
returnIfSuspended<T>(block(getContinuation<T>()))
|
||||
throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic")
|
||||
|
||||
/**
|
||||
* Intercept continuation with [ContinuationInterceptor].
|
||||
@@ -30,14 +35,9 @@ public suspend fun <T> suspendCoroutineUninterceptedOrReturn(block: (Continuatio
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> Continuation<T>.intercepted() = normalizeContinuation<T>(this)
|
||||
|
||||
/**
|
||||
* This value is used as a return value of [suspendCoroutineOrReturn] `block` argument to state that
|
||||
* the execution was suspended and will not return any result immediately.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public val COROUTINE_SUSPENDED: Any = Any()
|
||||
|
||||
|
||||
@SinceKotlin("1.1")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
+8
@@ -291,6 +291,14 @@ private val RESUMED: Any? = Any()
|
||||
|
||||
private class Fail(val exception: Throwable)
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
@Suppress("WRONG_MODIFIER_TARGET")
|
||||
@kotlin.internal.InlineOnly
|
||||
public suspend inline val coroutineContext: CoroutineContext
|
||||
get() {
|
||||
throw NotImplementedError("Implemented as intrinsic")
|
||||
}
|
||||
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun processBareContinuationResume(completion: Continuation<*>, block: () -> Any?) {
|
||||
try {
|
||||
+3
-28
@@ -3,36 +3,11 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.js
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
internal fun <T> getContinuation(): Continuation<T> { throw Exception("Implemented as intrinsic") }
|
||||
// Do we really need this intrinsic in JS?
|
||||
internal suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T {
|
||||
throw Exception("Implemented as intrinsic")
|
||||
}
|
||||
|
||||
fun <T> normalizeContinuation(continuation: Continuation<T>): Continuation<T> =
|
||||
(continuation as? CoroutineImpl)?.facade ?: continuation
|
||||
|
||||
internal fun <T> interceptContinuationIfNeeded(
|
||||
context: CoroutineContext,
|
||||
continuation: Continuation<T>
|
||||
) = context[ContinuationInterceptor]?.interceptContinuation(continuation) ?: continuation
|
||||
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
@Suppress("WRONG_MODIFIER_TARGET")
|
||||
public suspend val coroutineContext: CoroutineContext
|
||||
get() {
|
||||
throw Exception("Implemented as intrinsic")
|
||||
}
|
||||
|
||||
package kotlin.coroutines.experimental
|
||||
|
||||
internal abstract class CoroutineImpl(private val completion: Continuation<Any?>) : Continuation<Any?> {
|
||||
protected var exceptionState = 0
|
||||
protected var label: Int = 0
|
||||
protected var state: Int = 0
|
||||
|
||||
protected var exception: dynamic = null
|
||||
protected var result: dynamic = null
|
||||
@@ -51,7 +26,7 @@ internal abstract class CoroutineImpl(private val completion: Continuation<Any?>
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
// TODO: once we have arrays working refact it with exception table
|
||||
this.label = exceptionState
|
||||
this.state = exceptionState
|
||||
this.exception = exception
|
||||
doResumeWrapper()
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
@JsName("CoroutineImpl")
|
||||
internal abstract class CoroutineImpl(private val resultContinuation: Continuation<Any?>?) : Continuation<Any?> {
|
||||
protected var state = 0
|
||||
protected var exceptionState = 0
|
||||
protected var result: dynamic = null
|
||||
protected var exception: dynamic = null
|
||||
protected var finallyPath: Array<Int>? = null
|
||||
|
||||
public override val context: CoroutineContext get() = resultContinuation!!.context
|
||||
|
||||
private var intercepted_: Continuation<Any?>? = null
|
||||
|
||||
public fun intercepted(): Continuation<Any?> =
|
||||
intercepted_
|
||||
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
|
||||
.also { intercepted_ = it }
|
||||
|
||||
override fun resumeWith(result: Result<Any?>) {
|
||||
var current = this
|
||||
var currentResult: Any? = result.getOrNull()
|
||||
var currentException: Throwable? = result.exceptionOrNull()
|
||||
|
||||
// This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
|
||||
while (true) {
|
||||
with(current) {
|
||||
// Set result and exception fields in the current continuation
|
||||
if (currentException == null) {
|
||||
this.result = currentResult
|
||||
} else {
|
||||
state = exceptionState
|
||||
exception = currentException
|
||||
}
|
||||
|
||||
try {
|
||||
val outcome = doResume()
|
||||
if (outcome === COROUTINE_SUSPENDED) return
|
||||
currentResult = outcome
|
||||
currentException = null
|
||||
} catch (exception: dynamic) { // Catch all exceptions
|
||||
currentResult = null
|
||||
currentException = exception.unsafeCast<Throwable>()
|
||||
}
|
||||
|
||||
releaseIntercepted() // this state machine instance is terminating
|
||||
|
||||
val completion = resultContinuation!!
|
||||
|
||||
if (completion is CoroutineImpl) {
|
||||
// unrolling recursion via loop
|
||||
current = completion
|
||||
} else {
|
||||
// top-level completion reached -- invoke and return
|
||||
if (currentException != null) {
|
||||
completion.resumeWithException(currentException!!)
|
||||
} else {
|
||||
completion.resume(currentResult)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun releaseIntercepted() {
|
||||
val intercepted = intercepted_
|
||||
if (intercepted != null && intercepted !== this) {
|
||||
context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted)
|
||||
}
|
||||
this.intercepted_ = CompletedContinuation // just in case
|
||||
}
|
||||
|
||||
protected abstract fun doResume(): Any?
|
||||
|
||||
public open fun create(completion: Continuation<*>): Continuation<Unit> {
|
||||
throw UnsupportedOperationException("create(Continuation) has not been overridden")
|
||||
}
|
||||
|
||||
public open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
|
||||
throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden")
|
||||
}
|
||||
}
|
||||
|
||||
internal object CompletedContinuation : Continuation<Any?> {
|
||||
override val context: CoroutineContext
|
||||
get() = error("This continuation is already complete")
|
||||
|
||||
override fun resumeWith(result: Result<Any?>) {
|
||||
error("This continuation is already complete")
|
||||
}
|
||||
|
||||
override fun toString(): String = "This continuation is already complete"
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "UNCHECKED_CAST")
|
||||
|
||||
package kotlin.coroutines.intrinsics
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.internal.InlineOnly
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might
|
||||
* be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation
|
||||
* context is established.
|
||||
*
|
||||
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any? {
|
||||
val a = this.asDynamic()
|
||||
return if (jsTypeOf(a) == "function") a(completion, false)
|
||||
else a.invoke(completion)
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might
|
||||
* be present in the completion's [CoroutineContext]. It is invoker's responsibility to ensure that the proper invocation
|
||||
* context is established.
|
||||
*
|
||||
* This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@InlineOnly
|
||||
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any? {
|
||||
val a = this.asDynamic()
|
||||
return if(jsTypeOf(a) == "function") a(receiver, completion, false)
|
||||
else a.invoke_P1(receiver, completion)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates unintercepted coroutine without receiver and with result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* This function returns unintercepted continuation.
|
||||
* Invocation of `resume(Unit)` starts coroutine directly in the invoker's thread without going through the
|
||||
* [ContinuationInterceptor] that might be present in the completion's [CoroutineContext].
|
||||
* It is invoker's responsibility to ensure that the proper invocation context is established.
|
||||
* [Continuation.intercepted] can be used to acquire the intercepted continuation.
|
||||
*
|
||||
* Repeated invocation of any resume function on the resulting continuation corrupts the
|
||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
// Kotlin/JS suspend lambdas have an extra parameter `suspended`
|
||||
if (this.asDynamic().length == 2) {
|
||||
// When `suspended` is true the continuation is created, but not executed
|
||||
this.asDynamic()(completion, true)
|
||||
} else {
|
||||
createCoroutineFromSuspendFunction(completion) {
|
||||
val a = this.asDynamic()
|
||||
if (jsTypeOf(a) == "function") {
|
||||
a(completion)
|
||||
} else {
|
||||
a.invoke(completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates unintercepted coroutine with receiver type [R] and result type [T].
|
||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
||||
*
|
||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
*
|
||||
* This function returns unintercepted continuation.
|
||||
* Invocation of `resume(Unit)` starts coroutine directly in the invoker's thread without going through the
|
||||
* [ContinuationInterceptor] that might be present in the completion's [CoroutineContext].
|
||||
* It is invoker's responsibility to ensure that the proper invocation context is established.
|
||||
* [Continuation.intercepted] can be used to acquire the intercepted continuation.
|
||||
*
|
||||
* Repeated invocation of any resume function on the resulting continuation corrupts the
|
||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
// Kotlin/JS suspend lambdas have an extra parameter `suspended`
|
||||
if (this.asDynamic().length == 3) {
|
||||
// When `suspended` is true the continuation is created, but not executed
|
||||
this.asDynamic()(receiver, completion, true)
|
||||
} else {
|
||||
createCoroutineFromSuspendFunction(completion) {
|
||||
val a = this.asDynamic()
|
||||
if (jsTypeOf(a) == "function") {
|
||||
a(receiver, completion)
|
||||
} else {
|
||||
a.invoke_P1(receiver, completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts this continuation with [ContinuationInterceptor].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
|
||||
(this as? CoroutineImpl)?.intercepted() ?: this
|
||||
|
||||
|
||||
private inline fun <T> createCoroutineFromSuspendFunction(
|
||||
completion: Continuation<T>,
|
||||
crossinline block: () -> Any?
|
||||
): Continuation<Unit> {
|
||||
return object : CoroutineImpl(completion as Continuation<Any?>) {
|
||||
override fun doResume(): Any? {
|
||||
if (exception != null) throw exception
|
||||
return block()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
package kotlin.js.coroutineAliases
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
|
||||
typealias ContinuationAlias<T> = Continuation<T>
|
||||
typealias CoroutineContextAlias = CoroutineContext
|
||||
typealias ContinuationInterceptorAlias = ContinuationInterceptor
|
||||
@@ -97,3 +97,5 @@ fun THROW_CCE() {
|
||||
fun THROW_NPE() {
|
||||
throw NullPointerException()
|
||||
}
|
||||
|
||||
fun error(s: String): Nothing = throw IllegalStateException(s, null)
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.coroutines.experimental.SequenceBuilder
|
||||
|
||||
// TODO: Ignore FunctionN interfaces
|
||||
|
||||
public interface Function0<out R> : Function<R> {
|
||||
@@ -26,15 +24,3 @@ public interface Function3<in P1, in P2, in P3, out R> : Function<R> {
|
||||
}
|
||||
|
||||
public inline fun <reified T> arrayOfNulls(size: Int): Array<T?> = js("[]") // FIXME: Implement
|
||||
|
||||
internal inline fun <T> buildSequence(noinline builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T> =
|
||||
kotlin.coroutines.experimental.buildSequence(builderAction)
|
||||
|
||||
internal inline fun <T> buildIterator(noinline builderAction: suspend SequenceBuilder<T>.() -> Unit): Iterator<T> =
|
||||
kotlin.coroutines.experimental.buildIterator(builderAction)
|
||||
|
||||
internal inline fun <T> sequence(noinline builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T> =
|
||||
kotlin.coroutines.experimental.buildSequence(builderAction)
|
||||
|
||||
internal inline fun <T> iterator(noinline builderAction: suspend SequenceBuilder<T>.() -> Unit): Iterator<T> =
|
||||
kotlin.coroutines.experimental.buildIterator(builderAction)
|
||||
|
||||
Reference in New Issue
Block a user