16
16
17
17
package org .scalajs .macrotaskexecutor
18
18
19
- import scala .collection .mutable
20
19
import scala .concurrent .{ExecutionContext , ExecutionContextExecutor }
21
20
import scala .scalajs .js
21
+ import scala .scalajs .js .annotation ._
22
22
import scala .util .Random
23
23
import scala .util .control .NonFatal
24
24
@@ -29,15 +29,23 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
29
29
private [this ] final val Undefined = " undefined"
30
30
31
31
def execute (runnable : Runnable ): Unit =
32
- setImmediate(() => runnable.run() )
32
+ setImmediate(runnable)
33
33
34
34
def reportFailure (cause : Throwable ): Unit =
35
35
cause.printStackTrace()
36
36
37
- private [this ] val setImmediate : (() => Unit ) => Unit = {
37
+ @ js.native
38
+ private [this ] trait TaskMap extends js.Object {
39
+ @ JSBracketAccess
40
+ def apply (handle : Int ): Runnable
41
+ @ JSBracketAccess
42
+ def update (handle : Int , task : Runnable ): Unit
43
+ }
44
+
45
+ private [this ] val setImmediate : Runnable => Unit = {
38
46
if (js.typeOf(js.Dynamic .global.setImmediate) == Undefined ) {
39
47
var nextHandle = 1
40
- val tasksByHandle = mutable. Map [ Int , () => Unit ]()
48
+ val tasksByHandle = ( new js. Object ). asInstanceOf [ TaskMap ]
41
49
var currentlyRunningATask = false
42
50
43
51
def canUsePostMessage (): Boolean = {
@@ -63,21 +71,17 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
63
71
}
64
72
}
65
73
66
- def runIfPresent (handle : Int ): Unit = {
74
+ def runTaskForHandle (handle : Int ): Unit = {
67
75
if (currentlyRunningATask) {
68
- js.Dynamic .global.setTimeout(() => runIfPresent (handle), 0 )
76
+ js.Dynamic .global.setTimeout(() => runTaskForHandle (handle), 0 )
69
77
} else {
70
- tasksByHandle.get(handle) match {
71
- case Some (task) =>
72
- currentlyRunningATask = true
73
- try {
74
- task()
75
- } finally {
76
- tasksByHandle -= handle
77
- currentlyRunningATask = false
78
- }
79
-
80
- case None =>
78
+ val task = tasksByHandle(handle)
79
+ currentlyRunningATask = true
80
+ try {
81
+ task.run()
82
+ } finally {
83
+ js.special.delete(tasksByHandle, handle)
84
+ currentlyRunningATask = false
81
85
}
82
86
}
83
87
@@ -95,7 +99,7 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
95
99
js.Dynamic .global.Node .constructor(" return setImmediate" )()
96
100
97
101
{ k =>
98
- setImmediate(k )
102
+ setImmediate(() => k.run() )
99
103
()
100
104
}
101
105
} else if (canUsePostMessage()) {
@@ -115,7 +119,7 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
115
119
.data
116
120
.indexOf(messagePrefix)
117
121
.asInstanceOf [Int ] == 0 ) {
118
- runIfPresent (event.data.toString.substring(messagePrefix.length).toInt)
122
+ runTaskForHandle (event.data.toString.substring(messagePrefix.length).toInt)
119
123
}
120
124
}
121
125
@@ -129,22 +133,22 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
129
133
val handle = nextHandle
130
134
nextHandle += 1
131
135
132
- tasksByHandle += (handle -> k)
136
+ tasksByHandle(handle) = k
133
137
js.Dynamic .global.postMessage(messagePrefix + handle, " *" )
134
138
()
135
139
}
136
140
} else if (js.typeOf(js.Dynamic .global.MessageChannel ) != Undefined ) {
137
141
val channel = js.Dynamic .newInstance(js.Dynamic .global.MessageChannel )()
138
142
139
143
channel.port1.onmessage = { (event : js.Dynamic ) =>
140
- runIfPresent (event.data.asInstanceOf [Int ])
144
+ runTaskForHandle (event.data.asInstanceOf [Int ])
141
145
}
142
146
143
147
{ k =>
144
148
val handle = nextHandle
145
149
nextHandle += 1
146
150
147
- tasksByHandle += (handle -> k)
151
+ tasksByHandle(handle) = k
148
152
channel.port2.postMessage(handle)
149
153
()
150
154
}
@@ -153,13 +157,13 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
153
157
// we're also not going to bother fast-pathing for IE6; just fall through
154
158
155
159
{ k =>
156
- js.Dynamic .global.setTimeout(k , 0 )
160
+ js.Dynamic .global.setTimeout(() => k.run() , 0 )
157
161
()
158
162
}
159
163
}
160
164
} else {
161
165
{ k =>
162
- js.Dynamic .global.setImmediate(k )
166
+ js.Dynamic .global.setImmediate(() => k.run() )
163
167
()
164
168
}
165
169
}
0 commit comments