Skip to content

Commit

Permalink
[K/JS] Fix coroutines on ES2015 generators when there is not a Genera…
Browse files Browse the repository at this point in the history
…torCoroutine was provided as a continuation ^KTOR-6882 Fixed
  • Loading branch information
JSMonk authored and qodana-bot committed Aug 8, 2024
1 parent ca9fb23 commit ce5d599
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,16 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
val backingField = context.getNameForField(intrinsics.void.owner.backingField!!)
JsNameRef(backingField)
}

add(intrinsics.suspendOrReturnFunctionSymbol) { call, context ->
val (generatorCall, continuation) = translateCallArguments(call, context)
val jsInvokeFunName = context.getNameForStaticFunction(call.symbol.owner)
val VOID = context.getNameForField(intrinsics.void.owner.backingField!!)
val generatorBindCall = (generatorCall as JsInvocation).let {
JsInvocation(JsNameRef(Namer.BIND_FUNCTION, it.qualifier), listOf(JsNameRef(VOID)) + it.arguments.dropLast(1))
}
JsInvocation(JsNameRef(jsInvokeFunName), generatorBindCall, continuation)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,18 @@ internal fun <R, T, P> (suspend R.(P) -> T).createCoroutineUninterceptedGenerato
}


internal fun suspendOrReturn(value: Any?, continuation: Continuation<Any?>): Any? {
if (!isGeneratorSuspendStep(value)) return value
internal fun suspendOrReturn(generator: (continuation: Continuation<Any?>) -> dynamic, continuation: Continuation<Any?>): Any? {
val generatorCoroutineImpl = if (continuation.asDynamic().constructor === GeneratorCoroutineImpl::class.js) {
continuation.unsafeCast<GeneratorCoroutineImpl>()
} else {
GeneratorCoroutineImpl(continuation)
}

val iterator = value.unsafeCast<JsIterator<Any?>>()
val value = generator(generatorCoroutineImpl)

if (continuation.asDynamic().constructor !== GeneratorCoroutineImpl::class.js) {
return iterator.next().value
}
if (!isGeneratorSuspendStep(value)) return value

val generatorCoroutineImpl = continuation.unsafeCast<GeneratorCoroutineImpl>()
val iterator = value.unsafeCast<JsIterator<Any?>>()

generatorCoroutineImpl.addNewIterator(iterator)
try {
Expand Down

0 comments on commit ce5d599

Please sign in to comment.