Skip to content

Commit 4f54d9d

Browse files
authored
Ensure consistent delay behavior in immediate across platforms (#4432)
Fixes #4430
1 parent ff489dd commit 4f54d9d

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

kotlinx-coroutines-core/nativeDarwin/src/Dispatchers.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ private class DarwinMainDispatcher(
4646
val timer = Timer()
4747
val timerBlock: TimerBlock = {
4848
timer.dispose()
49-
continuation.resume(Unit)
49+
with(continuation) { resumeUndispatched(Unit) }
5050
}
5151
timer.start(timeMillis, timerBlock)
5252
continuation.disposeOnCancellation(timer)

test-utils/common/src/MainDispatcherTestBase.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package kotlinx.coroutines.testing
22

33
import kotlinx.coroutines.*
4+
import kotlinx.coroutines.channels.*
45
import kotlin.test.*
56

67
abstract class MainDispatcherTestBase: TestBase() {
@@ -151,6 +152,26 @@ abstract class MainDispatcherTestBase: TestBase() {
151152
}
152153
}
153154

155+
/** Tests that [delay] runs the task inline instead of explicitly scheduling it
156+
* (which can be observed by the event loop's ordering). */
157+
@Test
158+
@NoJs @NoWasmWasi @NoWasmJs // This test does not work for environments with a single always-on event loop
159+
fun testUndispatchedAfterDelay() = runTestOrSkip {
160+
launch(Dispatchers.Main.immediate) {
161+
val channel = Channel<Unit>()
162+
expect(1)
163+
launch {
164+
channel.receive()
165+
expect(3)
166+
}
167+
delay(100)
168+
checkIsMainThread()
169+
expect(2)
170+
channel.send(Unit)
171+
finish(4)
172+
}
173+
}
174+
154175
private suspend fun <R> withMainScope(block: suspend CoroutineScope.() -> R): R {
155176
MainScope().apply {
156177
return block().also { coroutineContext[Job]!!.cancelAndJoin() }

0 commit comments

Comments
 (0)