JS: improve how base class for coroutines is implemented: 1) use JVM-like style of passing dispatcher 2) instead of flag, use additional "facade" continuation when dealing with dispatchers
This commit is contained in:
@@ -29,7 +29,7 @@ public fun <R, T> (suspend R.() -> T).createCoroutine(
|
||||
receiver: R,
|
||||
completion: Continuation<T>,
|
||||
dispatcher: ContinuationDispatcher? = null
|
||||
): Continuation<Unit> = this.asDynamic().call(receiver, withDispatcher(completion, dispatcher))
|
||||
): Continuation<Unit> = this.asDynamic().call(receiver, withDispatcher(completion, dispatcher)).facade
|
||||
|
||||
/**
|
||||
* Starts coroutine with receiver type [R] and result type [T].
|
||||
@@ -57,7 +57,7 @@ public fun <R, T> (suspend R.() -> T).startCoroutine(
|
||||
public fun <T> (suspend () -> T).createCoroutine(
|
||||
completion: Continuation<T>,
|
||||
dispatcher: ContinuationDispatcher? = null
|
||||
): Continuation<Unit> = this.asDynamic()(withDispatcher(completion, dispatcher))
|
||||
): Continuation<Unit> = this.asDynamic()(withDispatcher(completion, dispatcher)).facade
|
||||
|
||||
/**
|
||||
* Starts coroutine without receiver and with result type [T].
|
||||
@@ -75,13 +75,19 @@ public fun <T> (suspend () -> T).startCoroutine(
|
||||
|
||||
// ------- internal stuff -------
|
||||
|
||||
private fun <T> withDispatcher(completion: Continuation<T>, dispatcher: ContinuationDispatcher?): Continuation<T> {
|
||||
val finalContinuationDispatcher = dispatcher ?: object : ContinuationDispatcher {
|
||||
override fun <T> dispatchResume(value: T, continuation: Continuation<T>) = false
|
||||
internal interface DispatchedContinuation {
|
||||
val dispatcher: ContinuationDispatcher?
|
||||
}
|
||||
|
||||
override fun dispatchResumeWithException(exception: Throwable, continuation: Continuation<*>) = false
|
||||
private fun <T> withDispatcher(completion: Continuation<T>, dispatcher: ContinuationDispatcher?): Continuation<T> {
|
||||
return if (dispatcher == null) {
|
||||
completion
|
||||
}
|
||||
else {
|
||||
object : Continuation<T> by completion, DispatchedContinuation {
|
||||
override val dispatcher = dispatcher
|
||||
}
|
||||
}
|
||||
return object : Continuation<T> by completion, ContinuationDispatcher by finalContinuationDispatcher {}
|
||||
}
|
||||
|
||||
@JsName("CoroutineImpl")
|
||||
@@ -91,18 +97,19 @@ internal abstract class CoroutineImpl(private val resultContinuation: Continuati
|
||||
protected var result: Any? = null
|
||||
protected var exception: Throwable? = null
|
||||
protected var finallyPath: Array<Int>? = null
|
||||
private val continuationDispatcher = resultContinuation as? ContinuationDispatcher
|
||||
private val continuationDispatcher = (resultContinuation as? DispatchedContinuation)?.dispatcher
|
||||
val facade: Continuation<Any?>
|
||||
|
||||
init {
|
||||
facade = if (continuationDispatcher != null) {
|
||||
ContinuationFacade(this, continuationDispatcher)
|
||||
}
|
||||
else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
override fun resume(data: Any?) {
|
||||
if (continuationDispatcher != null && (state and INTERCEPTING) == 0) {
|
||||
state = state or INTERCEPTING
|
||||
if (continuationDispatcher.dispatchResume(data, this)) {
|
||||
state = state and INTERCEPTING.inv()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
state = state and INTERCEPTING.inv()
|
||||
this.result = data
|
||||
try {
|
||||
val result = doResume()
|
||||
@@ -116,14 +123,6 @@ internal abstract class CoroutineImpl(private val resultContinuation: Continuati
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
if (continuationDispatcher != null && (state and INTERCEPTING) == 0) {
|
||||
state = state or INTERCEPTING
|
||||
if (continuationDispatcher.dispatchResumeWithException(exception, this)) {
|
||||
state = state and INTERCEPTING.inv()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
state = exceptionState
|
||||
this.exception = exception
|
||||
try {
|
||||
@@ -140,4 +139,16 @@ internal abstract class CoroutineImpl(private val resultContinuation: Continuati
|
||||
protected abstract fun doResume(): Any?
|
||||
}
|
||||
|
||||
private const val INTERCEPTING = 1 shl 31
|
||||
private class ContinuationFacade(val innerContinuation: Continuation<Any?>, val dispatcher: ContinuationDispatcher) : Continuation<Any?> {
|
||||
override fun resume(value: Any?) {
|
||||
if (!dispatcher.dispatchResume(value, innerContinuation)) {
|
||||
innerContinuation.resume(value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
if (!dispatcher.dispatchResumeWithException(exception, innerContinuation)) {
|
||||
innerContinuation.resumeWithException(exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -21,10 +21,7 @@ import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
@@ -156,7 +153,8 @@ class CallArgumentTranslator private constructor(
|
||||
|
||||
val callableDescriptor = resolvedCall.resultingDescriptor
|
||||
if (callableDescriptor is FunctionDescriptor && callableDescriptor.isSuspend) {
|
||||
result.add(TranslationUtils.translateContinuationArgument(context(), resolvedCall))
|
||||
val facadeName = context().getNameForDescriptor(TranslationUtils.getCoroutineProperty(context(), "facade"))
|
||||
result.add(JsAstUtils.pureFqn(facadeName, TranslationUtils.translateContinuationArgument(context(), resolvedCall)))
|
||||
}
|
||||
|
||||
removeLastUndefinedArguments(result)
|
||||
|
||||
Reference in New Issue
Block a user