Skip to content

Commit cf9d18f

Browse files
authored
Merge pull request #128 from armanbilge/optimize-allocation
Optimize allocations
2 parents 0e3c00b + af120b0 commit cf9d18f

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

core/src/main/scala/org/scalajs/macrotaskexecutor/MacrotaskExecutor.scala

+28-24
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
package org.scalajs.macrotaskexecutor
1818

19-
import scala.collection.mutable
2019
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
2120
import scala.scalajs.js
21+
import scala.scalajs.js.annotation._
2222
import scala.util.Random
2323
import 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

Comments
 (0)