From 8f6563b10d439b297765d6392e5e66e0bac13e6f Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Wed, 7 May 2025 11:42:53 +0200 Subject: [PATCH 1/2] Ensure consistent `delay` behavior in `immediate` across platforms Fixes #4430 --- .../nativeDarwin/src/Dispatchers.kt | 2 +- .../common/src/MainDispatcherTestBase.kt | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) 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..7047797638 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,25 @@ 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 + 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() } From a3836bb846f086782aa4a093b9cd685123f7d9ab Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Wed, 7 May 2025 15:06:03 +0200 Subject: [PATCH 2/2] Disable the new test for the JS main dispatcher --- test-utils/common/src/MainDispatcherTestBase.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/test-utils/common/src/MainDispatcherTestBase.kt b/test-utils/common/src/MainDispatcherTestBase.kt index 7047797638..e40494d93b 100644 --- a/test-utils/common/src/MainDispatcherTestBase.kt +++ b/test-utils/common/src/MainDispatcherTestBase.kt @@ -155,6 +155,7 @@ 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()