@@ -7,32 +7,45 @@ package kotlinx.coroutines
7
7
import kotlinx.coroutines.internal.*
8
8
import org.w3c.dom.*
9
9
import kotlin.coroutines.*
10
- import kotlin.js.*
10
+ import kotlin.js.Promise
11
11
12
12
private const val MAX_DELAY = Int .MAX_VALUE .toLong()
13
13
14
14
private fun delayToInt (timeMillis : Long ): Int =
15
15
timeMillis.coerceIn(0 , MAX_DELAY ).toInt()
16
16
17
- internal object NodeDispatcher : CoroutineDispatcher(), Delay {
18
- override fun dispatch (context : CoroutineContext , block : Runnable ) = NodeJsMessageQueue .enqueue(block)
17
+ internal sealed class SetTimeoutBasedDispatcher : CoroutineDispatcher (), Delay {
18
+ override fun invokeOnTimeout (timeMillis : Long , block : Runnable ): DisposableHandle {
19
+ val handle = setTimeout({ block.run () }, delayToInt(timeMillis))
20
+ return ClearTimeout (handle)
21
+ }
19
22
20
23
override fun scheduleResumeAfterDelay (timeMillis : Long , continuation : CancellableContinuation <Unit >) {
21
24
val handle = setTimeout({ with (continuation) { resumeUndispatched(Unit ) } }, delayToInt(timeMillis))
22
25
// Actually on cancellation, but clearTimeout is idempotent
23
26
continuation.invokeOnCancellation(handler = ClearTimeout (handle).asHandler)
24
27
}
28
+ }
29
+
30
+ internal object NodeDispatcher : SetTimeoutBasedDispatcher() {
31
+ override fun dispatch (context : CoroutineContext , block : Runnable ) = NodeJsMessageQueue .enqueue(block)
32
+ }
33
+
34
+ internal object SetTimeoutDispatcher : SetTimeoutBasedDispatcher() {
35
+ override fun dispatch (context : CoroutineContext , block : Runnable ) = SetTimeoutMessageQueue .enqueue(block)
36
+ }
25
37
26
- private class ClearTimeout (private val handle : Int ) : CancelHandler(), DisposableHandle {
27
- override fun dispose () { clearTimeout(handle) }
28
- override fun invoke ( cause : Throwable ? ) { dispose() }
29
- override fun toString (): String = " ClearTimeout[ $ handle] "
38
+ private class ClearTimeout (private val handle : Int ) : CancelHandler(), DisposableHandle {
39
+
40
+ override fun dispose () {
41
+ clearTimeout( handle)
30
42
}
31
43
32
- override fun invokeOnTimeout (timeMillis : Long , block : Runnable ): DisposableHandle {
33
- val handle = setTimeout({ block.run () }, delayToInt(timeMillis))
34
- return ClearTimeout (handle)
44
+ override fun invoke (cause : Throwable ? ) {
45
+ dispose()
35
46
}
47
+
48
+ override fun toString (): String = " ClearTimeout[$handle ]"
36
49
}
37
50
38
51
internal class WindowDispatcher (private val window : Window ) : CoroutineDispatcher(), Delay {
@@ -86,6 +99,16 @@ private object NodeJsMessageQueue : MessageQueue() {
86
99
}
87
100
}
88
101
102
+ private object SetTimeoutMessageQueue : MessageQueue() {
103
+ override fun schedule () = scheduleProcess()
104
+
105
+ override fun reschedule () = scheduleProcess()
106
+
107
+ private fun scheduleProcess () {
108
+ setTimeout({ process() }, 0 )
109
+ }
110
+ }
111
+
89
112
/* *
90
113
* An abstraction over JS scheduling mechanism that leverages micro-batching of [dispatch] blocks without
91
114
* paying the cost of JS callbacks scheduling on every dispatch.
@@ -136,4 +159,3 @@ internal abstract class MessageQueue : ArrayQueue<Runnable>() {
136
159
// using them via "window" (which only works in browser)
137
160
private external fun setTimeout (handler : dynamic , timeout : Int = definedExternally): Int
138
161
private external fun clearTimeout (handle : Int = definedExternally)
139
- private external val process: dynamic
0 commit comments