diff --git a/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt b/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt index 786f0f215d..3e3e9a1bdf 100644 --- a/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt @@ -46,7 +46,7 @@ private class DarwinMainDispatcher( val timer = Timer() val timerBlock: TimerBlock = { timer.dispose() - continuation.resume(Unit) + with(continuation) { resumeUndispatched(Unit) } } timer.start(timeMillis, timerBlock) continuation.disposeOnCancellation(timer) diff --git a/test-utils/common/src/MainDispatcherTestBase.kt b/test-utils/common/src/MainDispatcherTestBase.kt index dd867a2d64..e40494d93b 100644 --- a/test-utils/common/src/MainDispatcherTestBase.kt +++ b/test-utils/common/src/MainDispatcherTestBase.kt @@ -1,6 +1,7 @@ package kotlinx.coroutines.testing import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* import kotlin.test.* abstract class MainDispatcherTestBase: TestBase() { @@ -151,6 +152,26 @@ abstract class MainDispatcherTestBase: TestBase() { } } + /** Tests that [delay] runs the task inline instead of explicitly scheduling it + * (which can be observed by the event loop's ordering). */ + @Test + @NoJs @NoWasmWasi @NoWasmJs // This test does not work for environments with a single always-on event loop + fun testUndispatchedAfterDelay() = runTestOrSkip { + launch(Dispatchers.Main.immediate) { + val channel = Channel() + expect(1) + launch { + channel.receive() + expect(3) + } + delay(100) + checkIsMainThread() + expect(2) + channel.send(Unit) + finish(4) + } + } + private suspend fun withMainScope(block: suspend CoroutineScope.() -> R): R { MainScope().apply { return block().also { coroutineContext[Job]!!.cancelAndJoin() }