Skip to content

Commit 392d0a7

Browse files
authored
Scala.js: Add JS-specific version of VarArgsBuilder. (#24144)
It follows the model of regular varargs, which also use a `linkTimeIf`-based dispatch in `scala.scalajs.runtime.to*VarArgs`. See https://github.com/scala-js/scala-js/blob/4d538a13a81ff04258a0af8568daa60f83e82b13/library/src/main/scala/scala/scalajs/runtime/package.scala#L31-L87 for context in scala-js/scala-js.
2 parents dfb29d5 + 2994233 commit 392d0a7

File tree

2 files changed

+302
-0
lines changed

2 files changed

+302
-0
lines changed
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package scala.runtime
2+
3+
import scala.collection.immutable.ArraySeq
4+
import scala.reflect.ClassTag
5+
6+
import scala.scalajs.js
7+
import scala.scalajs.runtime.toScalaVarArgs
8+
import scala.scalajs.LinkingInfo.{isWebAssembly, linkTimeIf}
9+
10+
sealed abstract class VarArgsBuilder[T]:
11+
def add(elem: T): this.type
12+
def addSeq(elems: Seq[T]): this.type
13+
def addArray(elems: Array[T]): this.type
14+
def result(): Seq[T]
15+
16+
object VarArgsBuilder:
17+
18+
@inline
19+
private final class JSVarArgsBuilder[T] extends VarArgsBuilder[T]:
20+
private val array: js.Array[T] = js.Array()
21+
def add(elem: T): this.type =
22+
array.push(elem)
23+
this
24+
def addSeq(elems: Seq[T]): this.type =
25+
for elem <- elems do
26+
add(elem)
27+
this
28+
def addArray(elems: Array[T]): this.type =
29+
for elem <- elems do
30+
add(elem)
31+
this
32+
def result(): Seq[T] =
33+
toScalaVarArgs(array)
34+
35+
@inline
36+
def generic[T](n: Int): VarArgsBuilder[T] =
37+
linkTimeIf[VarArgsBuilder[T]](isWebAssembly)(GenericVarArgsBuilder(n))(JSVarArgsBuilder())
38+
39+
@inline
40+
private final class GenericVarArgsBuilder[T](n: Int) extends VarArgsBuilder[T]:
41+
private val xs = new Array[AnyRef](n)
42+
def result(): Seq[T] = ArraySeq.ofRef(xs).asInstanceOf[ArraySeq[T]]
43+
private var i = 0
44+
def add(elem: T): this.type =
45+
xs(i) = elem.asInstanceOf[AnyRef]
46+
i += 1
47+
this
48+
def addSeq(elems: Seq[T]): this.type =
49+
for elem <- elems do
50+
xs(i) = elem.asInstanceOf[AnyRef]
51+
i += 1
52+
this
53+
def addArray(elems: Array[T]): this.type =
54+
for elem <- elems do
55+
xs(i) = elem.asInstanceOf[AnyRef]
56+
i += 1
57+
this
58+
59+
def ofRef[T <: AnyRef](n: Int): VarArgsBuilder[T] =
60+
linkTimeIf[VarArgsBuilder[T]](isWebAssembly)(RefVarArgsBuilder(n))(JSVarArgsBuilder())
61+
62+
@inline
63+
private final class RefVarArgsBuilder[T <: AnyRef](n: Int) extends VarArgsBuilder[T]:
64+
private val xs = new Array[AnyRef](n)
65+
def result(): Seq[T] = ArraySeq.ofRef(xs).asInstanceOf[ArraySeq[T]]
66+
private var i = 0
67+
def add(elem: T): this.type =
68+
xs(i) = elem
69+
i += 1
70+
this
71+
def addSeq(elems: Seq[T]): this.type =
72+
for elem <- elems do
73+
xs(i) = elem
74+
i += 1
75+
this
76+
def addArray(elems: Array[T]): this.type =
77+
for elem <- elems do
78+
xs(i) = elem
79+
i += 1
80+
this
81+
82+
def ofByte(n: Int): VarArgsBuilder[Byte] =
83+
linkTimeIf[VarArgsBuilder[Byte]](isWebAssembly)(ByteVarArgsBuilder(n))(JSVarArgsBuilder())
84+
85+
@inline
86+
private final class ByteVarArgsBuilder(n: Int) extends VarArgsBuilder[Byte]:
87+
private val xs = new Array[Byte](n)
88+
def result(): Seq[Byte] = ArraySeq.ofByte(xs)
89+
private var i = 0
90+
def add(elem: Byte): this.type =
91+
xs(i) = elem
92+
i += 1
93+
this
94+
def addSeq(elems: Seq[Byte]): this.type =
95+
for elem <- elems do
96+
xs(i) = elem
97+
i += 1
98+
this
99+
def addArray(elems: Array[Byte]): this.type =
100+
for elem <- elems do
101+
xs(i) = elem
102+
i += 1
103+
this
104+
105+
def ofShort(n: Int): VarArgsBuilder[Short] =
106+
linkTimeIf[VarArgsBuilder[Short]](isWebAssembly)(ShortVarArgsBuilder(n))(JSVarArgsBuilder())
107+
108+
@inline
109+
private final class ShortVarArgsBuilder(n: Int) extends VarArgsBuilder[Short]:
110+
private val xs = new Array[Short](n)
111+
def result(): Seq[Short] = ArraySeq.ofShort(xs)
112+
private var i = 0
113+
def add(elem: Short): this.type =
114+
xs(i) = elem
115+
i += 1
116+
this
117+
def addSeq(elems: Seq[Short]): this.type =
118+
for elem <- elems do
119+
xs(i) = elem
120+
i += 1
121+
this
122+
def addArray(elems: Array[Short]): this.type =
123+
for elem <- elems do
124+
xs(i) = elem
125+
i += 1
126+
this
127+
128+
def ofChar(n: Int): VarArgsBuilder[Char] =
129+
linkTimeIf[VarArgsBuilder[Char]](isWebAssembly)(CharVarArgsBuilder(n))(JSVarArgsBuilder())
130+
131+
@inline
132+
private final class CharVarArgsBuilder(n: Int) extends VarArgsBuilder[Char]:
133+
private val xs = new Array[Char](n)
134+
def result(): Seq[Char] = ArraySeq.ofChar(xs)
135+
private var i = 0
136+
def add(elem: Char): this.type =
137+
xs(i) = elem
138+
i += 1
139+
this
140+
def addSeq(elems: Seq[Char]): this.type =
141+
for elem <- elems do
142+
xs(i) = elem
143+
i += 1
144+
this
145+
def addArray(elems: Array[Char]): this.type =
146+
for elem <- elems do
147+
xs(i) = elem
148+
i += 1
149+
this
150+
151+
def ofInt(n: Int): VarArgsBuilder[Int] =
152+
linkTimeIf[VarArgsBuilder[Int]](isWebAssembly)(IntVarArgsBuilder(n))(JSVarArgsBuilder())
153+
154+
@inline
155+
private final class IntVarArgsBuilder(n: Int) extends VarArgsBuilder[Int]:
156+
private val xs = new Array[Int](n)
157+
def result(): Seq[Int] = ArraySeq.ofInt(xs)
158+
private var i = 0
159+
def add(elem: Int): this.type =
160+
xs(i) = elem
161+
i += 1
162+
this
163+
def addSeq(elems: Seq[Int]): this.type =
164+
for elem <- elems do
165+
xs(i) = elem
166+
i += 1
167+
this
168+
def addArray(elems: Array[Int]): this.type =
169+
for elem <- elems do
170+
xs(i) = elem
171+
i += 1
172+
this
173+
174+
def ofLong(n: Int): VarArgsBuilder[Long] =
175+
linkTimeIf[VarArgsBuilder[Long]](isWebAssembly)(LongVarArgsBuilder(n))(JSVarArgsBuilder())
176+
177+
@inline
178+
private final class LongVarArgsBuilder(n: Int) extends VarArgsBuilder[Long]:
179+
private val xs = new Array[Long](n)
180+
def result(): Seq[Long] = ArraySeq.ofLong(xs)
181+
private var i = 0
182+
def add(elem: Long): this.type =
183+
xs(i) = elem
184+
i += 1
185+
this
186+
def addSeq(elems: Seq[Long]): this.type =
187+
for elem <- elems do
188+
xs(i) = elem
189+
i += 1
190+
this
191+
def addArray(elems: Array[Long]): this.type =
192+
for elem <- elems do
193+
xs(i) = elem
194+
i += 1
195+
this
196+
197+
def ofFloat(n: Int): VarArgsBuilder[Float] =
198+
linkTimeIf[VarArgsBuilder[Float]](isWebAssembly)(FloatVarArgsBuilder(n))(JSVarArgsBuilder())
199+
200+
@inline
201+
private final class FloatVarArgsBuilder(n: Int) extends VarArgsBuilder[Float]:
202+
private val xs = new Array[Float](n)
203+
def result(): Seq[Float] = ArraySeq.ofFloat(xs)
204+
private var i = 0
205+
def add(elem: Float): this.type =
206+
xs(i) = elem
207+
i += 1
208+
this
209+
def addSeq(elems: Seq[Float]): this.type =
210+
for elem <- elems do
211+
xs(i) = elem
212+
i += 1
213+
this
214+
def addArray(elems: Array[Float]): this.type =
215+
for elem <- elems do
216+
xs(i) = elem
217+
i += 1
218+
this
219+
220+
def ofDouble(n: Int): VarArgsBuilder[Double] =
221+
linkTimeIf[VarArgsBuilder[Double]](isWebAssembly)(DoubleVarArgsBuilder(n))(JSVarArgsBuilder())
222+
223+
@inline
224+
private final class DoubleVarArgsBuilder(n: Int) extends VarArgsBuilder[Double]:
225+
private val xs = new Array[Double](n)
226+
def result(): Seq[Double] = ArraySeq.ofDouble(xs)
227+
private var i = 0
228+
def add(elem: Double): this.type =
229+
xs(i) = elem
230+
i += 1
231+
this
232+
def addSeq(elems: Seq[Double]): this.type =
233+
for elem <- elems do
234+
xs(i) = elem
235+
i += 1
236+
this
237+
def addArray(elems: Array[Double]): this.type =
238+
for elem <- elems do
239+
xs(i) = elem
240+
i += 1
241+
this
242+
243+
def ofBoolean(n: Int): VarArgsBuilder[Boolean] =
244+
linkTimeIf[VarArgsBuilder[Boolean]](isWebAssembly)(BooleanVarArgsBuilder(n))(JSVarArgsBuilder())
245+
246+
@inline
247+
private final class BooleanVarArgsBuilder(n: Int) extends VarArgsBuilder[Boolean]:
248+
private val xs = new Array[Boolean](n)
249+
def result(): Seq[Boolean] = ArraySeq.ofBoolean(xs)
250+
private var i = 0
251+
def add(elem: Boolean): this.type =
252+
xs(i) = elem
253+
i += 1
254+
this
255+
def addSeq(elems: Seq[Boolean]): this.type =
256+
for elem <- elems do
257+
xs(i) = elem
258+
i += 1
259+
this
260+
def addArray(elems: Array[Boolean]): this.type =
261+
for elem <- elems do
262+
xs(i) = elem
263+
i += 1
264+
this
265+
266+
def ofUnit(n: Int): VarArgsBuilder[Unit] =
267+
linkTimeIf[VarArgsBuilder[Unit]](isWebAssembly)(UnitVarArgsBuilder(n))(JSVarArgsBuilder())
268+
269+
@inline
270+
private final class UnitVarArgsBuilder(n: Int) extends VarArgsBuilder[Unit]:
271+
private val xs = new Array[Unit](n)
272+
def result(): Seq[Unit] = ArraySeq.ofUnit(xs)
273+
private var i = 0
274+
def add(elem: Unit): this.type =
275+
xs(i) = elem
276+
i += 1
277+
this
278+
def addSeq(elems: Seq[Unit]): this.type =
279+
for elem <- elems do
280+
xs(i) = elem
281+
i += 1
282+
this
283+
def addArray(elems: Array[Unit]): this.type =
284+
for elem <- elems do
285+
xs(i) = elem
286+
i += 1
287+
this
288+
289+
end VarArgsBuilder

tests/run/spreads.scala-js.check

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
ArraySeq(1, 2, 3)
2+
ArraySeq(1, 2, 3)
3+
WrappedVarArgs(1, 2, 1, 2, 3)
4+
WrappedVarArgs(1, 2, 1, 2, 3)
5+
WrappedVarArgs(1, 1, 2, 3, 2)
6+
WrappedVarArgs(1, 1, 2, 3, 2, 1, 2, 3, 3)
7+
WrappedVarArgs(1, 1, 2, 3, true, A, false)
8+
WrappedVarArgs(1, 1, 2, 3, 2)
9+
one
10+
one-two-three
11+
two
12+
WrappedVarArgs(1, 1, 2, 3, 2)
13+
13.5

0 commit comments

Comments
 (0)