1616
1717package org .scalajs .macrotaskexecutor
1818
19- import scala .collection .mutable
2019import scala .concurrent .{ExecutionContext , ExecutionContextExecutor }
2120import scala .scalajs .js
21+ import scala .scalajs .js .annotation ._
2222import scala .util .Random
2323import scala .util .control .NonFatal
2424
@@ -29,15 +29,23 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
2929 private [this ] final val Undefined = " undefined"
3030
3131 def execute (runnable : Runnable ): Unit =
32- setImmediate(() => runnable.run() )
32+ setImmediate(runnable)
3333
3434 def reportFailure (cause : Throwable ): Unit =
3535 cause.printStackTrace()
3636
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 = {
3846 if (js.typeOf(js.Dynamic .global.setImmediate) == Undefined ) {
3947 var nextHandle = 1
40- val tasksByHandle = mutable. Map [ Int , () => Unit ]()
48+ val tasksByHandle = ( new js. Object ). asInstanceOf [ TaskMap ]
4149 var currentlyRunningATask = false
4250
4351 def canUsePostMessage (): Boolean = {
@@ -63,21 +71,17 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
6371 }
6472 }
6573
66- def runIfPresent (handle : Int ): Unit = {
74+ def runTaskForHandle (handle : Int ): Unit = {
6775 if (currentlyRunningATask) {
68- js.Dynamic .global.setTimeout(() => runIfPresent (handle), 0 )
76+ js.Dynamic .global.setTimeout(() => runTaskForHandle (handle), 0 )
6977 } 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
8185 }
8286 }
8387
@@ -95,7 +99,7 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
9599 js.Dynamic .global.Node .constructor(" return setImmediate" )()
96100
97101 { k =>
98- setImmediate(k )
102+ setImmediate(() => k.run() )
99103 ()
100104 }
101105 } else if (canUsePostMessage()) {
@@ -115,7 +119,7 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
115119 .data
116120 .indexOf(messagePrefix)
117121 .asInstanceOf [Int ] == 0 ) {
118- runIfPresent (event.data.toString.substring(messagePrefix.length).toInt)
122+ runTaskForHandle (event.data.toString.substring(messagePrefix.length).toInt)
119123 }
120124 }
121125
@@ -129,22 +133,22 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
129133 val handle = nextHandle
130134 nextHandle += 1
131135
132- tasksByHandle += (handle -> k)
136+ tasksByHandle(handle) = k
133137 js.Dynamic .global.postMessage(messagePrefix + handle, " *" )
134138 ()
135139 }
136140 } else if (js.typeOf(js.Dynamic .global.MessageChannel ) != Undefined ) {
137141 val channel = js.Dynamic .newInstance(js.Dynamic .global.MessageChannel )()
138142
139143 channel.port1.onmessage = { (event : js.Dynamic ) =>
140- runIfPresent (event.data.asInstanceOf [Int ])
144+ runTaskForHandle (event.data.asInstanceOf [Int ])
141145 }
142146
143147 { k =>
144148 val handle = nextHandle
145149 nextHandle += 1
146150
147- tasksByHandle += (handle -> k)
151+ tasksByHandle(handle) = k
148152 channel.port2.postMessage(handle)
149153 ()
150154 }
@@ -153,13 +157,13 @@ object MacrotaskExecutor extends ExecutionContextExecutor {
153157 // we're also not going to bother fast-pathing for IE6; just fall through
154158
155159 { k =>
156- js.Dynamic .global.setTimeout(k , 0 )
160+ js.Dynamic .global.setTimeout(() => k.run() , 0 )
157161 ()
158162 }
159163 }
160164 } else {
161165 { k =>
162- js.Dynamic .global.setImmediate(k )
166+ js.Dynamic .global.setImmediate(() => k.run() )
163167 ()
164168 }
165169 }
0 commit comments