Promise coroutines: await doesn't actualy wait

Hi @Alexey.Andreev,

that’s a totally reasonable response. I was info-dumping after a frustrating few hours last week but, if I got a bug report, I’d be asking for an isolated repeatable case, too :wink:

So, I upgraded to IJ2017.2 EAP and Kotlin plugin, as described here: Trouble with EAP - #2 by HughG 1.1.3-eap-34-IJ2017.2-1. That didn’t make my situation any better, so I cut it down to the following test case. I freely admit that I don’t really know what I’m doing in terms of using coroutines to implement async/await, I’m just copying others’ code, as follows.

package org.tameter.ksandbox

import kotlin.browser.window
import kotlin.coroutines.experimental.*
import kotlin.js.Promise

// From https://youtrack.jetbrains.com/issue/KT-17067
private object JavaScriptContext : AbstractCoroutineContextElement(ContinuationInterceptor.Key), ContinuationInterceptor {
    override fun <T> interceptContinuation(continuation: Continuation<T>) = object : Continuation<T> {
        override val context = continuation.context

        override fun resume(value: T) {
            window.setTimeout({ continuation.resume(value); }, 0)
        }

        override fun resumeWithException(exception: Throwable) {
            window.setTimeout({ continuation.resumeWithException(exception) }, 0)
        }
    }
}

// Also from https://youtrack.jetbrains.com/issue/KT-17067
fun <T> immediateAsync(c: suspend () -> T) {
    c.startCoroutine(object : Continuation<T> {
        override fun resume(value: T) { }

        override fun resumeWithException(exception: Throwable) { throw exception }

        override val context = JavaScriptContext
    })
}

// From https://discuss.kotlinlang.org/t/using-coroutines-to-avoid-callback-hell-when-using-xmlhttprequest/2450/3
fun <T> promiseAsync(c: suspend () -> T): Promise<T> {
    return Promise { resolve, reject ->
        c.startCoroutine(object : Continuation<T> {
            override fun resume(value: T) = resolve(value)

            override fun resumeWithException(exception: Throwable) = reject(exception)

            override val context = EmptyCoroutineContext
        })
    }
}

// Also from https://discuss.kotlinlang.org/t/using-coroutines-to-avoid-callback-hell-when-using-xmlhttprequest/2450/3
// Should work with promiseAsync; maybe doesn't make sense to use it with immediateAsync, I'm not sure.
inline suspend fun <T> Promise<T>.await() = suspendCoroutine<T> { c ->
    then({
        console.log("Resolving with $it")
        c.resume(it)
    }, {
        console.log("Rejecting with $it")
        c.resumeWithException(it)
    })
}

suspend fun <T> promise(value: T): Promise<T> {
    return Promise.resolve(value)
}

fun main(args: Array<String>) {
    promiseAsync {
        console.log("1")
        val a = promise("aardwolf").await()
        console.log(a)
        console.log("2")
    }
}

So, if I run the above code as it stands (in Firefox) I get the following console output.

1  sandbox.js:160:13
Object {  }  sandbox.js:173:13
2  sandbox.js:174:20
Resolving with aardwolf  sandbox.js:113:7

but I was hoping for

1
aardwolf
2

If I have main call immediateAsync I get this:

1  sandbox.js:160:13
Object {  }  sandbox.js:173:13
2  sandbox.js:174:20
Resolving with aardwolf  sandbox.js:113:7
TypeError: this$await.then is not a function[Learn More]  sandbox.js:125:7
	await$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:125:7
	suspendCoroutine$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:29004:7
	sandbox</Coroutine$main$lambda.prototype.doResume file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:171:29
	CoroutineImpl.prototype.doResumeWrapper_0 file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:3164:20
	CoroutineImpl.prototype.resume_11rb$ file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:3153:5
	JavaScriptContext$interceptContinuation$ObjectLiteral$resume$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:30:7

Am I just doing something dumb here, or missing some simple step?